WPF image control and jpg rotation metadata - c#

I am having some trouble with Image control in WPF.
I have one jpg file, which loads with wrong rotation and even i rotate this picture in windows (right click and rotate left/right) there is no change in application.
Seems that there are some EXIF metadata in the image, which gets rotated together with a wrong image.
I'm reading the image from www so I do not have local file (and I don't want to have it). Here's how I'm converting byte[] to BitmapImage:
public static BitmapImage BitmapImageFromByteArray(Byte[] bytes)
{
MemoryStream stream = new MemoryStream(bytes);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = stream;
image.EndInit();
stream.Close();
stream.Dispose();
return image;
}
So there are 2 ways of handling that:
Set Image control to ignore EXIF metadata
Remove EXIF metadata from BitmapImage
Can you help me with handling any of these?

Check out the code sample on the following link.
Remove Exif data from image files with C# and WPF libraries: http://www.techmikael.com/2009/07/remove-exif-data-from-image-files-with.html
Another option may be to use a RotateTransform to rotate the Image element:
How to do rotation around control's center in XAML

Related

Saved png image lose transparency when inserted in Catia V5 CATDrawing

I have a problem with transparency in the .png image when inserting to Catia V5 CATDrawing document. Something changes in the image after saving with System.Drawing.Image.Save(). If a newly saved image is opened with Paint.NET image is transparent and everything seems fine, but when inserted in CATDrawing image has no transparency. I can't find out what is changed in the image to cause this loss of transparency.
I'm rotating image that's why I need to save it. This is the code I'm using to rotate and save images.
Bitmap image1 = (Bitmap)Image.FromFile(sImagePath1, true);
image1.RotateFlip(RotateFlipType.Rotate90FlipNone);
image1.MakeTransparent();
image1.Save(sImagePath2, ImageFormat.Png);
I have also tried and failed with NuGet package Magick.NET-Q16-AnyCPU
using (MagickImage mimg = new(sImagePath1))
{
mimg.Rotate(90);
mimg.Write(sImagePath2);
}
and with save as stream
Bitmap image1 = (Bitmap)Image.FromFile(sImagePath1, true);
image1.RotateFlip(RotateFlipType.Rotate90FlipNone);
using (FileStream outputFileStream = new(sImagePath2, FileMode.Create))
{
var stream = new MemoryStream();
image1.Save(stream, ImageFormat.Png);
stream.Position = 0;
stream.CopyTo(outputFileStream);
}
Question: is there any other solution to rotate and save images via C# code?
Hi I'm afraid that Catia V5 can't import png with transparency. Try it yourself if manually putting the image into drawing keeps transparency. I Tried it but in my case it doesn't work.
In Catia you can rotate the picture manually but not trough api.
You can try vector image instead of bitmap, but this is just my guess.

.NET C# - Both Bitmap and Image Loads Images Smaller than Expected

I'm trying to process the typical 16 megapixel images from a modern camera. Picking a random image, both the file system and my image editing software says the image is 4608 x 3456. When I load the image in C# (VS2013 .Net 4.5) using either new Bitmap(filename) or Image.FromFile(filename), I get an image successfully loaded. However, the resulting image has a size of 1613 x 1210. Now, in some cases I want to create custom size thumbnails, and this will work ok. However, I have another need where I detect "non normal" orientations and I simply want to flip/rotate for display, then save.
Saving these images (without any adjustments, just load and save) creates a valid image on disk. However, both the file system AND my image tool says the size is 1613 x 1210.
How do I load the full size image and preserve all info back to disk? Any ideas as to what I'm doing wrong? I just want to rotate the image where needed, I don't want to shrink it!
Here's a snippet of what I tried, as promised in a comment below:
Bitmap bm = new Bitmap(fileName);
Image jpg = Image.FromFile(fileName);
jpg.Save("e:\\test.jpg");
bm.Save("e:\\test2.jpg");
Both files are smaller than their original size, and match the width and height the debugger shows for both in-memory images.
Per a suggested answer, I tried this code but saw no difference in the results:
long width = 0;
long height = 0;
byte[] imageBytes = File.ReadAllBytes(fileName);
using (MemoryStream ms = new MemoryStream(imageBytes))
{
Image jpg3 = Image.FromStream(ms);
width = jpg3.Width;
height = jpg3.Height;
jpg3.Save("e:\\test3.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
}
Thanks in advance.
[EDIT]
User Error from a followup post:
While it's true I do have a 4608x3456 size image of the very picture I
am trying to load, I selected the wrong directory in my OpenFileDialog
and was actually selected a, you guessed it, 1613 x 1210 version of
this image. The code WAS loading the full thing, the silly operator
(me) was gumming it up.
Before I post, I'll try the full-size image ... yeah, it works fine.
Can you show your program code?
I downloaded 5169x3423 size sample image.
Load this image using program and when i restored it, original and new image are same.
I load image file to byte array and save it to Bitmap.
private Image LoadImage()
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.ShowDialog();
byte[] byteImage = File.ReadAllBytes(openFile.FileName);
Image myImage;
using (var ms = new MemoryStream(byteImage))
{
myImage = Image.FromStream(ms);
}
return myImage;
}
private void SaveImage(Image myImage)
{
Bitmap bmp = new Bitmap(myImage);
// Temp save location
bmp.Save("c:\\test\\myImage.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}

System.Drawing.Image from ImageSource in Resources

My question is very similar to this one: wpf image resources and changing image in wpf control at runtime, but with a slight twist.
Here is my ResourceDictionary.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ImageSource x:Key="DisconnectedIcon">Images/disconnect.png</ImageSource>
<ImageSource x:Key="Synced">Images/tick.png</ImageSource>
<ImageSource x:Key="NotSynced">Images/x.png</ImageSource>
As for the C# code behind, I am able to load the ImageSource from the resources with the following. In which, I am able to see the metadata and the image name, but can't figure out how to get it into a System.Drawings.Image.
var imageSource = (ImageSource)Application.Current.FindResource("Synced");
System.Drawing.Image img = Image.FromFile(???)
The reason I am trying to convert it to a System.Drawing.Image is to send it to a printer.
Thanks!
In WPF, every UI element extends the Visual Class which Provides rendering support in WPF. There is also a RenderTargetBitmap Class that has a Render Method that takes a Visual object as an input parameter. So you could set your ImageSource as the Source property of an Image and simply render the Image to a Bitmap image:
Image yourImageObject = new Image();
yourImageObject.Source = yourImageSource;
RenderTargetBitmap renderTargetBitmap =
new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
renderTargetBitmap.Render(yourImageObject);
// Save to .png file
PngBitmapEncoder pngBitmapEncoder = new PngBitmapEncoder();
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream stream = File.Create(filepath))
{
pngBitmapEncoder.Save(stream);
}
As this is well documented on the internet, I won't bother to repeat the whole story here. To find out the full story, please see the How to Render Bitmap or to Print a Visual in WPF page from the Dot NET Tricks website, which will also help you with your printing requirement.

IO.Stream to Image in WPF

I am trying to read an image from a resource only DLL file. I am able to read the image name and image bytes, but How do I set the Image control to stream buffer? In windows form, I know I can use this :
pictureBox1.Image=new System.Drawing.Bitmap(IOStream);
since there is no Drawing namespace in wpf, how can I achieve the same thing?
In WPF, you can set the Source property of an Image, as in this example:
Image image = new Image();
using (MemoryStream stream = new MemoryStream(byteArray))
{
image.Source = BitmapFrame.Create(stream,
BitmapCreateOptions.None,
BitmapCacheOption.OnLoad);
}
Where byteArray is the array of bytes with the source of the image.
In WPF you probably have an Image element in your xaml. The Source can be any BitmapImage. You can bind a BitmapImage from your ViewModel, where you can create an instance from a Stream like this.

Getting a particular Portion of Image (Picture)

I want to cut the the specific portion of the the picture and use it to compare the cropped image with another stored in the HDD. The problem is that I don't know how to get a specific section of the source image. I know the location (X,Y) of the image to be cropped.
This will load the original and create a cropped version starting at (0,0) and with dimensions of 64x64.
Bitmap original = new Bitmap( #"C:\SomePath" );
Rectangle srcRect = new Rectangle( 0, 0, 64, 64 );
Bitmap cropped = (Bitmap)original.Clone( srcRect, original.PixelFormat );
BTW, you don't specify if this is WinForms or WPF, so going with WinForms as I don't really know WPF image manipulation functions.
For those who need to use the cropped image for their website within img-tag , you need some more code (just advicing, because i needed it myself)
Take the code above plus this:
byte[] imgbytes;
using (MemoryStream stream = new MemoryStream())
{
cropped.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
imgbytes = stream.ToArray();
}
<img src="#String.Format("data:image/png;base64,{0}", Convert.ToBase64String(imgbytes))" />

Categories