libtiff.net writeScanLine returns false

852 views Asked by At

I'm using libtiff.net to make a tiff from a jpeg. The problem apears when I try to write, because the tiff.writeScanLine returns false, meaning the image isn't written in the tiff.

Why is this happening? And how can I figure out what's wrong?

Here's the code:

 private bool creatingTiff()
        {
            using (Bitmap bmp = new Bitmap(targetFile))
            {
                using (Tiff tif = Tiff.Open("BitmapTo24BitColorTiff.tif", "w"))
                {
                    byte[] raster = getImageRasterBytes(bmp, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                    tif.SetField(TiffTag.IMAGEWIDTH, bmp.Width);
                    tif.SetField(TiffTag.IMAGELENGTH, bmp.Height);
                    tif.SetField(TiffTag.COMPRESSION, Compression.OJPEG);
                    tif.SetField(TiffTag.PHOTOMETRIC, Photometric.YCBCR);
                    tif.SetField(TiffTag.SUBFILETYPE, 0);
                    tif.SetField(TiffTag.ROWSPERSTRIP, bmp.Height);
                    tif.SetField(TiffTag.ORIENTATION, BitMiracle.LibTiff.Classic.Orientation.TOPLEFT);
                    tif.SetField(TiffTag.XRESOLUTION, bmp.HorizontalResolution);
                    tif.SetField(TiffTag.YRESOLUTION, bmp.VerticalResolution);
                    tif.SetField(TiffTag.RESOLUTIONUNIT, ResUnit.INCH);
                    tif.SetField(TiffTag.BITSPERSAMPLE, 8);
                    tif.SetField(TiffTag.SAMPLESPERPIXEL, 3);
                    tif.SetField(TiffTag.JPEGIFOFFSET, 768);
                    tif.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);

                    for (int i = 0, offset = 0; i < bmp.Height; i++)
                    {
                        bool b = tif.WriteScanline(raster, offset, i, 0);
                        Console.WriteLine("write succes: " + b);
                        offset += stride;
                    }
                }
                System.Diagnostics.Process.Start("BitmapTo24BitColorTiff.tif");
                return true;
            }
        }
            

        private static byte[] getImageRasterBytes(Bitmap bmp, System.Drawing.Imaging.PixelFormat format)
        {
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
            byte[] bits = null;

            try
            {
                // Lock the managed memory
                BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);

                // Declare an array to hold the bytes of the bitmap.
                bits = new byte[bmpdata.Stride * bmpdata.Height];

                // Copy the values into the array.
                System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length);

                // Release managed memory
                bmp.UnlockBits(bmpdata);
            }
            catch
            {
                return null;
            }

            return bits;
        }
                                                               
        private static void convertSamples(byte[] data, int width, int height)
        {
            int stride = data.Length / height;
            const int samplesPerPixel = 3;

            for (int y = 0; y < height; y++)
            {
                int offset = stride * y;
                int strideEnd = offset + width * samplesPerPixel;

                for (int i = offset; i < strideEnd; i += samplesPerPixel)
                {
                    byte temp = data[i + 2];
                    data[i + 2] = data[i];
                    data[i] = temp;
                }
            }
        }

The tif-tags are written, but the image itself isn't. Perhaps if someone can point me in the direction of the library developers blog (BitMiracle), I can direct my problem to them directly.

1

There are 1 answers

2
Bobrovsky On BEST ANSWER

I think your code has the following errors:

  • You can not use Compression.OJPEG for new images. Old-JPEGs can only be de-compressed.

  • You probably should not specify TiffTag.JPEGIFOFFSET value by hand. The library will specify proper value itself.

  • You are trying to write the whole strip using WriteScanline method. You should use WriteEncodedStrip instead.

It also helps to review warnings emitted by the library (it emits them into console).