16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)

View: New views
3 Messages — Rating Filter:   Alert me  

16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)

by Robert Zermeno :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I was not sure how to make a response to the user for everyone to see.  I had just posted my first message.  Do I just reply to the user that had emailed me to email her back and everyone else will receive my mail as well???  Oh, well, sorry for the additional post, but i want to make clear that I cannot use any other programs, plug-ins, or add-ons to perform the functionality. 
I have to manually do it.  I understand the concept, but it just is not working and I want another persons opinion since the mail archieve has helped me out.
Again, here is the Tags of my file for
 
SubFileType (1 Long): Zero
ImageWidth (1 Long): 14592
ImageLength (1 Long): 6940
BitsPerSample (1 Short): 16
Compression (1 Short): Uncompressed
Photometric (1 Short): MinIsBlack
ImageDescription (13 ASCII): Space Imaging
StripOffsets (6940 Long): 56040, 85224, 114408, 143592, 172776,...
SamplesPerPixel (1 Short): 1
RowsPerStrip (1 Short): 1
StripByteCounts (6940 Long): 29184, 29184, 29184, 29184, 29184, 29184,...
MinSampleValue (1 Short): 0
MaxSampleValue (1 Short): 2047
XResolution (1 Rational): 1
YResolution (1 Rational): 1
ResolutionUnit (1 Short): None
DateTime (20 ASCII): 2001:01:11 18:50:28
Copyright (24 ASCII): (c) Space Imaging LLC |
33550 (3 Double):
33922 (6 Double):
34735 (32 Short): 1, 1, 0, 7, 1024, 0, 1, 1, 1025, 0, 1, 1,...
34737 (31 ASCII): UTM, zone 11 | Meters|WGS 84, |
As you can see, BitsPerSample == 16 and Photometric == 1, so it is grayscale image (which it is).  My co-workers can view the image correctly through libtiff (it converts the image to 8 bpp), but we need for us to view the image the same way like libtiff, but manually.  I have coded all for 8-bit images, but for 16-bit I cannot get the right display of the image (you can see the image, but the gray color of each pixel is way off).
 
Here is my routine to go through the 16-bit image data.  I wish I can send you my image to see what I am talking about, but the file size is over 190 mb and I do not have a website for someone to pick it up.  Unless you can suggest a way for me to do it, I will be happy if you can tell me about it.
HBITMAP SubImage;
int imageBlock = (SubBitmap->Width * SubBitmap->Height) - (SubBitmap->Width * Form3->POffset);
int StripOffsetSize = ImageInfo.VByteCountPerStrip[0];
BYTE *pBits = (BYTE *)malloc(imageBlock);
BYTE *TmpBits = (BYTE *)malloc(StripOffsetSize);
 
fseek(m_TiffFile, (ImageInfo.VStripOffset[0] + (ImageInfo.ImageWidth * Form3->LOffset)), SEEK_SET);
//Process data and spit out to file...
int block= 0;
int SubHeight = 0;
int SubWidth = 0;
int lineHeight = 0;
int curPix = 0;
for(int i = Form3->LOffset; i < SubBitmap->Height; i++)
{
lineHeight++;
size_t GoodRead = fread(TmpBits, sizeof(BYTE), StripOffsetSize, m_TiffFile);
 
for(int curPixel = 0; curPixel < (GoodRead / 2); curPixel++)
{
 
//Convert the 16-bit pixel value to an 8-bit value
unsigned short value16 = *TmpBits++;
value16 = value16 + (*TmpBits++ << 8);
pBits[curPix++] = (value16/257. + .5);
 
}
 
TmpBits -= GoodRead;
 
}
inputHeight = lineHeight; //Globel variable keep track of acutal height of image..
 
SubImage = BuildDIB(pBits, SubBitmap->Width, SubBitmap->Height, 1);
pBits = 0;
TmpBits = 0;
free(pBits);
free(TmpBits); //Free memory
 
 
Where BuildDIB is a routine to make a BMP image object and returns the HBITMAP...well, here is the code as well:
 
 
HBITMAP BuildDIB(Byte *ASource, DWORD AWidth, DWORD AHeight, DWORD ABands)
{
// generate BMP/DIB handle from the raw image pixels
   BITMAPINFO bmi;                              // bitmap info structure
   Byte      *ptr;                              // pointer to raw image data
   Byte      *lpBits;                           // pointer to bitmap bits
   int        iDIBWidth;                        // "rounded" image width
   int        iImgWidth;                        // current image width
   HBITMAP    hBitmap;                          // handle to resultant bitmap
   HDC        hDC;                              // handle to device context
   HDC        hMemDC;                           // handle to temp context
   RGBQUAD    cm[256];                          // color map
// compute the "rounded" DIB width
   iImgWidth = AWidth * ABands;
   iDIBWidth = (((iImgWidth * 8) + 31) & ~31) >> 3;
// fill the BITMAPINFOHEADER structure
   ZeroMemory(&bmi, sizeof(BITMAPINFOHEADER));
   bmi.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
   bmi.bmiHeader.biWidth         = AWidth;
   bmi.bmiHeader.biHeight        = AHeight;
   bmi.bmiHeader.biPlanes        = 1;
   bmi.bmiHeader.biBitCount      = ABands << 3;
   bmi.bmiHeader.biCompression   = BI_RGB;
   bmi.bmiHeader.biSizeImage     = iDIBWidth * AHeight;
   bmi.bmiHeader.biXPelsPerMeter = 2835;        // assume 72 pixels per inch
   bmi.bmiHeader.biYPelsPerMeter = 2835;
   bmi.bmiHeader.biClrUsed       = (ABands > 1) ? 0 : 1U << bmi.bmiHeader.biBitCount;
   bmi.bmiHeader.biClrImportant  = bmi.bmiHeader.biClrUsed;
// create the DIB to hold the raw image
   hDC     = GetDC(Application->Handle);
   hBitmap = CreateDIBSection(hDC,
         &bmi,
         (ABands > 1) ? DIB_RGB_COLORS : DIB_PAL_COLORS,
         (void **)&lpBits,
         NULL,
         0);
        
   if (!hBitmap || !lpBits)
   {
      ReleaseDC(Application->Handle, hDC);
      DeleteObject(hBitmap);
      return static_cast<HBITMAP>(NULL);
   }
// generate a greyscale color map (if necessary)
   if (ABands == 1)
   {
      ZeroMemory(reinterpret_cast<char *>(cm), sizeof(cm));
      for (int ii = 0; ii < 256; ii++)
         FillMemory(reinterpret_cast<char *>(cm + ii), 3, ii);
      hMemDC  = CreateCompatibleDC(hDC);
      SelectObject(hMemDC, hBitmap);
      if (!SetDIBColorTable(hMemDC, 0, 256, static_cast<const RGBQUAD *>(cm)))
      {
         DeleteDC(hMemDC);
         ReleaseDC(Application->Handle, hDC);
         DeleteObject(hBitmap);
         return static_cast<HBITMAP>(NULL);
      }
      DeleteDC(hMemDC);
   }

// copy the raw image pixels to the bitmap
   ptr = ASource + (AHeight * iImgWidth);
   for (DWORD yy = 0; yy < AHeight; yy++)
   {
      ptr    -= iImgWidth;
      CopyMemory(lpBits, ptr, iImgWidth);
      lpBits += iDIBWidth;
   }
// release the device context and return the bitmap
   ReleaseDC(Application->Handle, hDC);
   return hBitmap;
}
 
What could I be doing wrong to not get the image to display correctly???
Thanks


_______________________________________________
Tiff mailing list: Tiff@...
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/

Parent Message unknown Re: 16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)

by Robert Zermeno :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Bob -
Sorry if you received it twice..I tried selecting reply all (within yahoo mail), but it did not cc the maptools...So I am sending it again.  Sorry..
 
 
>Endian issues and actual data range seem like the parts to be fixed.
 
I already account for Endian byte reading (either big/little), but what do you mean by "actual data range"?  Can you please provide more insight?
 
>What is the reason you are not allowed to use libtiff?
 
I answered this in the other post, but I cannot use libtiff because the handheld device that will use this application cannot support libtiff (as mentioned by my team lead).  That is why I am build my own tiff reader from scratch.  I can already read various tiff file types of 1-bit, 4-bit, 8-bit, 24-bit, and 32-bit tiff and Geotiff images.
However, I am stuck on 16-bit grayscale images.  It is requested that my solution to make the output image to be a 8-bit grayscale image.
 
So, I would like to know more about some techniques I can use to scale down.  I can already process the image and view it, but the grayscale color output is wrong (like I mentioned before, many pixel values are too white).  So, simply converting 2-bytes to 1-byte does not do the trick. 
 
Would I have to alter the colortable used in my bmp object.  Right now, I only produce a grayscale table starting at R=G=B=0 for 1st, then R=G=B=256 for second and +256 for each value up to 256 count. 
If so, how could I refine my colortable?
 
Robert

--- On Thu, 9/10/09, Bob Friesenhahn <bfriesen@...> wrote:

From: Bob Friesenhahn <bfriesen@...>
Subject: Re: [Tiff] 16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)
To: "Robert Zermeno" <refriguy68@...>
Date: Thursday, September 10, 2009, 8:59 AM

On Thu, 10 Sep 2009, Robert Zermeno wrote:

> I was not sure how to make a response to the user for everyone to see.  I had just posted my first message.  Do I just reply to the user that had emailed me to email her back and everyone else will receive my mail as well???  Oh, well, sorry for the additional post, but i want to make clear that I cannot use any other programs, plug-ins, or add-ons to perform the functionality. 

On this list you need to do a "group reply" or else the email response will go to just the one person.

What is the reason you are not allowed to use libtiff?  Libtiff does not solve this particular scaling issue, but it certainly makes everything else related to TIFF easier.

> What could I be doing wrong to not get the image to display correctly???

Endian issues and actual data range seem like the parts to be fixed.

Bob
--
Bob Friesenhahn
bfriesen@..., http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer,    http://www.GraphicsMagick.org/


_______________________________________________
Tiff mailing list: Tiff@...
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/

Re: 16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)

by Bob Friesenhahn :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, 10 Sep 2009, Robert Zermeno wrote:

> So, I would like to know more about some techniques I can use to
> scale down.  I can already process the image and view it, but the
> grayscale color output is wrong (like I mentioned before, many pixel
> values are too white).  So, simply converting 2-bytes to 1-byte does
> not do the trick. 

This is not my area of expertise.  The most obvious thing to do is to
obtain the maximum, minimum, and median, values, and then determine a
scaling from that.  But since it seems that your display device is not
ordinary, you may need to build a special color table so that
grayscale appears linear on your device.

Images may be linear-light so that they need a gamma mapping applied
so that they look correct on computer displays (which display sRGB).

>   Would I have to alter the colortable used in my bmp object.  Right
> now, I only produce a grayscale table starting at R=G=B=0 for 1st,
> then R=G=B=256 for second and +256 for each value up to 256 count. 

That sounds odd.  Normally for grayscale you want R, G, B to all be
set to the same values.  Sometimes you might use slightly colored
values in order to achieve a dithering effect to expand the effective
number of gray shades.

Bob
--
Bob Friesenhahn
bfriesen@..., http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer,    http://www.GraphicsMagick.org/
_______________________________________________
Tiff mailing list: Tiff@...
http://lists.maptools.org/mailman/listinfo/tiff
http://www.remotesensing.org/libtiff/