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.
Related
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.
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.)
I have problem with image compression. I need to compres a lot of files (700-900kb) to files 70-80kb without
loss of quality. (or small loss ) I found menu item "Save for Web & Devices ..." in Photoshop. It works great.
But I don't want to use photoshop programmatically. May be someone knows how to solve this problem with
other third party components or frameworks?
Thanks for any ideas!
.NET has a number of image decoding/encoding libraries, often tied to a particular GUI framework (e.g. in Windows Forms you have System.Drawing.Image and for WPF, see the Imaging Overview chapter on msdn).
There are also third party libraries specialized in image conversion/compression that you can find online (both free and non free)
Generally though, the amount of saving you get from compressing an image highly depends on the original format. If you already have JPEG photos with normal compression (quality of 85%) then there is not much you can do in terms of making them smaller except resizing them. If you have raw bitmaps (e.g. BMP, uncompressed/low compression TIFF etc.) then you can expect quite large savings with most compressing formats
When choosing image format, consider this:
Photos and similar: JPEG will often do fine. Good savings with reasonable quality loss
Screenshots and similar: PNG will generally give best results (PNG is lossless). JPEG will often create highly visible artifacts on screenshots
Compressing an already compressed image (i.e. PNG, JPEG etc.) with a general purpose compression algorithm like ZIP or RAR will in practice not give you any savings. You may actually end up with a bigger file.
You can have a look at the FreeImage project. It has a C# wrapper that you can use.
Imagemagick allows you to batch-processing on files and offers a everything you could possible ask for when it comes to handling of images
E.g. to resize every image in folder (destroy originals) to QVGA do
mogrify -resize 320x240 *.jpg
To preserve aspect ratio do
mogrify -resize 320x240! *.jpg
If you need to traverse a directory structure, this is how you can do it in *nix based systems (also destroying originals)
find . -type f -name *.jpg -exec convert -resize 800x800 {} \;
There is also an quality switch available, see here
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).
I'm having issues with TIFFs
Here is what I have to do, we have tiff images saved into the database, these images are CCITT4 compressed with a number of required tags, these include:
RowsPerStrip must be the ImageLength
Photometric Interpreation must be MinIsWhite
Multi-strip image format is not allowed
My problem is, I'm using the built in System.Drawing.Bitmap/Image objects, which happen to change the values of these when I put it into the object, I've tested this by saving the byte[] to a tiff directly from the database, checked the tags, they are fine.. but when i put the bytes into an Image object then save to file, they are modified.
To make things worse, I'm needing to add a text to the image before saving it.
So I need a component that will allow me more control with TIFF (and they must be tiff), and be able to add text to an image or be able to use the Graphics object.
I've tried using LibTiff but I have yet to see any examples on how to use this component,
any suggestions?
You can use our free and open-source LibTiff.Net library for this. It is freely available for all uses under a BSD license. The just released version 2.0 contains good documentation and number of samples.
There are samples that show how to convert any non-tiled TIFF image to the TIFF image which have all data written in a single strip and how to convert a System.Drawing.Bitmap to 1-bit CCITT single strip TIFF image.
I have never used the built int System.Drawing.Bitmap objects to do this. I personally use LeadTools, but it isn't free. It is however a robust and fairly straightforward API. I primarily use it for GEOTiff which contain specific data tags for image location data.
There is a 60 day evaluation if you would like to try it out.
I use FreeImage. There's a C# .NET wrapper available too.
The IEvolution component set from HiComponents is now totally free (no source) - http://www.hicomponents.com. A very powerful .NET imaging toolkit.