Leptonica 1.82.0
Image processing and image analysis suite
bmpio.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
42#ifdef HAVE_CONFIG_H
43#include <config_auto.h>
44#endif /* HAVE_CONFIG_H */
45
46#include <string.h>
47#include "allheaders.h"
48#include "bmp.h"
49
50/* --------------------------------------------*/
51#if USE_BMPIO /* defined in environ.h */
52/* --------------------------------------------*/
53
54 /* Here we're setting the pixel value 0 to white (255) and the
55 * value 1 to black (0). This is the convention for grayscale, but
56 * the opposite of the convention for 1 bpp, where 0 is white
57 * and 1 is black. Both colormap entries are opaque (alpha = 255) */
58RGBA_QUAD bwmap[2] = { {255,255,255,255}, {0,0,0,255} };
59
60 /* Image dimension limits */
61static const l_int32 L_MAX_ALLOWED_WIDTH = 1000000;
62static const l_int32 L_MAX_ALLOWED_HEIGHT = 1000000;
63static const l_int64 L_MAX_ALLOWED_PIXELS = 400000000LL;
64static const l_int32 L_MAX_ALLOWED_RES = 10000000; /* pixels/meter */
65
66#ifndef NO_CONSOLE_IO
67#define DEBUG 0
68#endif /* ~NO_CONSOLE_IO */
69
70/*--------------------------------------------------------------*
71 * Read bmp *
72 *--------------------------------------------------------------*/
86PIX *
88{
89l_uint8 *data;
90size_t size;
91PIX *pix;
92
93 PROCNAME("pixReadStreamBmp");
94
95 if (!fp)
96 return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
97
98 /* Read data from file and decode into Y,U,V arrays */
99 rewind(fp);
100 if ((data = l_binaryReadStream(fp, &size)) == NULL)
101 return (PIX *)ERROR_PTR("data not read", procName, NULL);
102
103 pix = pixReadMemBmp(data, size);
104 LEPT_FREE(data);
105 return pix;
106}
107
108
128PIX *
129pixReadMemBmp(const l_uint8 *cdata,
130 size_t size)
131{
132l_uint8 pel[4];
133l_uint8 *cmapBuf, *fdata, *data;
134l_int16 bftype, depth, d;
135l_int32 offset, ihbytes, width, height, height_neg, xres, yres;
136l_int32 compression, imagebytes, fdatabytes, cmapbytes, ncolors, maxcolors;
137l_int32 fdatabpl, extrabytes, pixWpl, pixBpl, i, j, k;
138l_uint32 *line, *pixdata, *pword;
139l_int64 npixels;
140BMP_FH *bmpfh;
141#if defined(__GNUC__)
142BMP_HEADER *bmph;
143#define bmpih (&bmph->bmpih)
144#else
145BMP_IH *bmpih;
146#endif
147PIX *pix, *pix1;
148PIXCMAP *cmap;
149
150 PROCNAME("pixReadMemBmp");
151
152 if (!cdata)
153 return (PIX *)ERROR_PTR("cdata not defined", procName, NULL);
154 if (size < sizeof(BMP_FH) + sizeof(BMP_IH))
155 return (PIX *)ERROR_PTR("bmf size error", procName, NULL);
156
157 /* Verify this is an uncompressed bmp */
158 bmpfh = (BMP_FH *)cdata;
159 bftype = bmpfh->bfType[0] + ((l_int32)bmpfh->bfType[1] << 8);
160 if (bftype != BMP_ID)
161 return (PIX *)ERROR_PTR("not bmf format", procName, NULL);
162#if defined(__GNUC__)
163 bmph = (BMP_HEADER *)bmpfh;
164#else
165 bmpih = (BMP_IH *)(cdata + BMP_FHBYTES);
166#endif
167 compression = convertOnBigEnd32(bmpih->biCompression);
168 if (compression != 0)
169 return (PIX *)ERROR_PTR("cannot read compressed BMP files",
170 procName, NULL);
171
172 /* Find the offset from the beginning of the file to the image data */
173 offset = bmpfh->bfOffBits[0];
174 offset += (l_int32)bmpfh->bfOffBits[1] << 8;
175 offset += (l_int32)bmpfh->bfOffBits[2] << 16;
176 offset += (l_uint32)bmpfh->bfOffBits[3] << 24;
177
178 /* Read the remaining useful data in the infoheader.
179 * Note that the first 4 bytes give the infoheader size. */
180 ihbytes = convertOnBigEnd32(*(l_uint32 *)(bmpih));
181 width = convertOnBigEnd32(bmpih->biWidth);
182 height = convertOnBigEnd32(bmpih->biHeight);
183 depth = convertOnBigEnd16(bmpih->biBitCount);
184 imagebytes = convertOnBigEnd32(bmpih->biSizeImage);
185 xres = convertOnBigEnd32(bmpih->biXPelsPerMeter);
186 yres = convertOnBigEnd32(bmpih->biYPelsPerMeter);
187
188 /* Some sanity checking. We impose limits on the image
189 * dimensions, resolution and number of pixels. We make sure the
190 * file is the correct size to hold the amount of uncompressed data
191 * that is specified in the header. The number of colormap
192 * entries is checked: it can be either 0 (no cmap) or some
193 * number between 2 and 256.
194 * Note that the imagebytes for uncompressed images is either
195 * 0 or the size of the file data. (The fact that it can
196 * be 0 is perhaps some legacy glitch). */
197 if (width < 1)
198 return (PIX *)ERROR_PTR("width < 1", procName, NULL);
199 if (width > L_MAX_ALLOWED_WIDTH)
200 return (PIX *)ERROR_PTR("width too large", procName, NULL);
201 if (height == 0 || height < -L_MAX_ALLOWED_HEIGHT ||
202 height > L_MAX_ALLOWED_HEIGHT)
203 return (PIX *)ERROR_PTR("invalid height", procName, NULL);
204 if (xres < 0 || xres > L_MAX_ALLOWED_RES ||
205 yres < 0 || yres > L_MAX_ALLOWED_RES)
206 return (PIX *)ERROR_PTR("invalid resolution", procName, NULL);
207 height_neg = 0;
208 if (height < 0) {
209 height_neg = 1;
210 height = -height;
211 }
212 if (ihbytes != 40 && ihbytes != 108 && ihbytes != 124) {
213 L_ERROR("invalid ihbytes = %d; not in {40, 108, 124}\n",
214 procName, ihbytes);
215 return NULL;
216 }
217 npixels = 1LL * width * height;
218 if (npixels > L_MAX_ALLOWED_PIXELS)
219 return (PIX *)ERROR_PTR("npixels too large", procName, NULL);
220 if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
221 depth != 16 && depth != 24 && depth != 32) {
222 L_ERROR("invalid depth = %d; not in {1, 2, 4, 8, 16, 24, 32}\n",
223 procName, depth);
224 return NULL;
225 }
226 fdatabpl = 4 * ((1LL * width * depth + 31)/32);
227 fdatabytes = fdatabpl * height;
228 if (imagebytes != 0 && imagebytes != fdatabytes) {
229 L_ERROR("invalid imagebytes = %d; not equal to fdatabytes = %d\n",
230 procName, imagebytes, fdatabytes);
231 return NULL;
232 }
233
234 /* In the original spec, BITMAPINFOHEADER is 40 bytes.
235 * There have been a number of revisions, to capture more information.
236 * For example, the fifth version, BITMAPV5HEADER, adds 84 bytes
237 * of ICC color profiles. We use the size of the infoheader
238 * to accommodate these newer formats. Knowing the size of the
239 * infoheader gives more opportunity to sanity check input params. */
240 cmapbytes = offset - BMP_FHBYTES - ihbytes;
241 ncolors = cmapbytes / sizeof(RGBA_QUAD);
242 if (ncolors < 0 || ncolors == 1)
243 return (PIX *)ERROR_PTR("invalid: cmap size < 0 or 1", procName, NULL);
244 if (ncolors > 0 && depth > 8)
245 return (PIX *)ERROR_PTR("can't have cmap for d > 8", procName, NULL);
246 maxcolors = (depth <= 8) ? 1 << depth : 0;
247 if (ncolors > maxcolors) {
248 L_ERROR("cmap too large for depth %d: ncolors = %d > maxcolors = %d\n",
249 procName, depth, ncolors, maxcolors);
250 return NULL;
251 }
252 if (size != 1LL * offset + 1LL * fdatabytes)
253 return (PIX *)ERROR_PTR("size incommensurate with image data",
254 procName,NULL);
255
256 /* Handle the colormap */
257 cmapBuf = NULL;
258 if (ncolors > 0) {
259 if ((cmapBuf = (l_uint8 *)LEPT_CALLOC(ncolors, sizeof(RGBA_QUAD)))
260 == NULL)
261 return (PIX *)ERROR_PTR("cmapBuf alloc fail", procName, NULL );
262
263 /* Read the colormap entry data from bmp. The RGBA_QUAD colormap
264 * entries are used for both bmp and leptonica colormaps. */
265 memcpy(cmapBuf, cdata + BMP_FHBYTES + ihbytes,
266 ncolors * sizeof(RGBA_QUAD));
267 }
268
269 /* Make a 32 bpp pix if depth is 24 bpp */
270 d = (depth == 24) ? 32 : depth;
271 if ((pix = pixCreate(width, height, d)) == NULL) {
272 LEPT_FREE(cmapBuf);
273 return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
274 }
275 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5)); /* to ppi */
276 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5)); /* to ppi */
277 pixSetInputFormat(pix, IFF_BMP);
278 pixWpl = pixGetWpl(pix);
279 pixBpl = 4 * pixWpl;
280
281 /* Convert the bmp colormap to a pixcmap */
282 cmap = NULL;
283 if (ncolors > 0) { /* import the colormap to the pix cmap */
284 cmap = pixcmapCreate(L_MIN(d, 8));
285 LEPT_FREE(cmap->array); /* remove generated cmap array */
286 cmap->array = (void *)cmapBuf; /* and replace */
287 cmap->n = L_MIN(ncolors, 256);
288 for (i = 0; i < cmap->n; i++) /* set all colors opaque */
289 pixcmapSetAlpha (cmap, i, 255);
290 }
291 if (pixSetColormap(pix, cmap)) {
292 pixDestroy(&pix);
293 return (PIX *)ERROR_PTR("invalid colormap", procName, NULL);
294 }
295
296 /* Acquire the image data. Image origin for bmp is at lower right. */
297 fdata = (l_uint8 *)cdata + offset; /* start of the bmp image data */
298 pixdata = pixGetData(pix);
299 if (depth != 24) { /* typ. 1 or 8 bpp */
300 data = (l_uint8 *)pixdata + pixBpl * (height - 1);
301 for (i = 0; i < height; i++) {
302 memcpy(data, fdata, fdatabpl);
303 fdata += fdatabpl;
304 data -= pixBpl;
305 }
306 } else { /* 24 bpp file; 32 bpp pix
307 * Note: for bmp files, pel[0] is blue, pel[1] is green,
308 * and pel[2] is red. This is opposite to the storage
309 * in the pix, which puts the red pixel in the 0 byte,
310 * the green in the 1 byte and the blue in the 2 byte.
311 * Note also that all words are endian flipped after
312 * assignment on L_LITTLE_ENDIAN platforms.
313 *
314 * We can then make these assignments for little endians:
315 * SET_DATA_BYTE(pword, 1, pel[0]); blue
316 * SET_DATA_BYTE(pword, 2, pel[1]); green
317 * SET_DATA_BYTE(pword, 3, pel[2]); red
318 * This looks like:
319 * 3 (R) 2 (G) 1 (B) 0
320 * |-----------|------------|-----------|-----------|
321 * and after byte flipping:
322 * 3 2 (B) 1 (G) 0 (R)
323 * |-----------|------------|-----------|-----------|
324 *
325 * For big endians we set:
326 * SET_DATA_BYTE(pword, 2, pel[0]); blue
327 * SET_DATA_BYTE(pword, 1, pel[1]); green
328 * SET_DATA_BYTE(pword, 0, pel[2]); red
329 * This looks like:
330 * 0 (R) 1 (G) 2 (B) 3
331 * |-----------|------------|-----------|-----------|
332 * so in both cases we get the correct assignment in the PIX.
333 *
334 * Can we do a platform-independent assignment?
335 * Yes, set the bytes without using macros:
336 * *((l_uint8 *)pword) = pel[2]; red
337 * *((l_uint8 *)pword + 1) = pel[1]; green
338 * *((l_uint8 *)pword + 2) = pel[0]; blue
339 * For little endians, before flipping, this looks again like:
340 * 3 (R) 2 (G) 1 (B) 0
341 * |-----------|------------|-----------|-----------|
342 */
343 extrabytes = fdatabpl - 3 * width;
344 line = pixdata + pixWpl * (height - 1);
345 for (i = 0; i < height; i++) {
346 for (j = 0; j < width; j++) {
347 pword = line + j;
348 memcpy(&pel, fdata, 3);
349 fdata += 3;
350 *((l_uint8 *)pword + COLOR_RED) = pel[2];
351 *((l_uint8 *)pword + COLOR_GREEN) = pel[1];
352 *((l_uint8 *)pword + COLOR_BLUE) = pel[0];
353 /* should not use alpha byte, but for buggy readers,
354 * set it to opaque */
355 *((l_uint8 *)pword + L_ALPHA_CHANNEL) = 255;
356 }
357 if (extrabytes) {
358 for (k = 0; k < extrabytes; k++) {
359 memcpy(&pel, fdata, 1);
360 fdata++;
361 }
362 }
363 line -= pixWpl;
364 }
365 }
366
368 if (height_neg)
369 pixFlipTB(pix, pix);
370
371 /* ----------------------------------------------
372 * We do not use 1 bpp pix with colormaps in leptonica.
373 * The colormap must be removed in such a way that the pixel
374 * values are not changed. If the values are only black and
375 * white, return a 1 bpp image; if gray, return an 8 bpp pix;
376 * otherwise, return a 32 bpp rgb pix.
377 * ---------------------------------------------- */
378 if (depth == 1 && cmap) {
379 L_INFO("removing opaque cmap from 1 bpp\n", procName);
381 pixDestroy(&pix);
382 pix = pix1; /* rename */
383 }
384
385 return pix;
386}
387
388
389/*--------------------------------------------------------------*
390 * Write bmp *
391 *--------------------------------------------------------------*/
399l_ok
401 PIX *pix)
402{
403l_uint8 *data;
404size_t size, nbytes;
405
406 PROCNAME("pixWriteStreamBmp");
407
408 if (!fp)
409 return ERROR_INT("stream not defined", procName, 1);
410 if (!pix)
411 return ERROR_INT("pix not defined", procName, 1);
412
413 pixWriteMemBmp(&data, &size, pix);
414 rewind(fp);
415 nbytes = fwrite(data, 1, size, fp);
416 free(data);
417 if (nbytes != size)
418 return ERROR_INT("Write error", procName, 1);
419 return 0;
420}
421
422
444l_ok
445pixWriteMemBmp(l_uint8 **pfdata,
446 size_t *pfsize,
447 PIX *pixs)
448{
449l_uint8 pel[4];
450l_uint8 *cta = NULL; /* address of the bmp color table array */
451l_uint8 *fdata, *data, *fmdata;
452l_int32 cmaplen; /* number of bytes in the bmp colormap */
453l_int32 ncolors, val, stepsize, w, h, d, fdepth, xres, yres, valid;
454l_int32 pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
455l_int32 heapcm; /* extra copy of cta on the heap ? 1 : 0 */
456l_uint32 offbytes, fimagebytes;
457l_uint32 *line, *pword;
458size_t fsize;
459BMP_FH *bmpfh;
460#if defined(__GNUC__)
461BMP_HEADER *bmph;
462#define bmpih (&bmph->bmpih)
463#else
464BMP_IH *bmpih;
465#endif
466PIX *pix;
467PIXCMAP *cmap;
468RGBA_QUAD *pquad;
469
470 PROCNAME("pixWriteMemBmp");
471
472 if (pfdata) *pfdata = NULL;
473 if (pfsize) *pfsize = 0;
474 if (!pfdata)
475 return ERROR_INT("&fdata not defined", procName, 1 );
476 if (!pfsize)
477 return ERROR_INT("&fsize not defined", procName, 1 );
478 if (!pixs)
479 return ERROR_INT("pixs not defined", procName, 1);
480
481 /* Verify validity of colormap */
482 if ((cmap = pixGetColormap(pixs)) != NULL) {
483 pixcmapIsValid(cmap, pixs, &valid);
484 if (!valid)
485 return ERROR_INT("colormap is not valid", procName, 1);
486 }
487
488 pixGetDimensions(pixs, &w, &h, &d);
489 if (d == 2) {
490 L_WARNING("2 bpp files can't be read; converting to 8 bpp\n", procName);
491 pix = pixConvert2To8(pixs, 0, 85, 170, 255, 1);
492 d = 8;
493 } else {
494 pix = pixCopy(NULL, pixs);
495 }
496 fdepth = (d == 32) ? 24 : d;
497
498 /* Resolution is given in pixels/meter */
499 xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
500 yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
501
502 pixWpl = pixGetWpl(pix);
503 pixBpl = 4 * pixWpl;
504 fWpl = (w * fdepth + 31) / 32;
505 fBpl = 4 * fWpl;
506 fimagebytes = h * fBpl;
507 if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
508 pixDestroy(&pix);
509 return ERROR_INT("image data is too large", procName, 1);
510 }
511
512 /* If not rgb or 16 bpp, the bmp data is required to have a colormap */
513 heapcm = 0;
514 if (d == 32 || d == 16) { /* 24 bpp rgb or 16 bpp: no colormap */
515 ncolors = 0;
516 cmaplen = 0;
517 } else if ((cmap = pixGetColormap(pix))) { /* existing colormap */
518 ncolors = pixcmapGetCount(cmap);
519 cmaplen = ncolors * sizeof(RGBA_QUAD);
520 cta = (l_uint8 *)cmap->array;
521 } else { /* no existing colormap; d <= 8; make a binary or gray one */
522 if (d == 1) {
523 cmaplen = sizeof(bwmap);
524 ncolors = 2;
525 cta = (l_uint8 *)bwmap;
526 } else { /* d = 2,4,8; use a grayscale output colormap */
527 ncolors = 1 << fdepth;
528 cmaplen = ncolors * sizeof(RGBA_QUAD);
529 heapcm = 1;
530 cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
531 stepsize = 255 / (ncolors - 1);
532 for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta;
533 i < ncolors;
534 i++, val += stepsize, pquad++) {
535 pquad->blue = pquad->green = pquad->red = val;
536 pquad->alpha = 255; /* opaque */
537 }
538 }
539 }
540
541#if DEBUG
542 {l_uint8 *pcmptr;
543 pcmptr = (l_uint8 *)pixGetColormap(pix)->array;
544 lept_stderr("Pix colormap[0] = %c%c%c%d\n",
545 pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
546 lept_stderr("Pix colormap[1] = %c%c%c%d\n",
547 pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
548 }
549#endif /* DEBUG */
550
551 offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen;
552 fsize = offbytes + fimagebytes;
553 fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
554 *pfdata = fdata;
555 *pfsize = fsize;
556
557 /* Write little-endian file header data */
558 bmpfh = (BMP_FH *)fdata;
559 bmpfh->bfType[0] = (l_uint8)(BMP_ID >> 0);
560 bmpfh->bfType[1] = (l_uint8)(BMP_ID >> 8);
561 bmpfh->bfSize[0] = (l_uint8)(fsize >> 0);
562 bmpfh->bfSize[1] = (l_uint8)(fsize >> 8);
563 bmpfh->bfSize[2] = (l_uint8)(fsize >> 16);
564 bmpfh->bfSize[3] = (l_uint8)(fsize >> 24);
565 bmpfh->bfOffBits[0] = (l_uint8)(offbytes >> 0);
566 bmpfh->bfOffBits[1] = (l_uint8)(offbytes >> 8);
567 bmpfh->bfOffBits[2] = (l_uint8)(offbytes >> 16);
568 bmpfh->bfOffBits[3] = (l_uint8)(offbytes >> 24);
569
570 /* Convert to little-endian and write the info header data */
571#if defined(__GNUC__)
572 bmph = (BMP_HEADER *)bmpfh;
573#else
574 bmpih = (BMP_IH *)(fdata + BMP_FHBYTES);
575#endif
576 bmpih->biSize = convertOnBigEnd32(BMP_IHBYTES);
577 bmpih->biWidth = convertOnBigEnd32(w);
578 bmpih->biHeight = convertOnBigEnd32(h);
579 bmpih->biPlanes = convertOnBigEnd16(1);
580 bmpih->biBitCount = convertOnBigEnd16(fdepth);
581 bmpih->biSizeImage = convertOnBigEnd32(fimagebytes);
582 bmpih->biXPelsPerMeter = convertOnBigEnd32(xres);
583 bmpih->biYPelsPerMeter = convertOnBigEnd32(yres);
584 bmpih->biClrUsed = convertOnBigEnd32(ncolors);
585 bmpih->biClrImportant = convertOnBigEnd32(ncolors);
586
587 /* Copy the colormap data and free the cta if necessary */
588 if (ncolors > 0) {
589 memcpy(fdata + BMP_FHBYTES + BMP_IHBYTES, cta, cmaplen);
590 if (heapcm) LEPT_FREE(cta);
591 }
592
593 /* When you write a binary image with a colormap
594 * that sets BLACK to 0, you must invert the data */
595 if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) {
596 pixInvert(pix, pix);
597 }
598
599 /* An endian byte swap is also required */
601
602 /* Transfer the image data. Image origin for bmp is at lower right. */
603 fmdata = fdata + offbytes;
604 if (fdepth != 24) { /* typ 1 or 8 bpp */
605 data = (l_uint8 *)pixGetData(pix) + pixBpl * (h - 1);
606 for (i = 0; i < h; i++) {
607 memcpy(fmdata, data, fBpl);
608 data -= pixBpl;
609 fmdata += fBpl;
610 }
611 } else { /* 32 bpp pix; 24 bpp file
612 * See the comments in pixReadStreamBmp() to
613 * understand the logic behind the pixel ordering below.
614 * Note that we have again done an endian swap on
615 * little endian machines before arriving here, so that
616 * the bytes are ordered on both platforms as:
617 Red Green Blue --
618 |-----------|------------|-----------|-----------|
619 */
620 extrabytes = fBpl - 3 * w;
621 line = pixGetData(pix) + pixWpl * (h - 1);
622 for (i = 0; i < h; i++) {
623 for (j = 0; j < w; j++) {
624 pword = line + j;
625 pel[2] = *((l_uint8 *)pword + COLOR_RED);
626 pel[1] = *((l_uint8 *)pword + COLOR_GREEN);
627 pel[0] = *((l_uint8 *)pword + COLOR_BLUE);
628 memcpy(fmdata, &pel, 3);
629 fmdata += 3;
630 }
631 if (extrabytes) {
632 for (k = 0; k < extrabytes; k++) {
633 memcpy(fmdata, &pel, 1);
634 fmdata++;
635 }
636 }
637 line -= pixWpl;
638 }
639 }
640
641 pixDestroy(&pix);
642 return 0;
643}
644
645/* --------------------------------------------*/
646#endif /* USE_BMPIO */
#define BMP_IHBYTES
Definition: bmp.h:108
#define BMP_FHBYTES
Definition: bmp.h:83
l_ok pixWriteStreamBmp(FILE *fp, PIX *pix)
pixWriteStreamBmp()
Definition: bmpio.c:400
PIX * pixReadStreamBmp(FILE *fp)
pixReadStreamBmp()
Definition: bmpio.c:87
l_ok pixWriteMemBmp(l_uint8 **pfdata, size_t *pfsize, PIX *pixs)
pixWriteMemBmp()
Definition: bmpio.c:445
PIX * pixReadMemBmp(const l_uint8 *cdata, size_t size)
pixReadMemBmp()
Definition: bmpio.c:129
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
Definition: colormap.c:1007
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:708
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
Definition: colormap.c:317
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:125
@ BMP_ID
Definition: imageio.h:126
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1699
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
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
Definition: pix2.c:3074
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
@ COLOR_BLUE
Definition: pix.h:206
@ COLOR_RED
Definition: pix.h:204
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ COLOR_GREEN
Definition: pix.h:205
@ REMOVE_CMAP_BASED_ON_SRC
Definition: pix.h:260
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
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
l_uint8 bfOffBits[4]
Definition: bmp.h:78
l_uint8 bfSize[4]
Definition: bmp.h:70
l_uint8 bfType[2]
Definition: bmp.h:69
l_int32 biSizeImage
Definition: bmp.h:99
l_int32 biXPelsPerMeter
Definition: bmp.h:100
l_int32 biClrImportant
Definition: bmp.h:103
l_int32 biClrUsed
Definition: bmp.h:102
l_int32 biSize
Definition: bmp.h:93
l_int32 biYPelsPerMeter
Definition: bmp.h:101
l_int16 biPlanes
Definition: bmp.h:96
l_int32 biWidth
Definition: bmp.h:94
l_int16 biBitCount
Definition: bmp.h:97
l_int32 biHeight
Definition: bmp.h:95
l_int32 biCompression
Definition: bmp.h:98
void * array
Definition: pix.h:161
l_int32 n
Definition: pix.h:164
Definition: pix.h:139
Definition: pix.h:174
l_uint8 alpha
Definition: pix.h:178
l_uint8 green
Definition: pix.h:176
l_uint8 blue
Definition: pix.h:175
l_uint8 red
Definition: pix.h:177
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402