AWARE [SYSTEMS] Imaging expertise for the Delphi developer
AWare Systems, Imaging expertise for the Delphi developer, Home TIFF and LibTiff Mailing List Archive

LibTiff Mailing List

TIFF and LibTiff Mailing List Archive
September 2009

Previous Thread
Next Thread

Previous by Thread
Next by Thread

Previous by Date
Next by Date

Contact

The TIFF Mailing List Homepage
This list is run by Frank Warmerdam
Archive maintained by AWare Systems



Valid HTML 4.01!



Thread

2009.09.10 14:38 "16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)", by Robert Zermeno
2009.09.11 00:37 "Re: 16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)", by Robert Zermeno
2009.09.11 01:43 "Re: 16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)", by Bob Friesenhahn

2009.09.10 14:38 "16-bit grayscale tiff to 8-bit grayscale in borland c++ (more info)", by Robert Zermeno

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