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) */
58 RGBA_QUAD bwmap[2] = { {255,255,255,255}, {0,0,0,255} };
59 
60  /* Image dimension limits */
61 static const l_int32 L_MAX_ALLOWED_WIDTH = 1000000;
62 static const l_int32 L_MAX_ALLOWED_HEIGHT = 1000000;
63 static const l_int64 L_MAX_ALLOWED_PIXELS = 400000000LL;
64 static 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  *--------------------------------------------------------------*/
86 PIX *
88 {
89 l_uint8 *data;
90 size_t size;
91 PIX *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 
128 PIX *
129 pixReadMemBmp(const l_uint8 *cdata,
130  size_t size)
131 {
132 l_uint8 pel[4];
133 l_uint8 *cmapBuf, *fdata, *data;
134 l_int16 bftype, depth, d;
135 l_int32 offset, ihbytes, width, height, height_neg, xres, yres;
136 l_int32 compression, imagebytes, fdatabytes, cmapbytes, ncolors, maxcolors;
137 l_int32 fdatabpl, extrabytes, pixWpl, pixBpl, i, j, k;
138 l_uint32 *line, *pixdata, *pword;
139 l_int64 npixels;
140 BMP_FH *bmpfh;
141 #if defined(__GNUC__)
142 BMP_HEADER *bmph;
143 #define bmpih (&bmph->bmpih)
144 #else
145 BMP_IH *bmpih;
146 #endif
147 PIX *pix, *pix1;
148 PIXCMAP *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 
367  pixEndianByteSwap(pix);
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  *--------------------------------------------------------------*/
399 l_ok
401  PIX *pix)
402 {
403 l_uint8 *data;
404 size_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 
444 l_ok
445 pixWriteMemBmp(l_uint8 **pfdata,
446  size_t *pfsize,
447  PIX *pixs)
448 {
449 l_uint8 pel[4];
450 l_uint8 *cta = NULL; /* address of the bmp color table array */
451 l_uint8 *fdata, *data, *fmdata;
452 l_int32 cmaplen; /* number of bytes in the bmp colormap */
453 l_int32 ncolors, val, stepsize, w, h, d, fdepth, xres, yres, valid;
454 l_int32 pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
455 l_int32 heapcm; /* extra copy of cta on the heap ? 1 : 0 */
456 l_uint32 offbytes, fimagebytes;
457 l_uint32 *line, *pword;
458 size_t fsize;
459 BMP_FH *bmpfh;
460 #if defined(__GNUC__)
461 BMP_HEADER *bmph;
462 #define bmpih (&bmph->bmpih)
463 #else
464 BMP_IH *bmpih;
465 #endif
466 PIX *pix;
467 PIXCMAP *cmap;
468 RGBA_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 */
600  pixEndianByteSwap(pix);
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
PIX * pixReadMemBmp(const l_uint8 *cdata, size_t size)
pixReadMemBmp()
Definition: bmpio.c:129
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
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_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
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 * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
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: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 * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition: pixconv.c:2492
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:328
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