Leptonica  1.82.0
Image processing and image analysis suite
leptwin.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
40 #ifdef _WIN32
41 #include <stdlib.h>
42 #include <string.h>
43 #include "allheaders.h"
44 #include "leptwin.h"
45 
46 /* Macro to determine the number of bytes per line in the DIB bits.
47  * This accounts for DWORD alignment by adding 31 bits,
48  * then dividing by 32, then rounding up to the next highest
49  * count of 4-bytes. Then, we multiply by 4 to get the total byte count. */
50 #define BYTESPERLINE(Width, BPP) ((l_int32)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
51 
52 
53 /* **********************************************************************
54  DWORD DSImageBitsSize(LPBITMAPINFO pbmi)
55 
56  PARAMETERS:
57  LPBITMAPINFO - pointer to a BITMAPINFO describing a DIB
58 
59  RETURNS:
60  DWORD - the size, in bytes, of the DIB's image bits
61 
62  REMARKS:
63  Calculates and returns the size, in bytes, of the image bits for
64  the DIB described by the BITMAPINFO.
65 ********************************************************************** */
66 static DWORD
67 DSImageBitsSize(LPBITMAPINFO pbmi)
68 {
69  switch(pbmi->bmiHeader.biCompression)
70  {
71  case BI_RLE8: /* wrong if haven't called DSCreateDIBSection or
72  * CreateDIBSection with this pbmi */
73  case BI_RLE4:
74  return pbmi->bmiHeader.biSizeImage;
75  break;
76  default: /* should not have to use "default" */
77  case BI_RGB:
78  case BI_BITFIELDS:
79  return BYTESPERLINE(pbmi->bmiHeader.biWidth, \
80  pbmi->bmiHeader.biBitCount * pbmi->bmiHeader.biPlanes) *
81  pbmi->bmiHeader.biHeight;
82  break;
83  }
84  return 0;
85 }
86 
87 /* **********************************************************************
88  DWORD ImageBitsSize(HBITMAP hbitmap)
89 
90  PARAMETERS:
91  HBITMAP - hbitmap
92 
93  RETURNS:
94  DWORD - the size, in bytes, of the HBITMAP's image bits
95 
96  REMARKS:
97  Calculates and returns the size, in bytes, of the image bits for
98  the DIB described by the HBITMAP.
99 ********************************************************************** */
100 static DWORD
101 ImageBitsSize(HBITMAP hBitmap)
102 {
103  DIBSECTION ds;
104 
105  GetObject(hBitmap, sizeof(DIBSECTION), &ds);
106  switch( ds.dsBmih.biCompression )
107  {
108  case BI_RLE8: /* wrong if haven't called DSCreateDIBSection or
109  * CreateDIBSection with this pbmi */
110  case BI_RLE4:
111  return ds.dsBmih.biSizeImage;
112  break;
113  default: /* should not have to use "default" */
114  case BI_RGB:
115  case BI_BITFIELDS:
116  return BYTESPERLINE(ds.dsBmih.biWidth, \
117  ds.dsBmih.biBitCount * ds.dsBmih.biPlanes) *
118  ds.dsBmih.biHeight;
119  break;
120  }
121  return 0;
122 }
123 
131 static int
132 setColormap(LPBITMAPINFO pbmi,
133  PIXCMAP *cmap)
134 {
135 l_int32 i, nColors, rval, gval, bval;
136 
137  nColors = pixcmapGetCount(cmap);
138  for (i = 0; i < nColors; i++) {
139  pixcmapGetColor(cmap, i, &rval, &gval, &bval);
140  pbmi->bmiColors[i].rgbRed = rval;
141  pbmi->bmiColors[i].rgbGreen = gval;
142  pbmi->bmiColors[i].rgbBlue = bval;
143  pbmi->bmiColors[i].rgbReserved = 0;
144  }
145  pbmi->bmiHeader.biClrUsed = nColors;
146  return nColors;
147 }
148 
149 /* **********************************************************************
150  HBITMAP DSCreateBitmapInfo(l_int32 width, l_int32 height, l_int32 depth,
151  PIXCMAP *cmap)
152 
153  PARAMETERS:
154  l_int32 width - Desired width of the DIBSection
155  l_int32 height - Desired height of the DIBSection
156  l_int32 depth - Desired bit-depth of the DIBSection
157  PIXCMAP cmap - leptonica colormap for depths < 16
158 
159  RETURNS:
160  LPBITMAPINFO - a ptr to BITMAPINFO of the desired size and bit-depth
161  NULL on failure
162 
163  REMARKS:
164  Creates a BITMAPINFO based on the criteria passed in as parameters.
165 
166 ********************************************************************** */
167 static LPBITMAPINFO
168 DSCreateBitmapInfo(l_int32 width,
169  l_int32 height,
170  l_int32 depth,
171  PIXCMAP *cmap)
172 {
173 l_int32 nInfoSize;
174 LPBITMAPINFO pbmi;
175 LPDWORD pMasks;
176 
177  nInfoSize = sizeof(BITMAPINFOHEADER);
178  if( depth <= 8 )
179  nInfoSize += sizeof(RGBQUAD) * (1 << depth);
180  if((depth == 16) || (depth == 32))
181  nInfoSize += (3 * sizeof(DWORD));
182 
183  /* Create the header big enough to contain color table and
184  * bitmasks if needed. */
185  pbmi = (LPBITMAPINFO)malloc(nInfoSize);
186  if (!pbmi)
187  return NULL;
188 
189  ZeroMemory(pbmi, nInfoSize);
190  pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
191  pbmi->bmiHeader.biWidth = width;
192  pbmi->bmiHeader.biHeight = height;
193  pbmi->bmiHeader.biPlanes = 1;
194  pbmi->bmiHeader.biBitCount = depth;
195 
196  /* override below for 16 and 32 bpp */
197  pbmi->bmiHeader.biCompression = BI_RGB;
198 
199  /* ?? not sure if this is right? */
200  pbmi->bmiHeader.biSizeImage = DSImageBitsSize(pbmi);
201 
202  pbmi->bmiHeader.biXPelsPerMeter = 0;
203  pbmi->bmiHeader.biYPelsPerMeter = 0;
204  pbmi->bmiHeader.biClrUsed = 0; /* override below */
205  pbmi->bmiHeader.biClrImportant = 0;
206 
207  switch(depth)
208  {
209  case 24:
210  /* 24bpp requires no special handling */
211  break;
212  case 16:
213  /* if it's 16bpp, fill in the masks and override the
214  * compression. These are the default masks -- you
215  * could change them if needed. */
216  pMasks = (LPDWORD)(pbmi->bmiColors);
217  pMasks[0] = 0x00007c00;
218  pMasks[1] = 0x000003e0;
219  pMasks[2] = 0x0000001f;
220  pbmi->bmiHeader.biCompression = BI_BITFIELDS;
221  break;
222  case 32:
223  /* if it's 32 bpp, fill in the masks and override
224  * the compression */
225  pMasks = (LPDWORD)(pbmi->bmiColors);
226  /*pMasks[0] = 0x00ff0000; */
227  /*pMasks[1] = 0x0000ff00; */
228  /*pMasks[2] = 0x000000ff; */
229  pMasks[0] = 0xff000000;
230  pMasks[1] = 0x00ff0000;
231  pMasks[2] = 0x0000ff00;
232 
233  pbmi->bmiHeader.biCompression = BI_BITFIELDS;
234  break;
235  case 8:
236  case 4:
237  case 1:
238  setColormap(pbmi, cmap);
239  break;
240  }
241  return pbmi;
242 }
243 
244 /* **********************************************************************
245  HBITMAP DSCreateDIBSection(l_int32 width, l_int32 height, l_int32 depth,
246  PIXCMAP *cmap)
247 
248  PARAMETERS:
249  l_int32 width - Desired width of the DIBSection
250  l_int32 height - Desired height of the DIBSection
251  l_int32 depth - Desired bit-depth of the DIBSection
252  PIXCMAP cmap - leptonica colormap for depths < 16
253 
254  RETURNS:
255  HBITMAP - a DIBSection HBITMAP of the desired size and bit-depth
256  NULL on failure
257 
258  REMARKS:
259  Creates a DIBSection based on the criteria passed in as parameters.
260 
261 ********************************************************************** */
262 static HBITMAP
263 DSCreateDIBSection(l_int32 width,
264  l_int32 height,
265  l_int32 depth,
266  PIXCMAP *cmap)
267 {
268 HBITMAP hBitmap;
269 l_int32 nInfoSize;
270 LPBITMAPINFO pbmi;
271 HDC hRefDC;
272 LPBYTE pBits;
273 
274  pbmi = DSCreateBitmapInfo (width, height, depth, cmap);
275  if (!pbmi)
276  return NULL;
277 
278  hRefDC = GetDC(NULL);
279  hBitmap = CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS,
280  (void **) &pBits, NULL, 0);
281  nInfoSize = GetLastError();
282  ReleaseDC(NULL, hRefDC);
283  free(pbmi);
284 
285  return hBitmap;
286 }
287 
288 
302 HBITMAP
303 pixGetWindowsHBITMAP(PIX *pix)
304 {
305 l_int32 width, height, depth;
306 l_uint32 *data;
307 HBITMAP hBitmap = NULL;
308 BITMAP bm;
309 DWORD imageBitsSize;
310 PIX *pixt = NULL;
311 PIXCMAP *cmap;
312 
313  PROCNAME("pixGetWindowsHBITMAP");
314  if (!pix)
315  return (HBITMAP)ERROR_PTR("pix not defined", procName, NULL);
316 
317  pixGetDimensions(pix, &width, &height, &depth);
318  cmap = pixGetColormap(pix);
319 
320  if (depth == 24) depth = 32;
321  if (depth == 2) {
322  pixt = pixConvert2To8(pix, 0, 85, 170, 255, TRUE);
323  if (!pixt)
324  return (HBITMAP)ERROR_PTR("unable to convert pix from 2bpp to 8bpp",
325  procName, NULL);
326  depth = pixGetDepth(pixt);
327  cmap = pixGetColormap(pixt);
328  }
329 
330  if (depth < 16) {
331  if (!cmap)
332  cmap = pixcmapCreateLinear(depth, 1<<depth);
333  }
334 
335  hBitmap = DSCreateDIBSection(width, height, depth, cmap);
336  if (!hBitmap)
337  return (HBITMAP)ERROR_PTR("Unable to create HBITMAP", procName, NULL);
338 
339  /* By default, Windows assumes bottom up images */
340  if (pixt)
341  pixt = pixFlipTB(pixt, pixt);
342  else
343  pixt = pixFlipTB(NULL, pix);
344 
345  /* "standard" color table assumes bit off=black */
346  if (depth == 1) {
347  pixInvert(pixt, pixt);
348  }
349 
350  /* Don't byte swap until done manipulating pix! */
351  if (depth <= 16)
352  pixEndianByteSwap(pixt);
353 
354  GetObject (hBitmap, sizeof(BITMAP), &bm);
355  imageBitsSize = ImageBitsSize(hBitmap);
356  data = pixGetData(pixt);
357  if (data) {
358  memcpy (bm.bmBits, data, imageBitsSize);
359  } else {
360  DeleteObject (hBitmap);
361  hBitmap = NULL;
362  }
363  pixDestroy(&pixt);
364 
365  return hBitmap;
366 }
367 
368 #endif /* _WIN32 */
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:708
l_ok pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
pixcmapGetColor()
Definition: colormap.c:824
PIXCMAP * pixcmapCreateLinear(l_int32 d, l_int32 nlevels)
pixcmapCreateLinear()
Definition: colormap.c:218
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
Definition: pix2.c:3074
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition: pixconv.c:2492
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:605
Definition: pix.h:139