Open huge TIF in .NET and copy parts to new image [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
I'm looking for a library that can open and copy sections of a large TIFF file. I've looked at LibTiff.Net which opens the file very quickly but it doesn't have any functions for cropping or copying sections of the image. My image is 100,000 x 100,000 pixels upwards and creating a System.Drawing.Bitmap of that size crashes the application so converting to a Bitmap first is not an option.
Can anyone recommend a .NET library?

If your file is less than 4GB on disk than I recommend you to take another look at LibTiff.Net. Even with such large images you have some options.
First of all, check whether your image is tiled or stripped. Tiff.IsTiled method will give you the answer.
If your image is tiled, than you probably shouldn't read it using ReadScanline method. It might be better to use ReadEncodedTile method in that case.
If your images is stripped, than you can use ReadScanline and ReadEncodedStrip methods to read it.
If you want to use something that expects System.Drawing.Bitmap than try using ReadRGBATile or ReadRGBAStrip. These methods can be used to create bitmaps from portions of your image. There is no sample for this, but Convert color TIFF to a 32-bit System.Drawing.Bitmap should give you almost all required information about how to convert tile or strip of an image to a bitmap.
EDIT:
LibTiff.Net 2.4.508 adds support for BigTiff so files larger than 4GB are also supported.

Your image must be in BigTIFF format, since normal TIFF can't be larger than 4 GB.
BigTIFF can be read with a modified version of libtiff (available in BigTIFF website), this library allows to handle such images the way you want without loading all pixel data in memory.
I didn't see bindings for .NET but it shouldn't be too long to do it.

Atalasoft dotImage has this ability built-in to the TIFF decoder. The decode implements the interface IRegionReadable, which lets you read a rectangular section from a given page of an image in a Stream.
In a TIFF, this section will honor the orientation tag and in stripped or tiled tiffs uses the minimum set of tiles and strips to fill the rectangle.
(disclaimer, I work for Atalasoft and wrote that interface and implemented it in the TIFF decoder)

As Bobrovsky mentioned you should check if your file image is tiled or not. In the following, I've presented the snippet code to read a stream tiff and crop the upper left part of the image.
using (Tiff input = Tiff.Open(#"imageFile.tif", "r"))
{
// get properties to use in writing output image file
int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();
int scanlineSize = input.ScanlineSize();
byte[][] buffer = new byte[height][];
for (int i = 0; i < height; ++i)
{
buffer[i] = new byte[scanlineSize];
input.ReadScanline(buffer[i], i);
}
using (Tiff output = Tiff.Open("splitedImage.tif", "w"))
{
output.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel);
output.SetField(TiffTag.IMAGEWIDTH, width/2);
output.SetField(TiffTag.IMAGELENGTH, height/2);
output.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample);
output.SetField(TiffTag.ROWSPERSTRIP, output.DefaultStripSize(0));
output.SetField(TiffTag.PHOTOMETRIC, photo);
output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
int c = 0;
byte[][] holder = new byte[height][];
for (int i = height/2; i < height; i++)
//for (int j = 0; j < height/2 ; j++)
{
holder[i] = buffer[i].Skip(buffer[i].Length/2).ToArray();
output.WriteScanline(holder[i], c);
c++;
}
}
}
System.Diagnostics.Process.Start("splitedImage.tif");
For other parts of the image, you can change the range of "i" in for loop.

Related

C# - Can I use Libtiff to output Tiff encoded JPEG (In YCbCr)

Hi I am quite new to Libtiff and image processing, and I have a question when I try to use Libtiff.net from Bitmiracle.
I have some OJPEG TIFF image and want to convert them into nowadays JPEG TIFF. I achieved that by converting the source into BMP and then save as TIFF (compression: JPEG; photometric: RGB), but the size of the image is quite large. So I thought if I can compress them with photometric of YCbCr, which can reduce the size a lot.
However, when I change the photometric from RGB to YCbCr, the program just don't work: the output is only 8 bytes (the input is about 400kb). When open the image as TXT, it shows:
"II* "
The code I use is:
byte[] raster1 = getImageRasterBytes(inputbmp[0], PixelFormat.Format24bppRgb);
tif1.SetField(TiffTag.IMAGEWIDTH, inputbmp[0].Width);
tif1.SetField(TiffTag.IMAGELENGTH, inputbmp[0].Height);
tif1.SetField(TiffTag.COMPRESSION, Compression.JPEG);
tif1.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR);
tif1.SetField(TiffTag.ROWSPERSTRIP, inputbmp[0].Height);
//tif1.SetField(TiffTag.JPEGQUALITY, confidence);
tif1.SetField(TiffTag.XRESOLUTION, 200);
tif1.SetField(TiffTag.YRESOLUTION, 200);
tif1.SetField(TiffTag.BITSPERSAMPLE,8);
tif1.SetField(TiffTag.SAMPLESPERPIXEL, 3);
int stride = raster1.Length / inputbmp[0].Height;
convertSamples(raster1, inputbmp[0].Width, inputbmp[0].Height);
for (int i = 0, offset = 0; i < inputbmp[0].Height; i++)
{
tif1.WriteScanline(raster1, offset, i, 0);
offset += stride;
}
I'm not quite sure if WriteScanline can handle YCbCr output or not, and if there are other ways, It's totally cool too.
Thank you for the help!
Output images are definetely broken. It usually happens when some fatal error occurred. The library should output warnings and errors into console in such a case.
Please investigate the warnings and errors. They might give you the answer.
Based on experience, I think you might have provided incorrect value for ROWSPERSTRIP tag. The value should be a multiple of 8.
JPEG converts image into YCbCr internally already, so I don't think you will benefit from this.

Decode an JFIF image file in C#

I have a JPEG image which is JFIF formatted. I want to decode it and get the dimension.
Here is my code:
while (binaryReader.ReadByte() == 0xff)
{
byte marker = binaryReader.ReadByte();
ushort chunkLength = binaryReader.ReadLittleEndianInt16();
if (marker == 0xc0)
{
binaryReader.ReadByte();
int height = binaryReader.ReadLittleEndianInt16();
int width = binaryReader.ReadLittleEndianInt16();
return new Size(width, height);
}
binaryReader.ReadBytes(chunkLength - 2);
}
Ok. This piece of code is common and you can find it all over the internet. It works fine for most of the JPEG images.
Now, this specific image which was taken by the camera - "Canon EOS 300D DIGITAL", does not support this piece of code. The marker for the dimension is 0xFFC2 instead of 0xFFC0.
My question is which one is correct? If the code is correct, then how can a Canon camera produce a non-standard image? If the Canon camera is correct, then how can we fix the code to correct find the dimension of this image?
Thanks.
FFC2 seems to be the marker for progressive images.
please see for example http://en.wikipedia.org/wiki/JPEG which explains what "progressive" format is (see "JPEG compression" section).
yes, i think you can change your if statement to check for both 0xc0 (SOF0 marker) and 0xc2 (SOF2 marker) because they seem to have similar structure (see "syntax and structure" section). see also here: http://fjcore.googlecode.com/svn/trunk/FJCore/Decoder/JpegDecoder.cs
i am not expert in JPEG formats, so you might want to check with specialised forums if you are developing a mission critical code.

Convert 1-bit image to 8-bits

How can I convert a 1 bit image to an 8 bit image using C#? What color matrix should be used? Can you please provide samples or links?
Disclaimer: I don't know C#, but I've done too much image processing on C/C++ so I can't pass on answering - I'll answer in C since I think C# shares a similar syntax.
Both 1bit (two colors) and 8bit (256 colors) images have a palette. but transitioning a 1bit to 8bit transition is easy - since there's no quantization involved, just up-sampling.
First you need to choose (or import) the two colors of the 1bit image's palette. If you don't have any, I suggest using black (0x000000FF) and white (0xFFFFFFFF) for clarity (note: both colors are RGBA, I think windows uses ABGR). This will be your 'palette'.
Then map each color to the palette - The input image is going to have width * height / 8 bytes. Each byte represents eight pixels. Since I don't know about your expertise in bittwiddling (i.e I don't want to confuse you and I don't want you to mindlessly copy and paste code you've been granted on the internets), I'll keep this answer simple.
// Insert your image's attributes here
int w = image.width;
int h = image.height;
// Data of the image
u8* data = image.data;
/*
* Here, you should allocate (w * h) bytes of data.
* I'm sure C# has ByteArray or something similar...
* I'll call it output in my code.
*/
u8* output = new u8[w * h];
u8* walker = output;
// Loop across each byte (8 pixels)
for(int i=0; i<w*h/8; ++i) {
// Loop across each pixel
for(int b=(1<<7); b>0; b>>=1) {
// Expand pixel data to output
*walker++ = !!(data[i] & b);
}
}
Hope that helps!
Does this help:
http://www.wischik.com/lu/programmer/1bpp.html
But of course it needs some clean up. It could use some try..finally's for all the delete's and releasing of DC's

C# - How to convert an Image into an 8-bit color Image?

I need to convert a PNG Image loaded from a file into an 8 bit-per-pixel byte array used by another device (embedded programming).
I'm copying over pixel by pixel into a new Image created with a 16-bit color - Format16bppRgb565, but I need Format8bpp, which is not present in the .NET Framework. (I cannot use Format8bppIndexed since the other device cannot handle indexed bitmaps)
Bitmap img = new Bitmap(imgPath);
Bitmap img8 = new Bitmap(imgW, imgH, PixelFormat.Format16bppRgb565);
for (int I = 0; I <= img.Width - 1; I++) {
for (int J = 0; J <= img.Height - 1; J++) {
img8.SetPixel(I, J, img.GetPixel(I, J));
}
}
So how can I convert an Image into an 8-bit per pixel byte array?
Can I use the 8-bit indexed format and extract the bytes? - Format8bppIndexed
Can I calculate the pixel colors by reducing the 32-bit color R,G,B values to 8-bit?
Is there a C# library that does this already?
"The easiest way is to create a new 8 bit bitmap, and draw your 24 bit image onto it." - how?
Although I'm not sure how to do it with plain vanilla C# you can use the FreeImage Project libraries to convert images formats:
FreeImage is an Open Source library
project for developers who would like
to support popular graphics image
formats like PNG, BMP, JPEG, TIFF and
others as needed by today's multimedia
applications. FreeImage is easy to
use, fast, multithreading safe,
compatible with all 32-bit versions of
Windows, and cross-platform (works
both with Linux and Mac OS X).
It's written in C++ but has good .NET wrappers you can use.
I already did it in one Pattern Recognition project. Searching some image processing and pattern recognition books you can find these solutions.
a) If you want to convert to greyscale you can find in general two solutions.
#1 Averaging RGB channels. - You can take 8-bit values for avery single channel and calculate pixel = ( R+G+B )/3
#2 Take only the Green component. It is best viewed.
b) If you want to convert to 8bit color representation you need to use a Color table.
You can see a solution here http://www.codeproject.com/KB/graphics/Image_Bitdepth_Conversion.aspx

Image cropping C# without .net library

Can anyone advise on how to crop an image, let's say jpeg, without using any .NET framework constructs, just raw bytes? Since this is the only* way in Silverlight...
Or point to a library?
I'm not concerned with rendering i'm wanting to manipulate a jpg before uploading.
*There are no GDI+(System.Drawing) or WPF(System.Windows.Media.Imaging) libraries available in Silverlight.
Lockbits requires GDI+, clarified question
Using fjcore: http://code.google.com/p/fjcore/ to resize but no way to crop :(
You could easily write crop yourself in fjcore. Start with the code for Resizer
http://web.archive.org/web/20140304090029/http://code.google.com:80/p/fjcore/source/browse/trunk/FJCore/Resize/ImageResizer.cs?
and FilterNNResize -- you can see how the image data is stored -- it's just simple arrays of pixels.
The important part is:
for (int y = 0; y < _newHeight; y++)
{
i_sY = (int)sY; sX = 0;
UpdateProgress((double)y / _newHeight);
for (int x = 0; x < _newWidth; x++)
{
i_sX = (int)sX;
_destinationData[0][x, y] = _sourceData[0][i_sX, i_sY];
if (_color) {
_destinationData[1][x, y] = _sourceData[1][i_sX, i_sY];
_destinationData[2][x, y] = _sourceData[2][i_sX, i_sY];
}
sX += xStep;
}
sY += yStep;
}
shows you that the data is stored in an array of color planes (1 element for 8bpp gray, 3 elements for color) and each element has a 2-D array of bytes (x, y) for the image.
You just need to loop through the destination pixels, copying then from the appropriate place in the source.
edit: don't forget to provide the patch to the author of fjcore
ImageMagick does a pretty good job. If you're ok with handing off editing tasks to your server...
(Seriously? The recommended way of manipulating images in Silverlight is to work with raw bytes? That's... incredibly lame.)
I'm taking a look at : http://code.google.com/p/fjcore/source/checkout
A dependency free image processing library.
where is silverlight executed?
Is there any reason at all to send an complete picture to the client to make the client crop it?
Do it on the server... (if you are not creating an image editor that is..)

Categories

Resources