]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
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 | ||
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 | ||
314 | LPSTR FAR FindDIBBits(LPSTR lpDIB) | |
315 | { | |
316 | return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB)); | |
317 | } | |
318 | ||
319 | ||
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 | ||
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 | } |