3

Creating tiff file, with LZW compression (default):-

System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(800, 1000); 
Graphics g = Graphics.FromImage(bitmap);
g.DrawString("Name: " + Name.Text, outputFont, Brushes.Black, new PointF(0, 20));
g.DrawString("Date Of Birth: " + Date_Of_Birth.Text, outputFont, Brushes.Black, new PointF(0, 40));
g.DrawString("Address: " + Address.Text, outputFont, Brushes.Black, new PointF(0, 60));
g.DrawString("City: " + City.Text, outputFont, Brushes.Black, new PointF(0, 80));
g.DrawString("State: " + State.Text, outputFont, Brushes.Black, new PointF(0, 100));
g.DrawString("Zip Code: " + Zip_Code.Text, outputFont, Brushes.Black, new PointF(0, 120));
g.DrawString("Phone: " + Phone.Text, outputFont, Brushes.Black, new PointF(0, 140));
g.DrawString(" ID: " + ID.Text, outputFont, Brushes.Black, new PointF(0, 160));
fileName = saveDirectory + id + ".tif";
bitmap.Save(fileName, ImageFormat.Tiff);

So I am trying to change its compression to CCITT:-

Bitmap myBitmap;
myBitmap = new Bitmap(fileName);
ImageCodecInfo myImageCodecInfo;
myImageCodecInfo = GetEncoderInfo("image/tiff");
System.Drawing.Imaging.Encoder myEncoder;
myEncoder = System.Drawing.Imaging.Encoder.Compression;
EncoderParameters myEncoderParameters;
myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter;      
myEncoderParameter = new EncoderParameter(myEncoder,(long)EncoderValue.CompressionCCITT4);
myEncoderParameters.Param[0] = myEncoderParameter;
myBitmap.Save(new_fileName, myImageCodecInfo, myEncoderParameters);

private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
  int j;
  ImageCodecInfo[] encoders;
  encoders = ImageCodecInfo.GetImageEncoders();
  for (j = 0; j < encoders.Length; ++j)
    {
        if (encoders[j].MimeType == mimeType)
        return encoders[j];
    }
  return null;
}

The process works and I can see that the compression type of my tiff file has correctly been modified to CCITT (by right clicking on the output file and checking properties). However when I try to open it, the whole image in black.. nothing is on it.

When I change the compression type to LZW or None or RLE then the tiff file is once again a viewable image.

Unfortunately I need the CCITT format only. Can anyone help me figure this out?

Update:

Even though the method now works on my windows 7 32 bit OS using Visual studio 2010.. Once published to the Windows 2008 server, the solution doesn't work (only for CCITT compression techniques). The following link explains why.

http://social.msdn.microsoft.com/Forums/vstudio/en-US/1585c562-f7a9-4cfd-9674-6855ffaa8653/parameter-is-not-valid-for-compressionccitt4-on-windows-server-2003-and-2008?forum=netfxbcl

As per this article, this is what I am trying but can't get the compression to apply to the original image:-

        int width = 800;
        int height = 1000;
        int stride = width/8;
        byte[] pixels = new byte[height*stride];

        // Try creating a new image with a custom palette.
        List<System.Windows.Media.Color> colors = new List<System.Windows.Media.Color>();
        colors.Add(System.Windows.Media.Colors.Red);
        colors.Add(System.Windows.Media.Colors.Blue);
        colors.Add(System.Windows.Media.Colors.Green);
        BitmapPalette myPalette = new BitmapPalette(colors);

        // Creates a new empty image with the pre-defined palette

        BitmapSource image = BitmapSource.Create(
            width,
            height,
            96,
            96,
            System.Windows.Media.PixelFormats.BlackWhite,
            myPalette, 
            pixels, 
            stride);


FileStream stream = new FileStream(Original_File, FileMode.Create);
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.Ccitt4;
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);

However, my end result is a file with the correct compression, but a solid black background. Deja Vu.

Philo
  • 1,931
  • 12
  • 39
  • 77
  • I believe CCITT is intended for bi-level images only, is it not? So pixels are either purely black or purely empty. See http://en.wikipedia.org/wiki/Group_4_compression for more info. What's your image content like? – Brian Warshaw Jan 17 '14 at 18:07
  • I have show some sample code of my image content (during the creation part of the code). Basically the user input on a web form translated into text (black text color with white background) onto a tiff file. – Philo Jan 17 '14 at 18:14
  • and Yes, CCITT is intended only for bi-level imaging. There is no coloring in my file, or any 3 Dimensional fancy graphics. Just plain text on a tiff file. – Philo Jan 17 '14 at 18:15
  • Just tossing stuff out here to help, but your tiff isn't somehow multipage or layered, is it? No transparency of any kind? – Brian Warshaw Jan 17 '14 at 18:19
  • In fact, it doesn't look like you're explicitly setting any background fill. How certain are you that it will default to white and not transparent? – Brian Warshaw Jan 17 '14 at 18:21
  • well, if I use any other form of compression, the image comes out correctly... white background, with black text from the user input on the web form. Only with CCITT it comes out as solid black. When I edit the picture in paint, I can draw on the picture with other colors and its fine. Somehow the compression method turns everything into black. – Philo Jan 17 '14 at 18:47
  • so I am not sure how only this compression method, defaults to something different than the other compression methods. – Philo Jan 17 '14 at 18:48
  • Different compression methods could handle an alpha channel differently. If you have an alpha background in your bitmap, it isn't a bi-level image as expected by your compression method. Basically, it's treating anything that isn't white as black, which is appropriate for a bi-level format conversion. And I just tested my hypothesis. See my answer to get your solution. – Brian Warshaw Jan 17 '14 at 18:51

1 Answers1

3

Edit your code as such, and you will be able to use your desired compression without the black background fill:

System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(800, 1000); 
Graphics g = Graphics.FromImage(bitmap);
/* Add this */ g.FillRectangle(Brushes.White, new Rectangle(0,0, 800, 1000));
g.DrawString("Name: " + Name.Text, outputFont, Brushes.Black, new PointF(0, 20));
g.DrawString("Date Of Birth: " + Date_Of_Birth.Text, outputFont, Brushes.Black, new PointF(0, 40));
g.DrawString("Address: " + Address.Text, outputFont, Brushes.Black, new PointF(0, 60));
g.DrawString("City: " + City.Text, outputFont, Brushes.Black, new PointF(0, 80));
g.DrawString("State: " + State.Text, outputFont, Brushes.Black, new PointF(0, 100));
g.DrawString("Zip Code: " + Zip_Code.Text, outputFont, Brushes.Black, new PointF(0, 120));
g.DrawString("Phone: " + Phone.Text, outputFont, Brushes.Black, new PointF(0, 140));
g.DrawString(" ID: " + ID.Text, outputFont, Brushes.Black, new PointF(0, 160));
fileName = saveDirectory + id + ".tif";
bitmap.Save(fileName, ImageFormat.Tiff);
Brian Warshaw
  • 22,657
  • 9
  • 53
  • 72
  • How can I change the font for my output tiff file? it seems that the font looks a bit muddy. – Philo Jan 17 '14 at 20:40
  • Unless the APIs have a diterhing algorithm built in (which, honestly, might not make it look a whole lot better in the end), your best bet is to start with a more pixely font and work with that. Smooth font strokes are achieved by using lighter shades of the font's assigned color, which obviously won't work in a bi-level image because everything not white goes pure black. – Brian Warshaw Jan 17 '14 at 20:43
  • nice!! I was using "technical" "tahoma" ...any suggestions ? – Philo Jan 17 '14 at 21:00
  • http://stackoverflow.com/questions/826185/i-need-a-windows-compatible-square-pixel-font has some options, though be careful with links. The link for Proggy Square was spammy at best, malicious at worst. – Brian Warshaw Jan 18 '14 at 12:39
  • http://www.dafont.com/proggy-clean.font that's a safe link for Proggy. Actually a rather nice-looking font. – Brian Warshaw Jan 18 '14 at 12:43
  • Hey thanks Brian you have been awesome, I have one last question:- I want to save my new compressed tiff file as the original file name instead of Test.tiff. However there seems to be a write lock. How do I dispose this lock and overwrite it on the original file name? – Philo Jan 20 '14 at 18:32
  • would something like this work? myBitmap.Dispose(); myBitmap = new Bitmap(saveDirectory + "test" + ".tif"); myBitmap.Save(fileName,myImageCodecInfo,myEncoderParameters); – Philo Jan 20 '14 at 18:58
  • From the docs for the `Bitmap` constructor you're using: "*The file name and path can be relative to the application or an absolute path. Use this constructor to open images with the following file formats: BMP, GIF, EXIF, JPG, PNG and TIFF. For more information about supported formats, see Types of Bitmaps. The file remains locked until the Bitmap is disposed.*" – Brian Warshaw Jan 21 '14 at 11:58
  • So in short, yes, it would appear that you need to `Dispose` your `Bitmap` instance to be able to write to that same filename. That said, the docs for `Dispose` indicate that it leaves the image in an unusable state (as expected), so saving to a temp file first (and rather than using test.tif, consider using `System.IO.Path.GetTempFileName()`, since temp files will get automatically cleaned up) would be necessary. – Brian Warshaw Jan 21 '14 at 12:00
  • amazing man, thanks for all the awesome help you have provided me with understanding tiff compression. I just found out that, the compression technique works when I run my application off of my IDE (VS studios) but when I publish my application on the production server I get an error:- System.ArgumentException Parameter is not valid. at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) – Philo Jan 22 '14 at 20:46
  • Do you know what version of .NET you have on the server vs. what you have on the desktop? – Brian Warshaw Jan 22 '14 at 20:55
  • 3.5 on both. Checked permissions as well on the server. The funny part is:- my app is able to create the original tiff file with LZW compression, Then it opens it in a filestream and does the compression technique and tries to save the compressed file as "test.tiff" and this is where it fails... the temp.tif file gets created in the server but nothing is on it.. an empty, un-formatted garbage file. This line from my code:- myBitmap.Save(new_fileName, myImageCodecInfo, myEncoderParameters); – Philo Jan 22 '14 at 21:06
  • Can you provide some info about the server where you're running it? Also, is there anything in that exception that tells you the name of the parameter that's invalid? – Brian Warshaw Jan 23 '14 at 20:55
  • Hey Brian , I updated my question. apparently the reason why it works on my desktop vs it not working on the server:- http://social.msdn.microsoft.com/Forums/vstudio/en-US/1585c562-f7a9-4cfd-9674-6855ffaa8653/parameter-is-not-valid-for-compressionccitt4-on-windows-server-2003-and-2008?forum=netfxbcl – Philo Jan 23 '14 at 20:59
  • However I cannot use the methodology mentioned in the solution, because I cannot add reference to System.Windows in my web app. – Philo Jan 23 '14 at 21:03
  • You can't add it from the GAC, but can't you copy the DLL that has System.Windows, add it as a resource to your project, and copy it to output? – Brian Warshaw Jan 24 '14 at 13:23
  • Hey Brian, I have been able to add System.Windows and apply the new method. I added the method in the update section of my original question. After running the new code I get, a tiff file with correct compression (CCIT) but a solid black background. Deja vu. – Philo Jan 27 '14 at 20:35
  • Just to make sure, are you still using fillRect like I said in my answer? – Brian Warshaw Jan 28 '14 at 00:25
  • yes Brian, I am still using fillRect. and I even tried reversing the fillRect Brush color to Black, just to test for any differences. Same result an image with a solid black background. I am thinking there might be something happening the way myPalette or Pixelformats. The good news is that this method works when published on the server, just need to figure out the solid background. – Philo Jan 28 '14 at 05:43
  • A couple of issues with the GDI and WIC collaboration on the Windows 2008 server led me to abandon this process. It works well on the Windows 7 OS. The Update Method, produced a black image, and I sort of get the idea that was because I wasn't being able to apply the old image parameters into the new image object I was creating. I tried libTiff and Atalasoft as 3rd party dlls. Atalasoft only handles 1bpp images, so the point was moot. Libtiff - a lot of code, ended up producing a black image as well. http://stackoverflow.com/questions/21321545/using-libtiff-net-library-for-tiff-conversion – Philo Feb 03 '14 at 23:18
  • Next test might be http://magick.codeplex.com/ But thanks a lot for all your help. Appreciate it. – Philo Feb 03 '14 at 23:20