]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/tiff/contrib/win_dib/tiff2dib.c
Merge in from trunk r64802 - r68625
[wxWidgets.git] / src / tiff / contrib / win_dib / tiff2dib.c
... / ...
CommitLineData
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
29static HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount);
30static LPSTR FindDIBBits(LPSTR lpDIB);
31static WORD PaletteSize(LPSTR lpDIB);
32static WORD DIBNumColors(LPSTR lpDIB);
33static 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
59HDIB 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 :
170RowsPerStrip);
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
184PerPixel+2];
185 lpBits[i*SamplePerPixel+1]=buf[l*LineSize+i*Sample
186PerPixel+1];
187 lpBits[i*SamplePerPixel+2]=buf[l*LineSize+i*Sample
188PerPixel+0];
189 }
190 else
191 memcpy(lpBits, &buf[(int) (l*LineSize)], (int)
192imageWidth*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
221static 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
246HDIB 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
275mean "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
314LPSTR FAR FindDIBBits(LPSTR lpDIB)
315{
316 return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
317}
318
319
320WORD 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
330WORD 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}