How to get the image format of a BitmapImage? - c#

I have a WPF application with an Image element whose source is bound to a property of type BitmapImage. I need to save this image into our database along with it's format (jpg, tif, basically I'm trying to use the ImageFormat class). How can I get the format of the BitmapImage?

The Image is a control that displays a BitmapImage. There is no meaning to save the Image. You want to save the bitmapImage (the image.Source). Also you should not care of the original encoding/decoding of the bitmapImage. This has to do with the data compression in the file on the disk. Now the thing is in memory as BitmapImage with no compression. You have to decide of the encoding method of your local file. For .jpg you have to run the following code :
BitmapEncoder bme = new JpegBitmapEncoder();
bme.Frames.Add(BitmapFrame.Create(image.Source));
using (var filestream = new System.IO.FileStream("temp.jpg", System.IO.FileMode.Create))
{
bme.Save(fileStream);
}

How can I get the format of the BitmapImage?
You can't, because it does not have a fixed format.
You may use any of the classed derived from BitmapEncoder to encode a BitmapSource. The format is then determined by the BitmapEncoder that is actually used, e.g. PNG when you use PngBitmapEncoder.

Related

Converting byte array to image and back again does not return the same array

I have two c# functions that convert byte[] to images and back. I thought that the two functions would be exactly reversible:
public static byte[] ImageToByte(System.Drawing.Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
return imageBytes;
}
}
public static Image ByteToImage(byte[] imageBytes)
{
using (MemoryStream ms = new MemoryStream())
{
ms.Write(imageBytes, 0, imageBytes.Length);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
}
However, if i look at the original byte array and then converted/reconverted array they are different (different lengths). I am not clear why? I would like to be able to tell if the image has been modified in my app so need to be able to compare the image array before and after.
Thanks
There is no reason to expect that both functions are reversible to get identical byte data, unless you choose an image format that does not use compression schemes controlled by variable parameters (like PNG or JPG, for example) and does not feature metadata fields that can change without altering the pixel data (like bytes 6...9 in a BMP format header, for example), or are not maintained by the infrastructure underlying System.Drawing.Image.
Instead of trying to compare the raw byte data (which can be variable depending on the image file format being used), compare the actual pixel data. In other words, load both your "before" image and "after" image into System.Drawing.Image instances, and then compare the pixel data of both images. Make sure both image instances use the same pixel format before you compare the pixel data. (Use the widest pixel format available like 64bppArgb to avoid potential reduction of the color space of the images loaded, which otherwise could spoil your efforts.) Also make sure that you don't use a "lossy" format like JPEG for your "before" and "after" pictures, otherwise the simple act of uncompressing/decoding and re-compressing/encoding of the image might change the actual pixel data.

C# Bitmap.Save Method , JPEG

Im creating a new Bitmap object as below,
var image = new Bitmap(#"C:\file.jpg");
I will be doing several modifications in pixel levels in the spatial domain and if save this object again as below.
image.Save(#"D:\final.jpg", ImageFormat.bitmap);
Is this final image is a really a jpg or a bitmap ? ,
Using this functional is there a way we can save a jpg lossless ?
image.Save(#"D:\final.jpg", ImageFormat.Bmp);
will save a bitmap image in spite of the extension
Jpg is a lossy compression method, if you want loseless you can use either Bmp or Png
The Bitmap class is always in a 'raw' format. So what happens in your code is:
Read from a JPEG file (lossy format) into a Bitmap class (raw lossless format).
Save the contents of the Bitmap class into another file (BMP lossless format).
The contents of the Bitmap class after that is still in raw lossless format so that you can continue to manipulate it, or save it to file in yet another format (lossless or lossy).
Note: The 'raw' format I mentioned above is not the same format as some .raw files that you sometimes encounter in music editing programs. By 'raw' format I just mean some temporary arbitrary format that Bitmap uses to store the image data in itself (possibly in byte[]).

Is there a way to keep a png/jpg image from being converted to a bitmap image

I'm making a C#/WPF/Windows 8 App store app and I'm trying to load up some PNGs/JPGs to display them in view. The images are all reasonably high resolution, but the file sizes are normally only around 200k or so. The problem is that when I load them up using the BitmapImage class (which is the only one I can find) the total memory used jumps up to 100s of megs. From what I can tell it takes the png/jpb and converts it to a bitmap image, which massively increases the memory usage. So far I haven't found a way around this, although it seems like there should be a simple solution.
Is there something really obvious I'm missing?
My code below
private async Task TestFunction(IReadOnlyList<StorageFile> files)
{
var images = new ObservableCollection<Image>();
imagePanel.ItemsSource = coverImages;
foreach (var file in files)
{
var bitmap = new BitmapImage();
var item = await file.OpenAsync(FileAccessMode.Read);
bitmap.SetSource(item);
var image = new Image();
image.Source = bitmap;
image.Height = 200;
images.Add(image);
}
}
If the image on disk is in compressed format (and most image file formats use some form of compression), the in-memory footprint will be larger.
If the image is 100x100 pixels in size and uses 8bits for colour depth, the raw data for that image would take up 100x100=10,000 bytes and that's the amount of data that has to be rendered to the screen.
If your looking for a way to reduce memorty usage in your WPF application there are a few option you can try.
Don't cache the images in memory, or selecting the best time to
load the images, using the BitmapCacheOption e.g: bitmap.CacheOption = BitmapCacheOption.None
this will fill the image as needed from disk, if the images are only 200k the performance drop should not be too bad, but it will not be as fast as caching
Make sure you not rendering images bigger than they need to be, If
the Element you are displaying the image on is 200x200 and the image
is 1024x768 you can set the DecodePixelWidth, this will create the
Bitmap to the size you define instead of its actual size.
e.g: bitmap.DecodePixelWidth = 200
PNG, JPG and all other forms of image compression are useful for storage only. In order to display compressed image content in WPF you have to decompress it to Bitmap which is a raw one-to-one representation of the image data.
If you were not to store decompressed image data in memory, then every time the system tried to reference the image for display it would have to decompress the image again, using precious CPU resources. In the case of popular formats like PNG or JPG, the compression and decompression process is rather complex.
There are image compression formats out there which are designed for dynamic decompression. These formats, such as DXT1-5, however are typically only supported by 3D libraries. (more info here)

Managing Images?

I'm working on a class that will help me read a game file, and part of the file is an image. Is there an image object that I can create from a byte array, or should I just store the image as a byte array? If I were to put that image into a picture displayer in winforms, can I do that with a byte array?
What's the best way to store the data from the file?
like this:
byte[] data = getYourImageData();
MemoryStream ms = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(ms);
to answer the other part of your question, it is fine to store it as a byte array - maybe provide a helper method that returns a memory stream as seen above, or alternatively store it in a System.Drawing.Bitmap and return that:
return new Bitmap(ms);
The Bitmap class in System.Drawing supports a constructor that takes a stream as a parameter. This stream can be supplied by a MemoryStream that is created from a byte array.
Once you have the bitmap, a PictureBox can be used to display it.
References:
http://msdn.microsoft.com/en-us/library/z7ha67kw.aspx (for the bitmap)
http://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx (for the stream)
http://msdn.microsoft.com/en-us/library/system.windows.forms.picturebox.aspx (PictureBox)

Can bitmap object be save as PNG or JPEG file format

Is C# bitmap supporting saving the object to JPEG or PNG file format?
Bitmap extends Image, therefore you can call: Image.Save (String, ImageFormat). For example:
using System.Drawing
// ...
Bitmap img = new Bitmap("file.jpg");
img.Save("file.png", ImageFormat.Png); // ImageFormat.Jpeg, etc
Omitting the second argument and just calling Image.Save(String) will save the image as its raw format.
In addition to last post (can't comment existing post since i'm new here)
File type is NOT based off of the extension.
Just try to do
img.Save("result.bmp")
and
Image.Save("result.bmp", ImageFormat.Bmp);
and you'll see that file sizes are dramatically different.

Categories

Resources