comparison mupdf-source/thirdparty/leptonica/src/leptwin.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
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
27 /*!
28 * \file leptwin.c
29 * <pre>
30 *
31 * This file contains Leptonica routines needed only on Microsoft Windows
32 *
33 * Currently it only contains one public function
34 * (based on dibsectn.c by jmh, 03-30-98):
35 *
36 * HBITMAP pixGetWindowsHBITMAP(PIX *pix)
37 * </pre>
38 */
39
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
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 }
83 }
84
85 /* **********************************************************************
86 DWORD ImageBitsSize(HBITMAP hbitmap)
87
88 PARAMETERS:
89 HBITMAP - hbitmap
90
91 RETURNS:
92 DWORD - the size, in bytes, of the HBITMAP's image bits
93
94 REMARKS:
95 Calculates and returns the size, in bytes, of the image bits for
96 the DIB described by the HBITMAP.
97 ********************************************************************** */
98 static DWORD
99 ImageBitsSize(HBITMAP hBitmap)
100 {
101 DIBSECTION ds;
102
103 GetObject(hBitmap, sizeof(DIBSECTION), &ds);
104 switch( ds.dsBmih.biCompression )
105 {
106 case BI_RLE8: /* wrong if haven't called DSCreateDIBSection or
107 * CreateDIBSection with this pbmi */
108 case BI_RLE4:
109 return ds.dsBmih.biSizeImage;
110
111 default: /* should not have to use "default" */
112 case BI_RGB:
113 case BI_BITFIELDS:
114 return BYTESPERLINE(ds.dsBmih.biWidth, \
115 ds.dsBmih.biBitCount * ds.dsBmih.biPlanes) *
116 ds.dsBmih.biHeight;
117 }
118 }
119
120 /*!
121 * \brief setColormap(LPBITMAPINFO pbmi, PIXCMAP *cmap)
122 *
123 * \param[in] pbmi pointer to a BITMAPINFO describing a DIB
124 * \param[in] cmap leptonica colormap
125 * \return number of colors in cmap
126 */
127 static int
128 setColormap(LPBITMAPINFO pbmi,
129 PIXCMAP *cmap)
130 {
131 l_int32 i, nColors, rval, gval, bval;
132
133 nColors = pixcmapGetCount(cmap);
134 for (i = 0; i < nColors; i++) {
135 pixcmapGetColor(cmap, i, &rval, &gval, &bval);
136 pbmi->bmiColors[i].rgbRed = rval;
137 pbmi->bmiColors[i].rgbGreen = gval;
138 pbmi->bmiColors[i].rgbBlue = bval;
139 pbmi->bmiColors[i].rgbReserved = 0;
140 }
141 pbmi->bmiHeader.biClrUsed = nColors;
142 return nColors;
143 }
144
145 /* **********************************************************************
146 HBITMAP DSCreateBitmapInfo(l_int32 width, l_int32 height, l_int32 depth,
147 PIXCMAP *cmap)
148
149 PARAMETERS:
150 l_int32 width - Desired width of the DIBSection
151 l_int32 height - Desired height of the DIBSection
152 l_int32 depth - Desired bit-depth of the DIBSection
153 PIXCMAP cmap - leptonica colormap for depths < 16
154
155 RETURNS:
156 LPBITMAPINFO - a ptr to BITMAPINFO of the desired size and bit-depth
157 NULL on failure
158
159 REMARKS:
160 Creates a BITMAPINFO based on the criteria passed in as parameters.
161
162 ********************************************************************** */
163 static LPBITMAPINFO
164 DSCreateBitmapInfo(l_int32 width,
165 l_int32 height,
166 l_int32 depth,
167 PIXCMAP *cmap)
168 {
169 l_int32 nInfoSize;
170 LPBITMAPINFO pbmi;
171 LPDWORD pMasks;
172
173 nInfoSize = sizeof(BITMAPINFOHEADER);
174 if( depth <= 8 )
175 nInfoSize += sizeof(RGBQUAD) * (1 << depth);
176 if((depth == 16) || (depth == 32))
177 nInfoSize += (3 * sizeof(DWORD));
178
179 /* Create the header big enough to contain color table and
180 * bitmasks if needed. */
181 pbmi = (LPBITMAPINFO)malloc(nInfoSize);
182 if (!pbmi)
183 return NULL;
184
185 ZeroMemory(pbmi, nInfoSize);
186 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
187 pbmi->bmiHeader.biWidth = width;
188 pbmi->bmiHeader.biHeight = height;
189 pbmi->bmiHeader.biPlanes = 1;
190 pbmi->bmiHeader.biBitCount = depth;
191
192 /* override below for 16 and 32 bpp */
193 pbmi->bmiHeader.biCompression = BI_RGB;
194
195 /* ?? not sure if this is right? */
196 pbmi->bmiHeader.biSizeImage = DSImageBitsSize(pbmi);
197
198 pbmi->bmiHeader.biXPelsPerMeter = 0;
199 pbmi->bmiHeader.biYPelsPerMeter = 0;
200 pbmi->bmiHeader.biClrUsed = 0; /* override below */
201 pbmi->bmiHeader.biClrImportant = 0;
202
203 switch(depth)
204 {
205 case 24:
206 /* 24bpp requires no special handling */
207 break;
208 case 16:
209 /* if it's 16bpp, fill in the masks and override the
210 * compression. These are the default masks -- you
211 * could change them if needed. */
212 pMasks = (LPDWORD)(pbmi->bmiColors);
213 pMasks[0] = 0x00007c00;
214 pMasks[1] = 0x000003e0;
215 pMasks[2] = 0x0000001f;
216 pbmi->bmiHeader.biCompression = BI_BITFIELDS;
217 break;
218 case 32:
219 /* if it's 32 bpp, fill in the masks and override
220 * the compression */
221 pMasks = (LPDWORD)(pbmi->bmiColors);
222 /*pMasks[0] = 0x00ff0000; */
223 /*pMasks[1] = 0x0000ff00; */
224 /*pMasks[2] = 0x000000ff; */
225 pMasks[0] = 0xff000000;
226 pMasks[1] = 0x00ff0000;
227 pMasks[2] = 0x0000ff00;
228
229 pbmi->bmiHeader.biCompression = BI_BITFIELDS;
230 break;
231 case 8:
232 case 4:
233 case 1:
234 setColormap(pbmi, cmap);
235 break;
236 }
237 return pbmi;
238 }
239
240 /* **********************************************************************
241 HBITMAP DSCreateDIBSection(l_int32 width, l_int32 height, l_int32 depth,
242 PIXCMAP *cmap)
243
244 PARAMETERS:
245 l_int32 width - Desired width of the DIBSection
246 l_int32 height - Desired height of the DIBSection
247 l_int32 depth - Desired bit-depth of the DIBSection
248 PIXCMAP cmap - leptonica colormap for depths < 16
249
250 RETURNS:
251 HBITMAP - a DIBSection HBITMAP of the desired size and bit-depth
252 NULL on failure
253
254 REMARKS:
255 Creates a DIBSection based on the criteria passed in as parameters.
256
257 ********************************************************************** */
258 static HBITMAP
259 DSCreateDIBSection(l_int32 width,
260 l_int32 height,
261 l_int32 depth,
262 PIXCMAP *cmap)
263 {
264 HBITMAP hBitmap;
265 l_int32 nInfoSize;
266 LPBITMAPINFO pbmi;
267 HDC hRefDC;
268 LPBYTE pBits;
269
270 pbmi = DSCreateBitmapInfo (width, height, depth, cmap);
271 if (!pbmi)
272 return NULL;
273
274 hRefDC = GetDC(NULL);
275 hBitmap = CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS,
276 (void **) &pBits, NULL, 0);
277 nInfoSize = GetLastError();
278 ReleaseDC(NULL, hRefDC);
279 free(pbmi);
280
281 return hBitmap;
282 }
283
284
285 /*!
286 * \brief pixGetWindowsHBITMAP()
287 *
288 * \param[in] pix
289 * \return Windows hBitmap, or NULL on error
290 *
291 * <pre>
292 * Notes:
293 * (1) It's the responsibility of the caller to destroy the
294 * returned hBitmap with a call to DeleteObject (or with
295 * something that eventually calls DeleteObject).
296 * </pre>
297 */
298 HBITMAP
299 pixGetWindowsHBITMAP(PIX *pix)
300 {
301 l_int32 width, height, depth;
302 l_uint32 *data;
303 HBITMAP hBitmap = NULL;
304 BITMAP bm;
305 DWORD imageBitsSize;
306 PIX *pixt = NULL;
307 PIXCMAP *cmap;
308
309 if (!pix)
310 return (HBITMAP)ERROR_PTR("pix not defined", __func__, NULL);
311
312 pixGetDimensions(pix, &width, &height, &depth);
313 cmap = pixGetColormap(pix);
314
315 if (depth == 24) depth = 32;
316 if (depth == 2) {
317 pixt = pixConvert2To8(pix, 0, 85, 170, 255, TRUE);
318 if (!pixt)
319 return (HBITMAP)ERROR_PTR("unable to convert pix from 2bpp to 8bpp",
320 __func__, NULL);
321 depth = pixGetDepth(pixt);
322 cmap = pixGetColormap(pixt);
323 }
324
325 if (depth < 16) {
326 if (!cmap)
327 cmap = pixcmapCreateLinear(depth, 1<<depth);
328 }
329
330 hBitmap = DSCreateDIBSection(width, height, depth, cmap);
331 if (!hBitmap)
332 return (HBITMAP)ERROR_PTR("Unable to create HBITMAP", __func__, NULL);
333
334 /* By default, Windows assumes bottom up images */
335 if (pixt)
336 pixt = pixFlipTB(pixt, pixt);
337 else
338 pixt = pixFlipTB(NULL, pix);
339
340 /* "standard" color table assumes bit off=black */
341 if (depth == 1) {
342 pixInvert(pixt, pixt);
343 }
344
345 /* Don't byte swap until done manipulating pix! */
346 if (depth <= 16)
347 pixEndianByteSwap(pixt);
348
349 GetObject (hBitmap, sizeof(BITMAP), &bm);
350 imageBitsSize = ImageBitsSize(hBitmap);
351 data = pixGetData(pixt);
352 if (data) {
353 memcpy (bm.bmBits, data, imageBitsSize);
354 } else {
355 DeleteObject (hBitmap);
356 hBitmap = NULL;
357 }
358 pixDestroy(&pixt);
359
360 return hBitmap;
361 }
362
363 #endif /* _WIN32 */