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