c# When does System.Drawing.Bitmap decompress the image stream? - c#

Right now I am using System.Drawing.Bitmap to take an image and divide it into regions. I assume that Bitmap must decompress the image in order to perform operations on it.
However, the Bitmap class accepts these formats: BMP, GIF, EXIF, JPG, PNG and TIFF
Some of these formats are compressed, so if the data in the stream is compressed, doesn't it have to be decompressed to perform manipulations? If so, does that mean that the Bitmap class allocates more memory for the decompressed version of the stream?
i feel like if the bitmap class makes data modifications to the stream then it would have to decompress the stream which should make the bitmap class take the same amount of memory working with BMP streams as when it works with PNG streams, despite the fact that the PNG streams is smaller.

In fact it does, GDI needs raw pixel data to feed it to the graphic card and/or represent it, so yes, it's being decompressed, but may be you don't see the memory rising because it's done into the system/graphic card.
Some special cases are DXT textures and some other special types which are understood by the hardware and don't need to be decompressed to work.

Related

How can I convert a PNG Image to a 1Bpp using SkiaSharp

How can I convert a PNG Image to a 1Bpp using SkiaSharp. I am currently using the SkiaSharp to do all the image processing for my .NET applications/services, and I have not been able to find an in-built way to encode an image from a SKCanvas or SKData to a 1bpp image format, I saw that Bmp & wbmp are available but they both return null in the following example:
byte[] imageBytes = *PNG Image Byte Array*
SKImage.FromEncodedData(imageBytes).Encode(SKEncodedImageFormat.Bmp, 100).ToArray();
SKImage.FromEncodedData(imageBytes).Encode(SKEncodedImageFormat.Wbmp, 100).ToArray();
Any ideas on how to accomplish this without doing a lot of custom code? Any help is most appreciated.
In the SkiaSharp, only three of these file formats (Jpeg, Png, and Webp) are actually supported by SkiaSharp. For all the other formats, the Encode method writes nothing into the stream and the resultant byte array is null. So this can not convert a PNG Image to a 1Bpp by using SkiaSharp.

C# Read huge image into array

I have huge images (1.800MP # 8bit or 16bit), all grayscale, no alpha, transparency or other stuff.
They may come as png, tiff, bmp, or even jpeg, so I need an image library to handle the reading, decompression and stuff.
After this, I just want to get an array with the grayscale pixel values out - preferrably 2d, but 1d is also alright. It also may be ushort all the time, even for the 8bit images.
I tried using the buid-int BitmapImage of C# - no luck, just throws exceptions for images this large.
Any other libraries that can give me the grayscale values, without hassle?
It will be faster if you use simple FileReader to read the content and generate your own array rather then looking for a library.

Lower image quality after converting from bytes

to give a background on what this topic is about. I am trying to convert an image file to byte[] by using a memorystream to return the memorystream.ToArray();
However, i have noticed that the image quality decreases after the conversion inputBitmap -> byte[] -> outputBitmap.
outputBitmap has a lower quality than the inputBitmap.
My code to convert the image to byte[] is as follows
MemoryStream mstream = new MemoryStream();
myImage.Save(mstream,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] buffer = mstream.ToArray();
and to convert from the byte[] back to an image,
MemoryStream mstream = new MemoryStream(buffer);
Image newImage = Image.FromStream(mstream);
can somebody explain why this is and hopefully guide me to correct this problem?
Note that before i used the inputBitmap as my pictureBox.Image, it looks great in quality. But after converting from byte[] to outputBitmap, setting outputBitmap as my pictureBox.Image becomes kind of blurred and low in quality.
A couple of things stand out for me.
You are saving to JPG rather than a lossless format like PNG.
You are not setting the quality of the compression used to save the image.
This means that you are probably compressing an image that has already been compressed thus losing even more information in the process.
I'd change to saving the file as PNG if I could, failing that make sure you set the quality of the JPG to 100% before you save it. This will reduce to a minimum the compression on the file and hence minimise the data loss.
If you're still seeing a difference in quality then the only thing that I can think of that might explain a this is a difference in the resolution (number of pixels and/or colour depth) between the screen shot and the saved file. Make sure you set the target bitmap size and colour depth to be the same as the source bitmap.

Getting a LSB of a BMP binary image

i was already able to convert a BMP image into binary memory stream but im confused with detecting LSB in pixel values..
I have the byte[] stream as '10101011101010101010010' ... .. ..
First is there a way that i can filter this binary stream to pixel values and detect LSB ?
If you want to read / write the Least Significant Byte to use the bitmap to hide information you will need to load the bmp data into an image, then access the pixel-data using GetPixel(). The BMP File itself might use RLL or some other compression so you cannot access the pixel data directly.
For detecting LSB in an image, it largely depends on the algorithm used, some are harder to detect as others. Do you have the description of the LSB-variant that might be in that image?

Image manipulation in C#

I am loading a JPG image from hard disk into a byte[]. Is there a way to resize the image (reduce resolution) without the need to put it in a Bitmap object?
thanks
There are always ways but whether they are better... a JPG is a compressed image format which means that to do any image manipulation on it you need something to interpret that data. The bimap object will do this for you but if you want to go another route you'll need to look into understanding the jpeg spec, creating some kind of parser, etc. It might be that there are shortcuts that can be used without needing to do full intepretation of the original jpg but I think it would be a bad idea.
Oh, and not to forget there are different file formats for JPG apparently (JFIF and EXIF) that you will ened to understand...
I'd think very hard before avoiding objects that are specifically designed for the sort of thing you are trying to do.
A .jpeg file is just a bag o' bytes without a JPEG decoder. There's one built into the Bitmap class, it does a fine job decoding .jpeg files. The result is a Bitmap object, you can't get around that.
And it supports resizing through the Graphics class as well as the Bitmap(Image, Size) constructor. But yes, making a .jpeg image smaller often produces a file that's larger. That's an unavoidable side-effect of Graphics.Interpolation mode. It tries to improve the appearance of the reduced image by running the pixels through a filter. The Bicubic filter does an excellent job of it.
Looks great to the human eye, doesn't look so great to the JPEG encoder. The filter produces interpolated pixel colors, designed to avoid making image details disappear completely when the size is reduced. These blended pixel values however make it harder on the encoder to compress the image, thus producing a larger file.
You can tinker with Graphics.InterpolationMode and select a lower quality filter. Produces a poorer image, but easier to compress. I doubt you'll appreciate the result though.
Here's what I'm doing.
And no, I don't think you can resize an image without first processing it in-memory (i.e. in a Bitmap of some kind).
Decent quality resizing involves using an interpolation/extrapolation algorithm; it can't just be "pick out every n pixels", unless you can settle with nearest neighbor.
Here's some explanation: http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
protected virtual byte[] Resize(byte[] data, int width, int height) {
var inStream = new MemoryStream(data);
var outStream = new MemoryStream();
var bmp = System.Drawing.Bitmap.FromStream(inStream);
var th = bmp.GetThumbnailImage(width, height, null, IntPtr.Zero);
th.Save(outStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return outStream.ToArray(); }

Categories