I need to process large images (20,000x20,000pixels) in C#. Opening these images directly isn't the way to go because of memory limitations, but what I want to do is split the image into smaller pieces (cropping). I was looking for a 3rd party library that could the trick, but so far no result. I tried FreeImage and ImageMagick, but they cannot open an 20,000x20x000 pixel image. How can I achieve this?
问题:
回答1:
My current project at work consists of an image viewer/analyzing program capable of loading images in excess of 16 gb. You have to use manual file IO, pull the header information out and create your subimages on-demand (or if you're processing the image, you can create a single tile and process it in-place). Very few libraries are going to give you the capability to load/modify a 20k by 20k image (1.2gb at 24bpp) and the ones that do will rarely do so with anything resembling performance (if that is a concern).
回答2:
Don't know if this would help, but here is an article on image processing with C# lambda expressions.
回答3:
I don't know of any existing library to do this.
You're probably going to have to crack open the image file stream, seek to location where the color and pixel data exists, and read a section of the pixel data into an array, and create your image from that.
For example, for the BMP file format, you'll want to seek into the color table, load the color table, then seek to the pixel array section, load however many pixes you wish into an array, then make a new bitmap with just those pixels.
回答4:
I'd do it with ImageMagick. There is a pretty solid .NET API available, and it is typically the best way to do image processing like this.
Look under .NET, part of the way down the page.
http://www.imagemagick.org/script/api.php
Here is the info on how the crop stuff in ImageMagick works, for the command line version.
http://www.imagemagick.org/Usage/crop/#crop
回答5:
You can use the built-in .Net libraries.
Use
sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);
That will stop the image data from being cached in memory. You can create a new destination bitmap to draw a subsection of that massive image to:
var output = new Bitmap(outputWidth, outputHeight);
var outputGraphics = Graphics.FromImage(output);
outputGraphics.DrawImage(sourceBitmap, destRect, srcRect, GraphicsUnit.Pixel);
using (var fs = File.OpenWrite(outputFilePath))
{
output.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
}
Where destRect can be the whole size of the outputImage, or a smaller area.