Leptonica  1.77.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  /* Colormap size limit */
61 static const l_int32 L_MAX_ALLOWED_NUM_COLORS = 256;
62 
63  /* Image dimension limits */
64 static const l_int32 L_MAX_ALLOWED_WIDTH = 1000000;
65 static const l_int32 L_MAX_ALLOWED_HEIGHT = 1000000;
66 static const l_int64 L_MAX_ALLOWED_PIXELS = 400000000LL;
67 static const l_int32 L_MAX_ALLOWED_RES = 10000000; /* pixels/meter */
68 
69 #ifndef NO_CONSOLE_IO
70 #define DEBUG 0
71 #endif /* ~NO_CONSOLE_IO */
72 
73 /*--------------------------------------------------------------*
74  * Read bmp *
75  *--------------------------------------------------------------*/
89 PIX *
91 {
92 l_uint8 *data;
93 size_t size;
94 PIX *pix;
95 
96  PROCNAME("pixReadStreamBmp");
97 
98  if (!fp)
99  return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
100 
101  /* Read data from file and decode into Y,U,V arrays */
102  rewind(fp);
103  if ((data = l_binaryReadStream(fp, &size)) == NULL)
104  return (PIX *)ERROR_PTR("data not read", procName, NULL);
105 
106  pix = pixReadMemBmp(data, size);
107  LEPT_FREE(data);
108  return pix;
109 }
110 
111 
119 PIX *
120 pixReadMemBmp(const l_uint8 *cdata,
121  size_t size)
122 {
123 l_uint8 pel[4];
124 l_uint8 *cmapBuf, *fdata, *data;
125 l_int16 bftype, depth, d;
126 l_int32 offset, width, height, height_neg, xres, yres, compression, imagebytes;
127 l_int32 cmapbytes, cmapEntries;
128 l_int32 fdatabpl, extrabytes, pixWpl, pixBpl, i, j, k;
129 l_uint32 *line, *pixdata, *pword;
130 l_int64 npixels;
131 BMP_FH *bmpfh;
132 #if defined(__GNUC__)
133 BMP_HEADER *bmph;
134 #define bmpih (&bmph->bmpih)
135 #else
136 BMP_IH *bmpih;
137 #endif
138 PIX *pix, *pix1;
139 PIXCMAP *cmap;
140 
141  PROCNAME("pixReadMemBmp");
142 
143  if (!cdata)
144  return (PIX *)ERROR_PTR("cdata not defined", procName, NULL);
145  if (size < sizeof(BMP_FH) + sizeof(BMP_IH))
146  return (PIX *)ERROR_PTR("bmf size error", procName, NULL);
147 
148  /* Verify this is an uncompressed bmp */
149  bmpfh = (BMP_FH *)cdata;
150  bftype = bmpfh->bfType[0] + ((l_int32)bmpfh->bfType[1] << 8);
151  if (bftype != BMP_ID)
152  return (PIX *)ERROR_PTR("not bmf format", procName, NULL);
153 #if defined(__GNUC__)
154  bmph = (BMP_HEADER *)bmpfh;
155 #else
156  bmpih = (BMP_IH *)(cdata + BMP_FHBYTES);
157 #endif
158  compression = convertOnBigEnd32(bmpih->biCompression);
159  if (compression != 0)
160  return (PIX *)ERROR_PTR("cannot read compressed BMP files",
161  procName, NULL);
162 
163  /* Read the rest of the useful header information */
164  offset = bmpfh->bfOffBits[0];
165  offset += (l_int32)bmpfh->bfOffBits[1] << 8;
166  offset += (l_int32)bmpfh->bfOffBits[2] << 16;
167  offset += (l_int32)bmpfh->bfOffBits[3] << 24;
168  width = convertOnBigEnd32(bmpih->biWidth);
169  height = convertOnBigEnd32(bmpih->biHeight);
170  depth = convertOnBigEnd16(bmpih->biBitCount);
171  imagebytes = convertOnBigEnd32(bmpih->biSizeImage);
172  xres = convertOnBigEnd32(bmpih->biXPelsPerMeter);
173  yres = convertOnBigEnd32(bmpih->biYPelsPerMeter);
174 
175  /* Some sanity checking. We impose limits on the image
176  * dimensions, resolution and number of pixels. We make sure the
177  * file is the correct size to hold the amount of uncompressed data
178  * that is specified in the header. The number of colormap
179  * entries is checked: it can be either 0 (no cmap) or some
180  * number between 2 and 256.
181  * Note that the imagebytes for uncompressed images is either
182  * 0 or the size of the file data. (The fact that it can
183  * be 0 is perhaps some legacy glitch). */
184  if (width < 1)
185  return (PIX *)ERROR_PTR("width < 1", procName, NULL);
186  if (width > L_MAX_ALLOWED_WIDTH)
187  return (PIX *)ERROR_PTR("width too large", procName, NULL);
188  if (height == 0 || height < -L_MAX_ALLOWED_HEIGHT ||
189  height > L_MAX_ALLOWED_HEIGHT)
190  return (PIX *)ERROR_PTR("invalid height", procName, NULL);
191  if (xres < 0 || xres > L_MAX_ALLOWED_RES ||
192  yres < 0 || yres > L_MAX_ALLOWED_RES)
193  return (PIX *)ERROR_PTR("invalid resolution", procName, NULL);
194  height_neg = 0;
195  if (height < 0) {
196  height_neg = 1;
197  height = -height;
198  }
199  npixels = 1LL * width * height;
200  if (npixels > L_MAX_ALLOWED_PIXELS)
201  return (PIX *)ERROR_PTR("npixels too large", procName, NULL);
202  if (depth != 1 && depth != 2 && depth != 4 && depth != 8 &&
203  depth != 16 && depth != 24 && depth != 32)
204  return (PIX *)ERROR_PTR("depth not in {1, 2, 4, 8, 16, 24, 32}",
205  procName,NULL);
206  fdatabpl = 4 * ((1LL * width * depth + 31)/32);
207  if (imagebytes != 0 && imagebytes != fdatabpl * height)
208  return (PIX *)ERROR_PTR("invalid imagebytes", procName, NULL);
209  cmapbytes = offset - BMP_FHBYTES - BMP_IHBYTES;
210  cmapEntries = cmapbytes / sizeof(RGBA_QUAD);
211  if (cmapEntries < 0 || cmapEntries == 1)
212  return (PIX *)ERROR_PTR("invalid: cmap size < 0 or 1", procName, NULL);
213  if (cmapEntries > L_MAX_ALLOWED_NUM_COLORS)
214  return (PIX *)ERROR_PTR("invalid cmap: too large", procName,NULL);
215  if (size != 1LL * offset + 1LL * fdatabpl * height)
216  return (PIX *)ERROR_PTR("size incommensurate with image data",
217  procName,NULL);
218 
219  /* Handle the colormap */
220  cmapBuf = NULL;
221  if (cmapEntries > 0) {
222  if ((cmapBuf = (l_uint8 *)LEPT_CALLOC(cmapEntries, sizeof(RGBA_QUAD)))
223  == NULL)
224  return (PIX *)ERROR_PTR("cmapBuf alloc fail", procName, NULL );
225 
226  /* Read the colormap entry data from bmp. The RGBA_QUAD colormap
227  * entries are used for both bmp and leptonica colormaps. */
228  memcpy(cmapBuf, cdata + BMP_FHBYTES + BMP_IHBYTES,
229  sizeof(RGBA_QUAD) * cmapEntries);
230  }
231 
232  /* Make a 32 bpp pix if depth is 24 bpp */
233  d = (depth == 24) ? 32 : depth;
234  if ((pix = pixCreate(width, height, d)) == NULL) {
235  LEPT_FREE(cmapBuf);
236  return (PIX *)ERROR_PTR( "pix not made", procName, NULL);
237  }
238  pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5)); /* to ppi */
239  pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5)); /* to ppi */
240  pixSetInputFormat(pix, IFF_BMP);
241  pixWpl = pixGetWpl(pix);
242  pixBpl = 4 * pixWpl;
243 
244  /* Convert the bmp colormap to a pixcmap */
245  cmap = NULL;
246  if (cmapEntries > 0) { /* import the colormap to the pix cmap */
247  cmap = pixcmapCreate(L_MIN(d, 8));
248  LEPT_FREE(cmap->array); /* remove generated cmap array */
249  cmap->array = (void *)cmapBuf; /* and replace */
250  cmap->n = L_MIN(cmapEntries, 256);
251  for (i = 0; i < cmap->n; i++) /* set all colors opaque */
252  pixcmapSetAlpha (cmap, i, 255);
253  }
254  pixSetColormap(pix, cmap);
255 
256  /* Acquire the image data. Image origin for bmp is at lower right. */
257  fdata = (l_uint8 *)cdata + offset; /* start of the bmp image data */
258  pixdata = pixGetData(pix);
259  if (depth != 24) { /* typ. 1 or 8 bpp */
260  data = (l_uint8 *)pixdata + pixBpl * (height - 1);
261  for (i = 0; i < height; i++) {
262  memcpy(data, fdata, fdatabpl);
263  fdata += fdatabpl;
264  data -= pixBpl;
265  }
266  } else { /* 24 bpp file; 32 bpp pix
267  * Note: for bmp files, pel[0] is blue, pel[1] is green,
268  * and pel[2] is red. This is opposite to the storage
269  * in the pix, which puts the red pixel in the 0 byte,
270  * the green in the 1 byte and the blue in the 2 byte.
271  * Note also that all words are endian flipped after
272  * assignment on L_LITTLE_ENDIAN platforms.
273  *
274  * We can then make these assignments for little endians:
275  * SET_DATA_BYTE(pword, 1, pel[0]); blue
276  * SET_DATA_BYTE(pword, 2, pel[1]); green
277  * SET_DATA_BYTE(pword, 3, pel[2]); red
278  * This looks like:
279  * 3 (R) 2 (G) 1 (B) 0
280  * |-----------|------------|-----------|-----------|
281  * and after byte flipping:
282  * 3 2 (B) 1 (G) 0 (R)
283  * |-----------|------------|-----------|-----------|
284  *
285  * For big endians we set:
286  * SET_DATA_BYTE(pword, 2, pel[0]); blue
287  * SET_DATA_BYTE(pword, 1, pel[1]); green
288  * SET_DATA_BYTE(pword, 0, pel[2]); red
289  * This looks like:
290  * 0 (R) 1 (G) 2 (B) 3
291  * |-----------|------------|-----------|-----------|
292  * so in both cases we get the correct assignment in the PIX.
293  *
294  * Can we do a platform-independent assignment?
295  * Yes, set the bytes without using macros:
296  * *((l_uint8 *)pword) = pel[2]; red
297  * *((l_uint8 *)pword + 1) = pel[1]; green
298  * *((l_uint8 *)pword + 2) = pel[0]; blue
299  * For little endians, before flipping, this looks again like:
300  * 3 (R) 2 (G) 1 (B) 0
301  * |-----------|------------|-----------|-----------|
302  */
303  extrabytes = fdatabpl - 3 * width;
304  line = pixdata + pixWpl * (height - 1);
305  for (i = 0; i < height; i++) {
306  for (j = 0; j < width; j++) {
307  pword = line + j;
308  memcpy(&pel, fdata, 3);
309  fdata += 3;
310  *((l_uint8 *)pword + COLOR_RED) = pel[2];
311  *((l_uint8 *)pword + COLOR_GREEN) = pel[1];
312  *((l_uint8 *)pword + COLOR_BLUE) = pel[0];
313  }
314  if (extrabytes) {
315  for (k = 0; k < extrabytes; k++) {
316  memcpy(&pel, fdata, 1);
317  fdata++;
318  }
319  }
320  line -= pixWpl;
321  }
322  }
323 
324  pixEndianByteSwap(pix);
325  if (height_neg)
326  pixFlipTB(pix, pix);
327 
328  /* ----------------------------------------------
329  * The bmp colormap determines the values of black
330  * and white pixels for binary in the following way:
331  * (a) white = 0 [255], black = 1 [0]
332  * 255, 255, 255, 255, 0, 0, 0, 255
333  * (b) black = 0 [0], white = 1 [255]
334  * 0, 0, 0, 255, 255, 255, 255, 255
335  * We have no need for a 1 bpp pix with a colormap!
336  * Note: the alpha component here is 255 (opaque)
337  * ---------------------------------------------- */
338  if (depth == 1 && cmap) {
340  pixDestroy(&pix);
341  pix = pix1; /* rename */
342  }
343 
344  return pix;
345 }
346 
347 
348 /*--------------------------------------------------------------*
349  * Write bmp *
350  *--------------------------------------------------------------*/
358 l_ok
360  PIX *pix)
361 {
362 l_uint8 *data;
363 size_t size, nbytes;
364 
365  PROCNAME("pixWriteStreamBmp");
366 
367  if (!fp)
368  return ERROR_INT("stream not defined", procName, 1);
369  if (!pix)
370  return ERROR_INT("pix not defined", procName, 1);
371 
372  pixWriteMemBmp(&data, &size, pix);
373  rewind(fp);
374  nbytes = fwrite(data, 1, size, fp);
375  free(data);
376  if (nbytes != size)
377  return ERROR_INT("Write error", procName, 1);
378  return 0;
379 }
380 
381 
403 l_ok
404 pixWriteMemBmp(l_uint8 **pfdata,
405  size_t *pfsize,
406  PIX *pixs)
407 {
408 l_uint8 pel[4];
409 l_uint8 *cta = NULL; /* address of the bmp color table array */
410 l_uint8 *fdata, *data, *fmdata;
411 l_int32 cmaplen; /* number of bytes in the bmp colormap */
412 l_int32 ncolors, val, stepsize;
413 l_int32 w, h, d, fdepth, xres, yres;
414 l_int32 pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
415 l_int32 heapcm; /* extra copy of cta on the heap ? 1 : 0 */
416 l_uint32 offbytes, fimagebytes;
417 l_uint32 *line, *pword;
418 size_t fsize;
419 BMP_FH *bmpfh;
420 #if defined(__GNUC__)
421 BMP_HEADER *bmph;
422 #define bmpih (&bmph->bmpih)
423 #else
424 BMP_IH *bmpih;
425 #endif
426 PIX *pix;
427 PIXCMAP *cmap;
428 RGBA_QUAD *pquad;
429 
430  PROCNAME("pixWriteMemBmp");
431 
432  if (pfdata) *pfdata = NULL;
433  if (pfsize) *pfsize = 0;
434  if (!pfdata)
435  return ERROR_INT("&fdata not defined", procName, 1 );
436  if (!pfsize)
437  return ERROR_INT("&fsize not defined", procName, 1 );
438  if (!pixs)
439  return ERROR_INT("pixs not defined", procName, 1);
440 
441  pixGetDimensions(pixs, &w, &h, &d);
442  if (d == 2) {
443  L_WARNING("2 bpp files can't be read; converting to 8 bpp\n", procName);
444  pix = pixConvert2To8(pixs, 0, 85, 170, 255, 1);
445  d = 8;
446  } else {
447  pix = pixCopy(NULL, pixs);
448  }
449  fdepth = (d == 32) ? 24 : d;
450 
451  /* Resolution is given in pixels/meter */
452  xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
453  yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
454 
455  pixWpl = pixGetWpl(pix);
456  pixBpl = 4 * pixWpl;
457  fWpl = (w * fdepth + 31) / 32;
458  fBpl = 4 * fWpl;
459  fimagebytes = h * fBpl;
460  if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
461  pixDestroy(&pix);
462  return ERROR_INT("image data is too large", procName, 1);
463  }
464 
465  /* If not rgb or 16 bpp, the bmp data is required to have a colormap */
466  heapcm = 0;
467  if (d == 32 || d == 16) { /* 24 bpp rgb or 16 bpp: no colormap */
468  ncolors = 0;
469  cmaplen = 0;
470  } else if ((cmap = pixGetColormap(pix))) { /* existing colormap */
471  ncolors = pixcmapGetCount(cmap);
472  cmaplen = ncolors * sizeof(RGBA_QUAD);
473  cta = (l_uint8 *)cmap->array;
474  } else { /* no existing colormap; d <= 8; make a binary or gray one */
475  if (d == 1) {
476  cmaplen = sizeof(bwmap);
477  ncolors = 2;
478  cta = (l_uint8 *)bwmap;
479  } else { /* d = 2,4,8; use a grayscale output colormap */
480  ncolors = 1 << fdepth;
481  cmaplen = ncolors * sizeof(RGBA_QUAD);
482  heapcm = 1;
483  cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
484  stepsize = 255 / (ncolors - 1);
485  for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta;
486  i < ncolors;
487  i++, val += stepsize, pquad++) {
488  pquad->blue = pquad->green = pquad->red = val;
489  pquad->alpha = 255; /* opaque */
490  }
491  }
492  }
493 
494 #if DEBUG
495  {l_uint8 *pcmptr;
496  pcmptr = (l_uint8 *)pixGetColormap(pix)->array;
497  fprintf(stderr, "Pix colormap[0] = %c%c%c%d\n",
498  pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
499  fprintf(stderr, "Pix colormap[1] = %c%c%c%d\n",
500  pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
501  }
502 #endif /* DEBUG */
503 
504  offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen;
505  fsize = offbytes + fimagebytes;
506  fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
507  *pfdata = fdata;
508  *pfsize = fsize;
509 
510  /* Write little-endian file header data */
511  bmpfh = (BMP_FH *)fdata;
512  bmpfh->bfType[0] = (l_uint8)(BMP_ID >> 0);
513  bmpfh->bfType[1] = (l_uint8)(BMP_ID >> 8);
514  bmpfh->bfSize[0] = (l_uint8)(fsize >> 0);
515  bmpfh->bfSize[1] = (l_uint8)(fsize >> 8);
516  bmpfh->bfSize[2] = (l_uint8)(fsize >> 16);
517  bmpfh->bfSize[3] = (l_uint8)(fsize >> 24);
518  bmpfh->bfOffBits[0] = (l_uint8)(offbytes >> 0);
519  bmpfh->bfOffBits[1] = (l_uint8)(offbytes >> 8);
520  bmpfh->bfOffBits[2] = (l_uint8)(offbytes >> 16);
521  bmpfh->bfOffBits[3] = (l_uint8)(offbytes >> 24);
522 
523  /* Convert to little-endian and write the info header data */
524 #if defined(__GNUC__)
525  bmph = (BMP_HEADER *)bmpfh;
526 #else
527  bmpih = (BMP_IH *)(fdata + BMP_FHBYTES);
528 #endif
529  bmpih->biSize = convertOnBigEnd32(BMP_IHBYTES);
530  bmpih->biWidth = convertOnBigEnd32(w);
531  bmpih->biHeight = convertOnBigEnd32(h);
532  bmpih->biPlanes = convertOnBigEnd16(1);
533  bmpih->biBitCount = convertOnBigEnd16(fdepth);
534  bmpih->biSizeImage = convertOnBigEnd32(fimagebytes);
535  bmpih->biXPelsPerMeter = convertOnBigEnd32(xres);
536  bmpih->biYPelsPerMeter = convertOnBigEnd32(yres);
537  bmpih->biClrUsed = convertOnBigEnd32(ncolors);
538  bmpih->biClrImportant = convertOnBigEnd32(ncolors);
539 
540  /* Copy the colormap data and free the cta if necessary */
541  if (ncolors > 0) {
542  memcpy(fdata + BMP_FHBYTES + BMP_IHBYTES, cta, cmaplen);
543  if (heapcm) LEPT_FREE(cta);
544  }
545 
546  /* When you write a binary image with a colormap
547  * that sets BLACK to 0, you must invert the data */
548  if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) {
549  pixInvert(pix, pix);
550  }
551 
552  /* An endian byte swap is also required */
553  pixEndianByteSwap(pix);
554 
555  /* Transfer the image data. Image origin for bmp is at lower right. */
556  fmdata = fdata + offbytes;
557  if (fdepth != 24) { /* typ 1 or 8 bpp */
558  data = (l_uint8 *)pixGetData(pix) + pixBpl * (h - 1);
559  for (i = 0; i < h; i++) {
560  memcpy(fmdata, data, fBpl);
561  data -= pixBpl;
562  fmdata += fBpl;
563  }
564  } else { /* 32 bpp pix; 24 bpp file
565  * See the comments in pixReadStreamBmp() to
566  * understand the logic behind the pixel ordering below.
567  * Note that we have again done an endian swap on
568  * little endian machines before arriving here, so that
569  * the bytes are ordered on both platforms as:
570  Red Green Blue --
571  |-----------|------------|-----------|-----------|
572  */
573  extrabytes = fBpl - 3 * w;
574  line = pixGetData(pix) + pixWpl * (h - 1);
575  for (i = 0; i < h; i++) {
576  for (j = 0; j < w; j++) {
577  pword = line + j;
578  pel[2] = *((l_uint8 *)pword + COLOR_RED);
579  pel[1] = *((l_uint8 *)pword + COLOR_GREEN);
580  pel[0] = *((l_uint8 *)pword + COLOR_BLUE);
581  memcpy(fmdata, &pel, 3);
582  fmdata += 3;
583  }
584  if (extrabytes) {
585  for (k = 0; k < extrabytes; k++) {
586  memcpy(fmdata, &pel, 1);
587  fmdata++;
588  }
589  }
590  line -= pixWpl;
591  }
592  }
593 
594  pixDestroy(&pix);
595  return 0;
596 }
597 
598 /* --------------------------------------------*/
599 #endif /* USE_BMPIO */
l_uint8 alpha
Definition: pix.h:174
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
Definition: pixconv.c:322
l_ok pixWriteStreamBmp(FILE *fp, PIX *pix)
pixWriteStreamBmp()
Definition: bmpio.c:359
l_int16 biBitCount
Definition: bmp.h:97
l_ok pixWriteMemBmp(l_uint8 **pfdata, size_t *pfsize, PIX *pixs)
pixWriteMemBmp()
Definition: bmpio.c:404
#define BMP_FHBYTES
Definition: bmp.h:83
l_int32 n
Definition: pix.h:160
PIX * pixReadStreamBmp(FILE *fp)
pixReadStreamBmp()
Definition: bmpio.c:90
l_int32 biCompression
Definition: bmp.h:98
l_uint8 red
Definition: pix.h:173
PIX * pixReadMemBmp(const l_uint8 *cdata, size_t size)
pixReadMemBmp()
Definition: bmpio.c:120
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
l_int32 biSize
Definition: bmp.h:93
l_int32 biXPelsPerMeter
Definition: bmp.h:100
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
Definition: pix1.c:1573
l_uint8 blue
Definition: pix.h:171
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
Definition: colormap.c:111
l_int32 biHeight
Definition: bmp.h:95
l_int32 biClrUsed
Definition: bmp.h:102
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:601
l_int32 biWidth
Definition: bmp.h:94
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
Definition: pix2.c:2942
#define BMP_IHBYTES
Definition: bmp.h:108
l_uint8 green
Definition: pix.h:172
Definition: pix.h:169
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
Definition: colormap.c:934
l_int32 biClrImportant
Definition: bmp.h:103
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
l_uint8 bfType[2]
Definition: bmp.h:69
l_int32 biYPelsPerMeter
Definition: bmp.h:101
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
Definition: pixconv.c:2456
void * array
Definition: pix.h:157
l_int32 pixcmapGetCount(PIXCMAP *cmap)
pixcmapGetCount()
Definition: colormap.c:635
Definition: pix.h:134
l_uint8 bfOffBits[4]
Definition: bmp.h:78
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
Definition: pix.h:201
l_int32 biSizeImage
Definition: bmp.h:99
l_uint8 bfSize[4]
Definition: bmp.h:70
l_int16 biPlanes
Definition: bmp.h:96