2

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!

Mike
  • 23
  • 3

2 Answers2

0

JPEG converts image into YCbCr internally already, so I don't think you will benefit from this.

Roman Zavalov
  • 575
  • 3
  • 8
  • Perhaps I'm new to this field and am not sure about it, TIFF using JPEG compressed data can also work on RGB color spaces, and color conversion to YCbCr can greatly compress the image. Actually, when I run the program under RGB PHOTOMETRIC, the size of the image is greatly increased (compared with original tiff, which is OJPEG using YCbCr). And the problem is when I try to use YCbCr, the image cannot be generated. FYI:ftp://ftp.remotesensing.org/pub/libtiff/doc/TIFF6.pdf page 102 – Mike Oct 07 '13 at 08:31
  • Hmm, it might be that TIFF don't necessarily convert to YCbCr when compressing to JPEG. However, JPEG (JFIF) itself always uses YCbCr. – Roman Zavalov Oct 07 '13 at 10:09
0

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.

Bobrovsky
  • 13,789
  • 19
  • 80
  • 130
  • Thank you for the reply! I tried and found out that indeed the ROWSPERSTRIP went wrong. And after I change that to 16, still some problems exist:"Compression algorithm does not support random access" and "JPEGLib: Application transferred too few scanlines". I believe it might be caused by the WriteScanline function (FYI: http://www.remotesensing.org/libtiff/man/TIFFWriteScanline.3tiff.html DIAGNOSTICS tag). So is there a way to copy entire strip? As for JPEG, ROWSPERSTRIP cannot be 1 (must be multiplex of 16). Thank you. – Mike Oct 08 '13 at 07:07
  • @Mike you could accumulate 16 (or whatever the ROWSPERSTRIP value is) scanlines in a buffer and then write all of them at once using WriteEncodedStrip method. – Bobrovsky Oct 08 '13 at 09:00
  • 1
    Thank you for the help! I just finish my code, using a whole strip to save the image, and it works. – Mike Oct 11 '13 at 07:54
  • Hi Mike, would you mind to share how did you wrote that strip to save the image? – coloboxp Mar 10 '16 at 17:07
  • I found it, so I put it here (adapted to your code) in case someone else needs it: Replace: 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; } with: tif1.WriteEncodedStrip(0, raster1, raster1.Length); – coloboxp Mar 10 '16 at 17:33