Blame contrib/win_dib/tiff2dib.c

Packit 7838c8
/*************************************************************************
Packit 7838c8
 *
Packit 7838c8
 * Source file for Windows 95/Win32. 
Packit 7838c8
 *
Packit 7838c8
 * The function LoadTIFFinDIB in this source file let you load 
Packit 7838c8
 * a TIFF file and build a memory DIB with it and return the 
Packit 7838c8
 * HANDLE (HDIB) of the memory bloc containing the DIB.
Packit 7838c8
 *
Packit 7838c8
 *  Example : 
Packit 7838c8
 * 
Packit 7838c8
 *   HDIB   hDIB;
Packit 7838c8
 *   hDIB = LoadTIFFinDIB("sample.tif");
Packit 7838c8
 *
Packit 7838c8
 *
Packit 7838c8
 * To build this source file you must include the TIFF library   
Packit 7838c8
 * in your project.
Packit 7838c8
 *
Packit 7838c8
 * 4/12/95   Philippe Tenenhaus   100423.3705@compuserve.com
Packit 7838c8
 *
Packit 7838c8
 ************************************************************************/
Packit 7838c8
Packit 7838c8
Packit 7838c8
#include "tiffio.h" 
Packit 7838c8
Packit 7838c8
#define HDIB HANDLE
Packit 7838c8
#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
Packit 7838c8
#define CVT(x)      (((x) * 255L) / ((1L<<16)-1))
Packit 7838c8
Packit 7838c8
static HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount);
Packit 7838c8
static LPSTR FindDIBBits(LPSTR lpDIB);
Packit 7838c8
static WORD PaletteSize(LPSTR lpDIB);
Packit 7838c8
static WORD DIBNumColors(LPSTR lpDIB);
Packit 7838c8
static int checkcmap(int n, uint16* r, uint16* g, uint16* b);
Packit 7838c8
Packit 7838c8
Packit 7838c8
Packit 7838c8
/*************************************************************************
Packit 7838c8
 *
Packit 7838c8
 * HDIB LoadTIFFinDIB(LPSTR lpFileName) 
Packit 7838c8
 *
Packit 7838c8
 * Parameter:
Packit 7838c8
 *
Packit 7838c8
 * LPSTR lpDIB      - File name of a tiff imag
Packit 7838c8
 *
Packit 7838c8
 * Return Value:
Packit 7838c8
 *
Packit 7838c8
 * LPSTR            - HANDLE of a DIB
Packit 7838c8
 *
Packit 7838c8
 * Description:
Packit 7838c8
 *
Packit 7838c8
 * This function load a TIFF file and build a memory DIB with it
Packit 7838c8
 * and return the HANDLE (HDIB) of the memory bloc containing
Packit 7838c8
 * the DIB.
Packit 7838c8
 *
Packit 7838c8
 * 4/12/95   Philippe Tenenhaus   100423.3705@compuserve.com
Packit 7838c8
 *
Packit 7838c8
 ************************************************************************/
Packit 7838c8
Packit 7838c8
HDIB LoadTIFFinDIB(LPSTR lpFileName)    
Packit 7838c8
{
Packit 7838c8
    TIFF          *tif;
Packit 7838c8
    unsigned long imageLength; 
Packit 7838c8
    unsigned long imageWidth; 
Packit 7838c8
    unsigned int  BitsPerSample;
Packit 7838c8
    unsigned long LineSize;
Packit 7838c8
    unsigned int  SamplePerPixel;
Packit 7838c8
    unsigned long RowsPerStrip;  
Packit 7838c8
    int           PhotometricInterpretation;
Packit 7838c8
    long          nrow;
Packit 7838c8
	unsigned long row;
Packit 7838c8
    char          *buf;          
Packit 7838c8
    LPBITMAPINFOHEADER lpDIB; 
Packit 7838c8
    HDIB          hDIB;
Packit 7838c8
    char          *lpBits;
Packit 7838c8
    HGLOBAL       hStrip;
Packit 7838c8
    int           i,l;
Packit 7838c8
    int           Align; 
Packit 7838c8
    
Packit 7838c8
    tif = TIFFOpen(lpFileName, "r");
Packit 7838c8
    
Packit 7838c8
    if (!tif)
Packit 7838c8
        goto TiffOpenError;
Packit 7838c8
    
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);  
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);  
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);   
Packit 7838c8
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
Packit 7838c8
           
Packit 7838c8
    LineSize = TIFFScanlineSize(tif); //Number of byte in ine line
Packit 7838c8
Packit 7838c8
    SamplePerPixel = (int) (LineSize/imageWidth);
Packit 7838c8
Packit 7838c8
    //Align = Number of byte to add at the end of each line of the DIB
Packit 7838c8
    Align = 4 - (LineSize % 4);
Packit 7838c8
    if (Align == 4)	Align = 0;
Packit 7838c8
Packit 7838c8
    
Packit 7838c8
    //Create a new DIB
Packit 7838c8
    hDIB = CreateDIB((DWORD) imageWidth, (DWORD) imageLength, (WORD)
Packit 7838c8
(BitsPerSample*SamplePerPixel));
Packit 7838c8
    lpDIB  = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
Packit 7838c8
    if (!lpDIB)
Packit 7838c8
          goto OutOfDIBMemory;
Packit 7838c8
          
Packit 7838c8
    if (lpDIB)
Packit 7838c8
       lpBits = FindDIBBits((LPSTR) lpDIB);
Packit 7838c8
Packit 7838c8
    //In the tiff file the lines are save from up to down 
Packit 7838c8
	//In a DIB the lines must be save from down to up
Packit 7838c8
    if (lpBits)
Packit 7838c8
      {
Packit 7838c8
        lpBits = FindDIBBits((LPSTR) lpDIB);
Packit 7838c8
        lpBits+=((imageWidth*SamplePerPixel)+Align)*(imageLength-1);
Packit 7838c8
		//now lpBits pointe on the bottom line
Packit 7838c8
        
Packit 7838c8
        hStrip = GlobalAlloc(GHND,TIFFStripSize(tif));
Packit 7838c8
        buf = GlobalLock(hStrip);           
Packit 7838c8
        
Packit 7838c8
        if (!buf)
Packit 7838c8
           goto OutOfBufMemory;
Packit 7838c8
        
Packit 7838c8
        //PhotometricInterpretation = 2 image is RGB
Packit 7838c8
        //PhotometricInterpretation = 3 image have a color palette              
Packit 7838c8
        if (PhotometricInterpretation == 3)
Packit 7838c8
        {
Packit 7838c8
          uint16* red;
Packit 7838c8
          uint16* green;
Packit 7838c8
          uint16* blue;
Packit 7838c8
          int16 i;
Packit 7838c8
          LPBITMAPINFO lpbmi;   
Packit 7838c8
          int   Palette16Bits;          
Packit 7838c8
           
Packit 7838c8
          TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue); 
Packit 7838c8
Packit 7838c8
		  //Is the palette 16 or 8 bits ?
Packit 7838c8
          if (checkcmap(1<
Packit 7838c8
             Palette16Bits = TRUE;
Packit 7838c8
          else
Packit 7838c8
             Palette16Bits = FALSE;
Packit 7838c8
             
Packit 7838c8
          lpbmi = (LPBITMAPINFO)lpDIB;                      
Packit 7838c8
                
Packit 7838c8
          //load the palette in the DIB
Packit 7838c8
          for (i = (1<<BitsPerSample)-1; i >= 0; i--) 
Packit 7838c8
            {             
Packit 7838c8
             if (Palette16Bits)
Packit 7838c8
                {
Packit 7838c8
                  lpbmi->bmiColors[i].rgbRed =(BYTE) CVT(red[i]);
Packit 7838c8
                  lpbmi->bmiColors[i].rgbGreen = (BYTE) CVT(green[i]);
Packit 7838c8
                  lpbmi->bmiColors[i].rgbBlue = (BYTE) CVT(blue[i]);           
Packit 7838c8
                }
Packit 7838c8
             else
Packit 7838c8
                {
Packit 7838c8
                  lpbmi->bmiColors[i].rgbRed = (BYTE) red[i];
Packit 7838c8
                  lpbmi->bmiColors[i].rgbGreen = (BYTE) green[i];
Packit 7838c8
                  lpbmi->bmiColors[i].rgbBlue = (BYTE) blue[i];        
Packit 7838c8
                }
Packit 7838c8
            }  
Packit 7838c8
                 
Packit 7838c8
        }
Packit 7838c8
        
Packit 7838c8
        //read the tiff lines and save them in the DIB
Packit 7838c8
		//with RGB mode, we have to change the order of the 3 samples RGB
Packit 7838c8
<=> BGR
Packit 7838c8
        for (row = 0; row < imageLength; row += RowsPerStrip) 
Packit 7838c8
          {     
Packit 7838c8
            nrow = (row + RowsPerStrip > imageLength ? imageLength - row :
Packit 7838c8
RowsPerStrip);
Packit 7838c8
            if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
Packit 7838c8
                buf, nrow*LineSize)==-1)
Packit 7838c8
                  {
Packit 7838c8
                     goto TiffReadError;
Packit 7838c8
                  } 
Packit 7838c8
            else
Packit 7838c8
                  {  
Packit 7838c8
                    for (l = 0; l < nrow; l++) 
Packit 7838c8
                      {
Packit 7838c8
                         if (SamplePerPixel  == 3)
Packit 7838c8
                           for (i=0;i< (int) (imageWidth);i++)
Packit 7838c8
                              {
Packit 7838c8
                               lpBits[i*SamplePerPixel+0]=buf[l*LineSize+i*Sample
Packit 7838c8
PerPixel+2]; 
Packit 7838c8
                               lpBits[i*SamplePerPixel+1]=buf[l*LineSize+i*Sample
Packit 7838c8
PerPixel+1];
Packit 7838c8
                               lpBits[i*SamplePerPixel+2]=buf[l*LineSize+i*Sample
Packit 7838c8
PerPixel+0];
Packit 7838c8
                              }
Packit 7838c8
                         else
Packit 7838c8
                           memcpy(lpBits, &buf[(int) (l*LineSize)], (int)
Packit 7838c8
imageWidth*SamplePerPixel); 
Packit 7838c8
                          
Packit 7838c8
                         lpBits-=imageWidth*SamplePerPixel+Align;
Packit 7838c8
Packit 7838c8
                      }
Packit 7838c8
                 }
Packit 7838c8
          }
Packit 7838c8
        GlobalUnlock(hStrip);
Packit 7838c8
        GlobalFree(hStrip);
Packit 7838c8
        GlobalUnlock(hDIB); 
Packit 7838c8
        TIFFClose(tif);
Packit 7838c8
      }
Packit 7838c8
      
Packit 7838c8
    return hDIB;
Packit 7838c8
    
Packit 7838c8
    OutOfBufMemory:
Packit 7838c8
       
Packit 7838c8
    TiffReadError:
Packit 7838c8
       GlobalUnlock(hDIB); 
Packit 7838c8
       GlobalFree(hStrip);
Packit 7838c8
    OutOfDIBMemory:
Packit 7838c8
       TIFFClose(tif);
Packit 7838c8
    TiffOpenError:
Packit 7838c8
       return (HANDLE) 0;
Packit 7838c8
       
Packit 7838c8
         
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
static int checkcmap(int n, uint16* r, uint16* g, uint16* b)
Packit 7838c8
{
Packit 7838c8
    while (n-- > 0)
Packit 7838c8
        if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
Packit 7838c8
        return (16);
Packit 7838c8
    
Packit 7838c8
    return (8);
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
Packit 7838c8
/*************************************************************************
Packit 7838c8
 * All the following functions were created by microsoft, they are
Packit 7838c8
 * parts of the sample project "wincap" given with the SDK Win32.
Packit 7838c8
 *
Packit 7838c8
 * Microsoft says that :
Packit 7838c8
 *
Packit 7838c8
 *  You have a royalty-free right to use, modify, reproduce and
Packit 7838c8
 *  distribute the Sample Files (and/or any modified version) in
Packit 7838c8
 *  any way you find useful, provided that you agree that
Packit 7838c8
 *  Microsoft has no warranty obligations or liability for any
Packit 7838c8
 *  Sample Application Files which are modified.
Packit 7838c8
 *
Packit 7838c8
 ************************************************************************/
Packit 7838c8
Packit 7838c8
HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
Packit 7838c8
{
Packit 7838c8
   BITMAPINFOHEADER bi;         // bitmap header
Packit 7838c8
   LPBITMAPINFOHEADER lpbi;     // pointer to BITMAPINFOHEADER
Packit 7838c8
   DWORD dwLen;                 // size of memory block
Packit 7838c8
   HDIB hDIB;
Packit 7838c8
   DWORD dwBytesPerLine;        // Number of bytes per scanline
Packit 7838c8
Packit 7838c8
Packit 7838c8
   // Make sure bits per pixel is valid
Packit 7838c8
   if (wBitCount <= 1)
Packit 7838c8
      wBitCount = 1;
Packit 7838c8
   else if (wBitCount <= 4)
Packit 7838c8
      wBitCount = 4;
Packit 7838c8
   else if (wBitCount <= 8)
Packit 7838c8
      wBitCount = 8;
Packit 7838c8
   else if (wBitCount <= 24)
Packit 7838c8
      wBitCount = 24;
Packit 7838c8
   else
Packit 7838c8
      wBitCount = 4;  // set default value to 4 if parameter is bogus
Packit 7838c8
Packit 7838c8
   // initialize BITMAPINFOHEADER
Packit 7838c8
   bi.biSize = sizeof(BITMAPINFOHEADER);
Packit 7838c8
   bi.biWidth = dwWidth;         // fill in width from parameter
Packit 7838c8
   bi.biHeight = dwHeight;       // fill in height from parameter
Packit 7838c8
   bi.biPlanes = 1;              // must be 1
Packit 7838c8
   bi.biBitCount = wBitCount;    // from parameter
Packit 7838c8
   bi.biCompression = BI_RGB;    
Packit 7838c8
   bi.biSizeImage = (dwWidth*dwHeight*wBitCount)/8; //0;           // 0's here
Packit 7838c8
mean "default"
Packit 7838c8
   bi.biXPelsPerMeter = 2834; //0;
Packit 7838c8
   bi.biYPelsPerMeter = 2834; //0;
Packit 7838c8
   bi.biClrUsed = 0;
Packit 7838c8
   bi.biClrImportant = 0;
Packit 7838c8
Packit 7838c8
   // calculate size of memory block required to store the DIB.  This
Packit 7838c8
   // block should be big enough to hold the BITMAPINFOHEADER, the color
Packit 7838c8
   // table, and the bits
Packit 7838c8
Packit 7838c8
   dwBytesPerLine =   (((wBitCount * dwWidth) + 31) / 32 * 4);
Packit 7838c8
   dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
Packit 7838c8
Packit 7838c8
   // alloc memory block to store our bitmap
Packit 7838c8
   hDIB = GlobalAlloc(GHND, dwLen);
Packit 7838c8
Packit 7838c8
   // major bummer if we couldn't get memory block
Packit 7838c8
   if (!hDIB)
Packit 7838c8
   {
Packit 7838c8
      return NULL;
Packit 7838c8
   }
Packit 7838c8
Packit 7838c8
   // lock memory and get pointer to it
Packit 7838c8
   lpbi = (VOID FAR *)GlobalLock(hDIB);
Packit 7838c8
Packit 7838c8
   // use our bitmap info structure to fill in first part of
Packit 7838c8
   // our DIB with the BITMAPINFOHEADER
Packit 7838c8
   *lpbi = bi;
Packit 7838c8
Packit 7838c8
   // Since we don't know what the colortable and bits should contain,
Packit 7838c8
   // just leave these blank.  Unlock the DIB and return the HDIB.
Packit 7838c8
Packit 7838c8
   GlobalUnlock(hDIB);
Packit 7838c8
Packit 7838c8
   /* return handle to the DIB */
Packit 7838c8
   return hDIB;
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
LPSTR FAR FindDIBBits(LPSTR lpDIB)
Packit 7838c8
{
Packit 7838c8
   return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
WORD FAR PaletteSize(LPSTR lpDIB)
Packit 7838c8
{
Packit 7838c8
   /* calculate the size required by the palette */
Packit 7838c8
   if (IS_WIN30_DIB (lpDIB))
Packit 7838c8
      return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
Packit 7838c8
   else
Packit 7838c8
      return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
Packit 7838c8
}
Packit 7838c8
Packit 7838c8
Packit 7838c8
WORD DIBNumColors(LPSTR lpDIB)
Packit 7838c8
{
Packit 7838c8
   WORD wBitCount;  // DIB bit count
Packit 7838c8
Packit 7838c8
   /*  If this is a Windows-style DIB, the number of colors in the
Packit 7838c8
    *  color table can be less than the number of bits per pixel
Packit 7838c8
    *  allows for (i.e. lpbi->biClrUsed can be set to some value).
Packit 7838c8
    *  If this is the case, return the appropriate value.
Packit 7838c8
    */
Packit 7838c8
Packit 7838c8
   if (IS_WIN30_DIB(lpDIB))
Packit 7838c8
   {
Packit 7838c8
      DWORD dwClrUsed;
Packit 7838c8
Packit 7838c8
      dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
Packit 7838c8
      if (dwClrUsed)
Packit 7838c8
     return (WORD)dwClrUsed;
Packit 7838c8
   }
Packit 7838c8
Packit 7838c8
   /*  Calculate the number of colors in the color table based on
Packit 7838c8
    *  the number of bits per pixel for the DIB.
Packit 7838c8
    */
Packit 7838c8
   if (IS_WIN30_DIB(lpDIB))
Packit 7838c8
      wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
Packit 7838c8
   else
Packit 7838c8
      wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
Packit 7838c8
Packit 7838c8
   /* return number of colors based on bits per pixel */
Packit 7838c8
   switch (wBitCount)
Packit 7838c8
      {
Packit 7838c8
   case 1:
Packit 7838c8
      return 2;
Packit 7838c8
Packit 7838c8
   case 4:
Packit 7838c8
      return 16;
Packit 7838c8
Packit 7838c8
   case 8:
Packit 7838c8
      return 256;
Packit 7838c8
Packit 7838c8
   default:
Packit 7838c8
      return 0;
Packit 7838c8
      }
Packit 7838c8
}
Packit 7838c8
/*
Packit 7838c8
 * Local Variables:
Packit 7838c8
 * mode: c
Packit 7838c8
 * c-basic-offset: 8
Packit 7838c8
 * fill-column: 78
Packit 7838c8
 * End:
Packit 7838c8
 */