File extension from System.Drawing.Image - c#

I'm writing a method that needs to save a System.Drawing.Image to a file. Without knowing the original file the Image was created from, is there anyway to determine what file extension it should have?
The best solution I've come up with is to use a Switch/Case statement with the value of Image.RawFormat.
Does it even matter that I save the Image in it's original format? Is an Image generated from a PNG any different from say one generated from a JPEG? Or is the data stored in an Image object completely generic?

While Steve Danner is correct in that an image created from a JPG will look different to an image created from a PNG once it's loaded into memory it's an uncompressed data stream.
This means that you can save it out to any file format you want.
However, if you load a JPG image and then save it as another JPG you are throwing away more information due to the compression algorithm. If you do this repeatedly you will eventually lose the image.
If you can I'd recommend always saving as PNG.

Image.RawFormat has cooties, stay away from it. I've seen several reports of it having no legal value for no apparent reason. Undiagnosed as yet.
You are quite right, it doesn't matter what format you save it to. After you loaded the file, the internal format is the same for any bitmap (not vector) with the same pixel format. Generally avoid recompressing jpeg files, they tend to get bigger and acquire more artifacts. Steve mentions multi-frame files, they need to be saved a different way.

Yes, it definitely matters because different fileformats support different features such as compression, multiple frames, etc.
I've always used a switch statement like you have, perhaps baked into an extension method or something.

To answer your question 'Does it even matter that I save the Image in it's original format?' explicitly: Yes, it does, but in a negative way.
When you load the image, it is uncompressed internally to a bitmap (or as ChrisF calls it, an uncompressed data stream). So if the original image used a lossy compression (for example jpeg), saving it in the same format will again result in loss of information (i.e. more artifacts, less detail, lower quality). Especially if you have repeated actions of read - modify - save, this is something to avoid.
(Note that it is also something to avoid if you are not modifying the picture. Just the repeated decompress - compress cycles will degrade the image quality).
So if disk space is not an issue here (and it usually isn't in the age of hard disks that are big enough for HD video), always store any intermediate pictures in lossless compression formats, or uncompressed. You may consider saving the finall output in a compressed format, depending on what you use it for. (If you want to present those final pictures on the web, jpeg or png would be good choices).

Related

c# Image size increases after saving it

I'm trying to save the image as follows:
var file = Image.FromFile(#"D:\front.png");
file.Save(#"D:\front_save.png");
Size of the saved imeage increases almost twice the size of original one. How do I save the image so it's completely the same as original image?
Image Link
Unfortunately, .NET doesn't expose any way to control the parameters that are applied as part of the PNG compression. Since PNG is a lossless format, the two images are "the same", they're just stored differently. What ever tool saved the original image must use different compression parameters than the default .NET PNG compression defaults, resulting in an optimized file size. When you save from .NET, the default compression parameters result in a larger, non-optimized, file size.
The answer to this question lists some third party libraries that you could use for PNG optimization. If you're not concerned about losing information, you could save the image as a jpeg.

Corrupted data when using LockBits/UnlockBits after saving and loading images

I'm writing a steganography program which supports multiple file types. There is a working implementation for WAV files and then one for image files, which is currently not working.
The image carrier is basically a wrapper around the .NET classes Bitmap and Image. It uses LockBits/UnlockBits to access the array of bytes contained in images. When the program is finished making changes to the byte array, it will copy it back into the Bitmap.
When the data has been copied and the Bitmap has been unlocked, I save it using:
image.Save(destination, ImageFormat.Png);
The next time I load the Image, I would expect that the byte array I saved earlier is identical to the one that I am going to extract from the saved Image (since PNG is lossless). However, this is not always the case.
The byte arrays are ALMOST identical, but SOME of the bytes with a value of 1 have been changed to 0. Other than this there is not really any pattern to it, seeing as it appears to happen to all channels.
Is there something about Image.Save or the PNG format that I have missed?
edit: When embedding the exact same data, it works for some images but not for all, even if they share the same attributes (both 24 bpp and PNG).
When saving an image you can specify different compression algorithms. The default one might produce this undesired effect. Try another one.
See:
- System.Drawing.Imaging.Encoder Compression
- System.Drawing.Imaging.EncoderValue Enumeration
- Image.Save Method (String, ImageCodecInfo, EncoderParameters)
Don't confuse these compression algorithms with the image quality. Image quality should not affect PNGs, as they use lossless compression.

How to write big image directly into bmp file (without creating bitmap object in memory) in c#?

Hello good smart programmers,
I need to merge small images into one big image which will have dimension about 7600 x 7600 px. When I create it in memory it takes too much memory I can't afford that.
I think good way to do this is make buffer (for every small picture which i want to put in big Image) and write directly into file (excatly blob - on azure). Somebody know how to do that (any free library?) I've searched google but no answers (maybe wrong question - my english is poor).
If you are talking about a "bmp" file, you can do this by directly writing data to a file stream in the Bitmap file format. It's pretty simple, actually the "bmp" is the simplest image format, so I doubt you will have any difficulties. Here are 2 useful articles that explain the bitmap file format in details:
BMP file format in Wikipedia
Microsoft Windows Bitmap
I'm not aware of any image libraries that will do the encoding into BMP format on the fly so I'm afraid you'll have to implement your own.
Fortunately the BMP format is very simple when no compression is used and not very difficult with RLE compression. It's basically a header followed by the raw bytes of the image pixels, line after line.
This means you're going to have to load all the images in a line (if your target image is say 30 by 40 images, you'll need to load 30.) Unless your input images are also in BMP format and you don't mind creating a custom reader.
You can get the BMP file format by typing "BMP Format" in Google (wikipedia has it as well.)

is there a way to compress a paged .tiff file using C#?

At the end of my process, I need to upload several paged .tiff file images to a website. The files need to be very small, 500kb or less when i upload them.
The problem is, even with me resizing them a lot but at the same time being able to read a few lines of text that are in some of them, they are around 1mb each or so.
I first resize all images going into the tiff files but it's not enough. I need a way to change the quality of them to decrease their size as well.
Can C# do this or would I need a third party software to do it?
The files being uploaded MUST be .tiff.
You don't provide much detail about your data, so can only make some guesses as to what you might need to look at.
First, can you loose some resolution? Can you make the images smaller?
Second, can you loose some color depth? Are you saving the files in a color format when bilevel or greyscale images would suffice?
Third, how clean are these images? Are they photos, scanned documents, what? If they are scanned documents of text or drawings, then some pre-processing to remove noise can make a significant difference in size.
Lastly, what compression method are you saving the file with? Only a lossy format is going to give you the highest degree of compression is most circumstances.
Based on your follow-up:
1) If you can make smaller, this of course saves significant storage space. Determine what is the minimum acceptable resolution that they need to be and standardize on that.
2) If you need to persist color, then this step might not be as effective, since you would have to algorithmically decrease the dynamic range of colors used in the image to an acceptable level before compressing. If you are not sure what this means, then you would probably best skip considering this completely unless you can spend time learning more about image processing and/or using a image processing library that will simplify this for you.
3) I don't think you addressed this in your comments. If you want more precise help, you should update your original question and add much more detail about what you are trying to accomplish. Provide some explanations of what/why you need to do in order to help determine what tradeoffs make sense.
4) Yes, JPG is a lossy format, but I think you may be confusing a few different things (or I may not be understanding your intent from your description). If you are first resizing your original images down into a new JPG file (an intermediate image file), then you are building a TIFF file and inserting the resized JPG as a source image into a multi-page TIFF and saving that, then you need to realize that the process of how the files are compressed in the intermediate files do not necessarily have any correlation with the compression format used in the TIFF file. Depending on what you are using to build and create the TIFF file, the compression format used in the TIFF is done separately and you probably need to specify those parameters when you save that file. If this is what you are doing, then the intermediary process of saving the JPG files may be increasing the size a bit.

Convert multiple byte[] to multipage tiff equivalent of Image.SaveAdd without GDI+

I am working on a system that stores many images in a database as byte[]. Each byte[] is a multi page tiff already, but I have a need to retrieve the images, converting them all to one multi page tiff. The system was previously using the System.Drawing.Image classes, with Save and SaveAdd - this was nice in that it saves the file progressively, and therefore memory usage was minimal, however GDI+ concurrency issues were encountered - this is running on a back end in COM+.
The methods were converted to use the System.Windows.Media.Imaging classes, TiffBitmapDecoder and TiffBitmapEncoder, with a bit of massaging in between. This resolved the concurrency issue, but I am struggling to find a way to save the image progressively (i.e. frame by frame) to limit memory usage, and therefore the size of images that can be manipulated is much lower (i.e. I created a test 1.2GB image using the GDI+ classes, and could have gone on, but could only create a ~600MB file using the other method).
Is there any way to progressively save a multi page tiff image to avoid memory issues? If Save is called on the TiffBitmapEncoder more than once an error is thrown.
I think I would use the standard .NET way to decode the tiff images and write my own tiff encoder that can write progressively to disk. The tiff format specifications are public.
Decoding a tiff is not that easy, that's why I would use the TiffBitmapDecoder for this. Encoding is is easier, so I think it is doable to write an encoder that you can feed with separate frames and that is writing the necessary data progressively to disk. You'll probably have to update the header of the resulting tiff once you are ready to update the IFD (Image File Directory) entry.
Good luck!
I've done this via LibTIFF.NET I can handle multi-gigabyte images this way with no pain. See my question at
Using LibTIFF from c# to access tiled tiff images
Although I use it for tiled access, the memory issues are similar. LibTIFF allows full access to all TIFF functions, so files can be read and stored in a directory-like manner.
The other thing worth noting is the differences between GDI on different windows versions. See GDI .NET exceptions.

Categories

Resources