Converting a JPG to TIF in C#

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



I needed to create a batch process to convert a large number of JPGs to TIF
CCIT4 format. I'm sure there are libraries out there to do this, but I
couldn't find any that were free. I also found lots of source code that got
me on the right track but never seemed to solve my problem completely. So I
implemented my solution, it works, and I thought I would share it with this
group as I was helped by the group (especially Bob Powell's posts and
website). I thought something like this would be built into the framework.
Maybe it is and I just missed it. If there's an easier way, I'd love to
hear how. This solution is works for my scenario, and I also ran it through
a profiler (ANTS Profiler) to tighten things up a bit (made a huge
difference).

Good luck!
-joe

Here's the C# code:
/********************************************/
private static void ConvertJPGtoTIF (string jpgPath, string tifPath,
ImageCodecInfo ici)
{
byte tifPixels = 0;
float[] brightnessValues;

Bitmap jpgImage;
Bitmap tifImage;
BitmapData jpgBmd;
BitmapData tifBmd;
Color[] entries;
EncoderParameters eps = new EncoderParameters(1);

// new up a Bitmap from the source JPG file then
// get the bytes of the jpg so we can read through them
// 8 bits or 1 byte of the jpg is equal to 1 pixel
// each byte represents a color value that is in the Bitmaps Palette
jpgImage = new Bitmap (jpgPath);
jpgBmd = jpgImage.LockBits (
new Rectangle (0, 0, jpgImage.Width, jpgImage.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format8bppIndexed);

// new up a Bitmap that will hold our destination TIF file then
// get the bytes of the tif so we can write to them
// 8 bits or 1 byte of the tif is equal to 8 pixels (i.e. 1 bit of the
tif is equal to 1 pixel)
tifImage = new Bitmap (jpgImage.Width, jpgImage.Height,
PixelFormat.Format1bppIndexed);
tifBmd = tifImage.LockBits (
new Rectangle (0, 0, tifImage.Width, tifImage.Height),
ImageLockMode.WriteOnly,
PixelFormat.Format1bppIndexed);

// we will be doing a lookup into Palette.Entries for the color
reference by the JPG pixel
// Entries is a collection of Color objects that is generated each time
Palette.Entries is called
// I originally had this code inside the loop, but that was obviously
extremely inefficient once
// I realized how it was working. I then discovered that the
GetBrightness() call seems to be
// calculated on each call also. So since I only need the brightness
value from each color,
// I stuck those values in an array of floats that I would go after in
the loop
entries = jpgImage.Palette.Entries;
brightnessValues = new float[entries.Length];
for (int index = 0; index < entries.Length; index++)
brightnessValues[index] = entries[index].GetBrightness ();

// starting point from http://www.bobpowell.net/lockingbits.htm and
Bob's newsgroup posts...thanks Bob!
// for understanding of Stride see Bob's site - basically, the image is
wider in memory than the actual width
for (int h = 0; h < jpgBmd.Height; h++) // iterate through all of the
rows of the JPG
for (int w = 0; w < jpgBmd.Stride; w++) // iterate through all of
the columns for the current row of the JPG
{
// 1 byte of the jpg is 1 pixel
byte jpgPixel = Marshal.ReadByte (jpgBmd.Scan0, h *
jpgBmd.Stride + w);

// get the brightness/luminescence HSB/L value for a good
conversion to black or white
// using .5 as black = 0.0 and white = 1.0
bool isWhitePixel = brightnessValues[jpgPixel] < 0.5 ? false :
true;

// we need to translate what we know about this JPG pixel (white
or black) to the correct
// bit in the current byte of the TIF pixel
// the whole 7- thing is for writing the bits left to right
// only do this work if it's white, otherwise the bit is already
0 from the reset below
if (isWhitePixel)
tifPixels = (byte)(tifPixels | (1 << (7-(w % 8))));
if (w % 8 == 7) // we only write out TIF bytes after every 8 JPG
bytes
{
// divide width by 8 for proper TIF pixel
Marshal.WriteByte (tifBmd.Scan0, h * tifBmd.Stride + w/8,
tifPixels);
tifPixels = 0; // reset is needed since we are not ORing 0s
in
}
}
jpgImage.UnlockBits (jpgBmd);
tifImage.UnlockBits (tifBmd);

// save it out as a CCITT4 compressed TIF
eps.Param[0] = new EncoderParameter (Encoder.Compression,
(long)EncoderValue.CompressionCCITT4);
tifImage.Save (tifPath, ici, eps);
}


.



Relevant Pages

  • Re: Converting a JPG to TIF in C#
    ... Bob Powell ... >I needed to create a batch process to convert a large number of JPGs to TIF ... > Bitmap jpgImage; ... > // get the bytes of the jpg so we can read through them ...
    (microsoft.public.dotnet.framework.drawing)
  • Re: Best format question
    ... Recently I discovered that this format is prone to progressive quality loss over successive saves. ... Trying to research this issue I came to the conclusion that TIF might be better for storage. ... So will it help if I get the JPG images off the camera and immediately convert them to TIF before doing anything else with them? ...
    (rec.photo.digital)
  • Re: Converting a JPG to TIF in C#
    ... >> Bitmap jpgImage; ... >> BitmapData jpgBmd; ... >> BitmapData tifBmd; ... >> rows of the JPG ...
    (microsoft.public.dotnet.framework.drawing)
  • Re: JPG / TIF
    ... Converting it back to tif will not restore the lost information. ... Most cameras allow you to save in jpg or RAW. ... I notice on comparing the same picture saved in each of the two formats ... My uncle only saves his scanned images as TIF files - I generally stick ...
    (alt.photography)
  • Re: Damaged image files
    ... On my UK-European trip I planned to use RAW or TIF but because of the ... I should probably save the original JPG files as TIF. ... I hope you verified them against the disk at that stage. ... I left a copy of all the images on the hard drive and processed them ...
    (rec.photo.digital)