43 #include <config_auto.h> 47 #include "allheaders.h" 58 RGBA_QUAD bwmap[2] = { {255,255,255,255}, {0,0,0,255} };
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;
93 PROCNAME(
"pixReadStreamBmp");
96 return (
PIX *)ERROR_PTR(
"fp not defined", procName, NULL);
101 return (
PIX *)ERROR_PTR(
"data not read", procName, NULL);
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;
141 #if defined(__GNUC__) 143 #define bmpih (&bmph->bmpih) 150 PROCNAME(
"pixReadMemBmp");
153 return (
PIX *)ERROR_PTR(
"cdata not defined", procName, NULL);
155 return (
PIX *)ERROR_PTR(
"bmf size error", procName, NULL);
159 bftype = bmpfh->
bfType[0] + ((l_int32)bmpfh->
bfType[1] << 8);
161 return (
PIX *)ERROR_PTR(
"not bmf format", procName, NULL);
162 #if defined(__GNUC__) 163 bmph = (BMP_HEADER *)bmpfh;
168 if (compression != 0)
169 return (
PIX *)ERROR_PTR(
"cannot read compressed BMP files",
174 offset += (l_int32)bmpfh->
bfOffBits[1] << 8;
175 offset += (l_int32)bmpfh->
bfOffBits[2] << 16;
176 offset += (l_uint32)bmpfh->
bfOffBits[3] << 24;
180 ihbytes = convertOnBigEnd32(*(l_uint32 *)(bmpih));
181 width = convertOnBigEnd32(bmpih->
biWidth);
182 height = convertOnBigEnd32(bmpih->
biHeight);
184 imagebytes = convertOnBigEnd32(bmpih->
biSizeImage);
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);
212 if (ihbytes != 40 && ihbytes != 108 && ihbytes != 124) {
213 L_ERROR(
"invalid ihbytes = %d; not in {40, 108, 124}\n",
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",
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);
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);
252 if (size != 1LL * offset + 1LL * fdatabytes)
253 return (
PIX *)ERROR_PTR(
"size incommensurate with image data",
259 if ((cmapBuf = (l_uint8 *)LEPT_CALLOC(ncolors,
sizeof(
RGBA_QUAD)))
261 return (
PIX *)ERROR_PTR(
"cmapBuf alloc fail", procName, NULL );
270 d = (depth == 24) ? 32 : depth;
271 if ((pix =
pixCreate(width, height, d)) == NULL) {
273 return (
PIX *)ERROR_PTR(
"pix not made", procName, NULL);
275 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
276 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
277 pixSetInputFormat(pix, IFF_BMP);
278 pixWpl = pixGetWpl(pix);
285 LEPT_FREE(cmap->
array);
286 cmap->
array = (
void *)cmapBuf;
287 cmap->
n = L_MIN(ncolors, 256);
288 for (i = 0; i < cmap->
n; i++)
293 return (
PIX *)ERROR_PTR(
"invalid colormap", procName, NULL);
297 fdata = (l_uint8 *)cdata + offset;
300 data = (l_uint8 *)pixdata + pixBpl * (height - 1);
301 for (i = 0; i < height; i++) {
302 memcpy(data, fdata, fdatabpl);
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++) {
348 memcpy(&pel, fdata, 3);
350 *((l_uint8 *)pword +
COLOR_RED) = pel[2];
358 for (k = 0; k < extrabytes; k++) {
359 memcpy(&pel, fdata, 1);
378 if (depth == 1 && cmap) {
379 L_INFO(
"removing opaque cmap from 1 bpp\n", procName);
406 PROCNAME(
"pixWriteStreamBmp");
409 return ERROR_INT(
"stream not defined", procName, 1);
411 return ERROR_INT(
"pix not defined", procName, 1);
415 nbytes = fwrite(data, 1, size, fp);
418 return ERROR_INT(
"Write error", procName, 1);
451 l_uint8 *fdata, *data, *fmdata;
453 l_int32 ncolors, val, stepsize, w, h, d, fdepth, xres, yres, valid;
454 l_int32 pixWpl, pixBpl, extrabytes, fBpl, fWpl, i, j, k;
456 l_uint32 offbytes, fimagebytes;
457 l_uint32 *line, *pword;
460 #if defined(__GNUC__) 462 #define bmpih (&bmph->bmpih) 470 PROCNAME(
"pixWriteMemBmp");
472 if (pfdata) *pfdata = NULL;
473 if (pfsize) *pfsize = 0;
475 return ERROR_INT(
"&fdata not defined", procName, 1 );
477 return ERROR_INT(
"&fsize not defined", procName, 1 );
479 return ERROR_INT(
"pixs not defined", procName, 1);
482 if ((cmap = pixGetColormap(pixs)) != NULL) {
485 return ERROR_INT(
"colormap is not valid", procName, 1);
490 L_WARNING(
"2 bpp files can't be read; converting to 8 bpp\n", procName);
496 fdepth = (d == 32) ? 24 : d;
499 xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
500 yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
502 pixWpl = pixGetWpl(pix);
504 fWpl = (w * fdepth + 31) / 32;
506 fimagebytes = h * fBpl;
507 if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
509 return ERROR_INT(
"image data is too large", procName, 1);
514 if (d == 32 || d == 16) {
517 }
else if ((cmap = pixGetColormap(pix))) {
520 cta = (l_uint8 *)cmap->
array;
523 cmaplen =
sizeof(bwmap);
525 cta = (l_uint8 *)bwmap;
527 ncolors = 1 << fdepth;
530 cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
531 stepsize = 255 / (ncolors - 1);
532 for (i = 0, val = 0, pquad = (
RGBA_QUAD *)cta;
534 i++, val += stepsize, pquad++) {
543 pcmptr = (l_uint8 *)pixGetColormap(pix)->
array;
545 pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
547 pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
552 fsize = offbytes + fimagebytes;
553 fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
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);
571 #if defined(__GNUC__) 572 bmph = (BMP_HEADER *)bmpfh;
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);
584 bmpih->
biClrUsed = convertOnBigEnd32(ncolors);
590 if (heapcm) LEPT_FREE(cta);
595 if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->
array))[0] == 0x0) {
603 fmdata = fdata + offbytes;
605 data = (l_uint8 *)
pixGetData(pix) + pixBpl * (h - 1);
606 for (i = 0; i < h; i++) {
607 memcpy(fmdata, data, fBpl);
620 extrabytes = fBpl - 3 * w;
622 for (i = 0; i < h; i++) {
623 for (j = 0; j < w; j++) {
625 pel[2] = *((l_uint8 *)pword +
COLOR_RED);
628 memcpy(fmdata, &pel, 3);
632 for (k = 0; k < extrabytes; k++) {
633 memcpy(fmdata, &pel, 1);
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
pixRemoveColormap()
l_ok pixWriteStreamBmp(FILE *fp, PIX *pix)
pixWriteStreamBmp()
l_ok pixWriteMemBmp(l_uint8 **pfdata, size_t *pfsize, PIX *pixs)
pixWriteMemBmp()
PIX * pixReadStreamBmp(FILE *fp)
pixReadStreamBmp()
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
void lept_stderr(const char *fmt,...)
lept_stderr()
PIX * pixReadMemBmp(const l_uint8 *cdata, size_t size)
pixReadMemBmp()
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
l_uint32 * pixGetData(PIX *pix)
pixGetData()
l_ok pixSetColormap(PIX *pix, PIXCMAP *colormap)
pixSetColormap()
PIXCMAP * pixcmapCreate(l_int32 depth)
pixcmapCreate()
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
void pixDestroy(PIX **ppix)
pixDestroy()
l_ok pixcmapSetAlpha(PIXCMAP *cmap, l_int32 index, l_int32 aval)
pixcmapSetAlpha()
l_ok pixcmapIsValid(const PIXCMAP *cmap, PIX *pix, l_int32 *pvalid)
pixcmapIsValid()
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
PIX * pixConvert2To8(PIX *pixs, l_uint8 val0, l_uint8 val1, l_uint8 val2, l_uint8 val3, l_int32 cmapflag)
pixConvert2To8()
l_int32 pixcmapGetCount(const PIXCMAP *cmap)
pixcmapGetCount()