0
votes

I wrote a desktop app which converts an 8bit TIFF to a 1bit but the output file cannot be opened in Photoshop (or other graphics software). What the application does is

  • it iterates every 8 bytes (1 byte per pixel) of the original image
  • then converts each value to bool (so either 0 or 1)
  • saves every 8 pixels in a byte - bits in the byte are in the same order as the pixels in the original image

The TIFF tags I set: MINISBLACK, compression is NONE, fill order is MSB2LSB, planar config is contiguous. I'm using BitMiracle's LibTiff.NET for reading and writing the files.

What am I doing wrong that the output cannot be opened by popular software?

Input image: http://www.filedropper.com/input
Output image: http://www.filedropper.com/output

1
For a start you could try looking at what e.g. Photoshop generates when you do the same steps there. - Joey
You probably specify wrong BITSPERSAMPLE and/or SAMPLESPERPIXEL values. Try and open your image using AsTiffTagViewer utility and see what it will display. - Bobrovsky
Post a sample file and I'll tell you what's wrong with it. - BitBank
Input image: filedropper.com/input Output image: filedropper.com/output My conversion code: paste.ofcode.org/jqQ4zQp5SYaJwR2rUybBa Thx! - Val

1 Answers

2
votes

From your description of the byte manipulation part, it appears you are converting the image data from 8-bit to 1-bit correctly. If that's the case, and you don't have specific reasons to do it from scratch using your own code, you can simplify the task of creating valid TIFF files by using System.Drawing.Bitmap and System.Drawing.Imaging.ImageCodecInfo. This allows you to save either uncompressed 1-bit TIFF or compressed files with different types of compression. The code is as follows:

// first convert from byte[] to pointer
IntPtr pData = Marshal.AllocHGlobal(imgData.Length);
Marshal.Copy(imgData, 0, pData, imgData.Length);
int bytesPerLine = (imgWidth + 31) / 32 * 4; //stride must be a multiple of 4. Make sure the byte array already has enough padding for each scan line if needed
System.Drawing.Bitmap img = new Bitmap(imgWidth, imgHeight, bytesPerLine, PixelFormat.Format1bppIndexed, pData);

ImageCodecInfo TiffCodec = null;
foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
   if (codec.MimeType == "image/tiff")
   {
      TiffCodec = codec;
      break;
   }
EncoderParameters parameters = new EncoderParameters(2);
parameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW);
parameters.Param[1] = new EncoderParameter(Encoder.ColorDepth, (long)1);
img.Save("OnebitLzw.tif", TiffCodec, parameters);

parameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
img.Save("OnebitFaxGroup4.tif", TiffCodec, parameters);

parameters.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);
img.Save("OnebitUncompressed.tif", TiffCodec, parameters);

img.Dispose();
Marshal.FreeHGlobal(pData); //important to not get memory leaks