1 /*************************************************************************
2  *
3  * Source file for Windows 95/Win32.
4  *
5  * The function LoadTIFFinDIB in this source file let you load
6  * a TIFF file and build a memory DIB with it and return the
7  * HANDLE (HDIB) of the memory bloc containing the DIB.
8  *
9  *  Example :
10  *
11  *   HDIB   hDIB;
12  *   hDIB = LoadTIFFinDIB("sample.tif");
13  *
14  *
15  * To build this source file you must include the TIFF library
16  * in your project.
17  *
18  * 4/12/95   Philippe Tenenhaus   100423.3705@compuserve.com
19  *
20  ************************************************************************/
21 
22 
23 #include "tiffio.h"
24 
25 #define HDIB HANDLE
26 #define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
27 #define CVT(x)      (((x) * 255L) / ((1L<<16)-1))
28 
29 static HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount);
30 static LPSTR FindDIBBits(LPSTR lpDIB);
31 static WORD PaletteSize(LPSTR lpDIB);
32 static WORD DIBNumColors(LPSTR lpDIB);
33 static int checkcmap(int n, uint16* r, uint16* g, uint16* b);
34 
35 
36 
37 /*************************************************************************
38  *
39  * HDIB LoadTIFFinDIB(LPSTR lpFileName)
40  *
41  * Parameter:
42  *
43  * LPSTR lpDIB      - File name of a tiff imag
44  *
45  * Return Value:
46  *
47  * LPSTR            - HANDLE of a DIB
48  *
49  * Description:
50  *
51  * This function load a TIFF file and build a memory DIB with it
52  * and return the HANDLE (HDIB) of the memory bloc containing
53  * the DIB.
54  *
55  * 4/12/95   Philippe Tenenhaus   100423.3705@compuserve.com
56  *
57  ************************************************************************/
58 
LoadTIFFinDIB(LPSTR lpFileName)59 HDIB LoadTIFFinDIB(LPSTR lpFileName)
60 {
61     TIFF          *tif;
62     unsigned long imageLength;
63     unsigned long imageWidth;
64     unsigned int  BitsPerSample;
65     unsigned long LineSize;
66     unsigned int  SamplePerPixel;
67     unsigned long RowsPerStrip;
68     int           PhotometricInterpretation;
69     long          nrow;
70 	unsigned long row;
71     char          *buf;
72     LPBITMAPINFOHEADER lpDIB;
73     HDIB          hDIB;
74     char          *lpBits;
75     HGLOBAL       hStrip;
76     int           i,l;
77     int           Align;
78 
79     tif = TIFFOpen(lpFileName, "r");
80 
81     if (!tif)
82         goto TiffOpenError;
83 
84     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
85     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
86     TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
87     TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
88     TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
89     TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
90 
91     LineSize = TIFFScanlineSize(tif); //Number of byte in ine line
92 
93     SamplePerPixel = (int) (LineSize/imageWidth);
94 
95     //Align = Number of byte to add at the end of each line of the DIB
96     Align = 4 - (LineSize % 4);
97     if (Align == 4)	Align = 0;
98 
99 
100     //Create a new DIB
101     hDIB = CreateDIB((DWORD) imageWidth, (DWORD) imageLength, (WORD)
102 (BitsPerSample*SamplePerPixel));
103     lpDIB  = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
104     if (!lpDIB)
105           goto OutOfDIBMemory;
106 
107     if (lpDIB)
108        lpBits = FindDIBBits((LPSTR) lpDIB);
109 
110     //In the tiff file the lines are save from up to down
111 	//In a DIB the lines must be save from down to up
112     if (lpBits)
113       {
114         lpBits = FindDIBBits((LPSTR) lpDIB);
115         lpBits+=((imageWidth*SamplePerPixel)+Align)*(imageLength-1);
116 		//now lpBits pointe on the bottom line
117 
118         hStrip = GlobalAlloc(GHND,TIFFStripSize(tif));
119         buf = GlobalLock(hStrip);
120 
121         if (!buf)
122            goto OutOfBufMemory;
123 
124         //PhotometricInterpretation = 2 image is RGB
125         //PhotometricInterpretation = 3 image have a color palette
126         if (PhotometricInterpretation == 3)
127         {
128           uint16* red;
129           uint16* green;
130           uint16* blue;
131           int16 i;
132           LPBITMAPINFO lpbmi;
133           int   Palette16Bits;
134 
135           TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);
136 
137 		  //Is the palette 16 or 8 bits ?
138           if (checkcmap(1<<BitsPerSample, red, green, blue) == 16)
139              Palette16Bits = TRUE;
140           else
141              Palette16Bits = FALSE;
142 
143           lpbmi = (LPBITMAPINFO)lpDIB;
144 
145           //load the palette in the DIB
146           for (i = (1<<BitsPerSample)-1; i >= 0; i--)
147             {
148              if (Palette16Bits)
149                 {
150                   lpbmi->bmiColors[i].rgbRed =(BYTE) CVT(red[i]);
151                   lpbmi->bmiColors[i].rgbGreen = (BYTE) CVT(green[i]);
152                   lpbmi->bmiColors[i].rgbBlue = (BYTE) CVT(blue[i]);
153                 }
154              else
155                 {
156                   lpbmi->bmiColors[i].rgbRed = (BYTE) red[i];
157                   lpbmi->bmiColors[i].rgbGreen = (BYTE) green[i];
158                   lpbmi->bmiColors[i].rgbBlue = (BYTE) blue[i];
159                 }
160             }
161 
162         }
163 
164         //read the tiff lines and save them in the DIB
165 		//with RGB mode, we have to change the order of the 3 samples RGB
166 <=> BGR
167         for (row = 0; row < imageLength; row += RowsPerStrip)
168           {
169             nrow = (row + RowsPerStrip > imageLength ? imageLength - row :
170 RowsPerStrip);
171             if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
172                 buf, nrow*LineSize)==-1)
173                   {
174                      goto TiffReadError;
175                   }
176             else
177                   {
178                     for (l = 0; l < nrow; l++)
179                       {
180                          if (SamplePerPixel  == 3)
181                            for (i=0;i< (int) (imageWidth);i++)
182                               {
183                                lpBits[i*SamplePerPixel+0]=buf[l*LineSize+i*Sample
184 PerPixel+2];
185                                lpBits[i*SamplePerPixel+1]=buf[l*LineSize+i*Sample
186 PerPixel+1];
187                                lpBits[i*SamplePerPixel+2]=buf[l*LineSize+i*Sample
188 PerPixel+0];
189                               }
190                          else
191                            memcpy(lpBits, &buf[(int) (l*LineSize)], (int)
192 imageWidth*SamplePerPixel);
193 
194                          lpBits-=imageWidth*SamplePerPixel+Align;
195 
196                       }
197                  }
198           }
199         GlobalUnlock(hStrip);
200         GlobalFree(hStrip);
201         GlobalUnlock(hDIB);
202         TIFFClose(tif);
203       }
204 
205     return hDIB;
206 
207     OutOfBufMemory:
208 
209     TiffReadError:
210        GlobalUnlock(hDIB);
211        GlobalFree(hStrip);
212     OutOfDIBMemory:
213        TIFFClose(tif);
214     TiffOpenError:
215        return (HANDLE) 0;
216 
217 
218 }
219 
220 
checkcmap(int n,uint16 * r,uint16 * g,uint16 * b)221 static int checkcmap(int n, uint16* r, uint16* g, uint16* b)
222 {
223     while (n-- > 0)
224         if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
225         return (16);
226 
227     return (8);
228 }
229 
230 
231 
232 /*************************************************************************
233  * All the following functions were created by microsoft, they are
234  * parts of the sample project "wincap" given with the SDK Win32.
235  *
236  * Microsoft says that :
237  *
238  *  You have a royalty-free right to use, modify, reproduce and
239  *  distribute the Sample Files (and/or any modified version) in
240  *  any way you find useful, provided that you agree that
241  *  Microsoft has no warranty obligations or liability for any
242  *  Sample Application Files which are modified.
243  *
244  ************************************************************************/
245 
CreateDIB(DWORD dwWidth,DWORD dwHeight,WORD wBitCount)246 HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
247 {
248    BITMAPINFOHEADER bi;         // bitmap header
249    LPBITMAPINFOHEADER lpbi;     // pointer to BITMAPINFOHEADER
250    DWORD dwLen;                 // size of memory block
251    HDIB hDIB;
252    DWORD dwBytesPerLine;        // Number of bytes per scanline
253 
254 
255    // Make sure bits per pixel is valid
256    if (wBitCount <= 1)
257       wBitCount = 1;
258    else if (wBitCount <= 4)
259       wBitCount = 4;
260    else if (wBitCount <= 8)
261       wBitCount = 8;
262    else if (wBitCount <= 24)
263       wBitCount = 24;
264    else
265       wBitCount = 4;  // set default value to 4 if parameter is bogus
266 
267    // initialize BITMAPINFOHEADER
268    bi.biSize = sizeof(BITMAPINFOHEADER);
269    bi.biWidth = dwWidth;         // fill in width from parameter
270    bi.biHeight = dwHeight;       // fill in height from parameter
271    bi.biPlanes = 1;              // must be 1
272    bi.biBitCount = wBitCount;    // from parameter
273    bi.biCompression = BI_RGB;
274    bi.biSizeImage = (dwWidth*dwHeight*wBitCount)/8; //0;           // 0's here
275 mean "default"
276    bi.biXPelsPerMeter = 2834; //0;
277    bi.biYPelsPerMeter = 2834; //0;
278    bi.biClrUsed = 0;
279    bi.biClrImportant = 0;
280 
281    // calculate size of memory block required to store the DIB.  This
282    // block should be big enough to hold the BITMAPINFOHEADER, the color
283    // table, and the bits
284 
285    dwBytesPerLine =   (((wBitCount * dwWidth) + 31) / 32 * 4);
286    dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
287 
288    // alloc memory block to store our bitmap
289    hDIB = GlobalAlloc(GHND, dwLen);
290 
291    // major bummer if we couldn't get memory block
292    if (!hDIB)
293    {
294       return NULL;
295    }
296 
297    // lock memory and get pointer to it
298    lpbi = (VOID FAR *)GlobalLock(hDIB);
299 
300    // use our bitmap info structure to fill in first part of
301    // our DIB with the BITMAPINFOHEADER
302    *lpbi = bi;
303 
304    // Since we don't know what the colortable and bits should contain,
305    // just leave these blank.  Unlock the DIB and return the HDIB.
306 
307    GlobalUnlock(hDIB);
308 
309    /* return handle to the DIB */
310    return hDIB;
311 }
312 
313 
FindDIBBits(LPSTR lpDIB)314 LPSTR FAR FindDIBBits(LPSTR lpDIB)
315 {
316    return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
317 }
318 
319 
PaletteSize(LPSTR lpDIB)320 WORD FAR PaletteSize(LPSTR lpDIB)
321 {
322    /* calculate the size required by the palette */
323    if (IS_WIN30_DIB (lpDIB))
324       return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
325    else
326       return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
327 }
328 
329 
DIBNumColors(LPSTR lpDIB)330 WORD DIBNumColors(LPSTR lpDIB)
331 {
332    WORD wBitCount;  // DIB bit count
333 
334    /*  If this is a Windows-style DIB, the number of colors in the
335     *  color table can be less than the number of bits per pixel
336     *  allows for (i.e. lpbi->biClrUsed can be set to some value).
337     *  If this is the case, return the appropriate value.
338     */
339 
340    if (IS_WIN30_DIB(lpDIB))
341    {
342       DWORD dwClrUsed;
343 
344       dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
345       if (dwClrUsed)
346      return (WORD)dwClrUsed;
347    }
348 
349    /*  Calculate the number of colors in the color table based on
350     *  the number of bits per pixel for the DIB.
351     */
352    if (IS_WIN30_DIB(lpDIB))
353       wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
354    else
355       wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
356 
357    /* return number of colors based on bits per pixel */
358    switch (wBitCount)
359       {
360    case 1:
361       return 2;
362 
363    case 4:
364       return 16;
365 
366    case 8:
367       return 256;
368 
369    default:
370       return 0;
371       }
372 }
373 /*
374  * Local Variables:
375  * mode: c
376  * c-basic-offset: 8
377  * fill-column: 78
378  * End:
379  */
380