136l_uint8 *cmapBuf, *fdata, *data;
137l_int16 bftype, depth, d;
138l_int32 offset, ihbytes, width, height, height_neg, xres, yres, spp;
139l_int32 compression, imagebytes, fdatabytes, cmapbytes, ncolors, maxcolors;
140l_int32 fdatabpl, extrabytes, filebpp, pixWpl, pixBpl, i, j, k;
141l_uint32 *line, *pixdata, *pword;
146#define bmpih (&bmph->bmpih)
154 return (
PIX *)ERROR_PTR(
"cdata not defined", __func__, NULL);
156 return (
PIX *)ERROR_PTR(
"bmf size error", __func__, NULL);
160 bftype = bmpfh->
bfType[0] + ((l_int32)bmpfh->
bfType[1] << 8);
162 return (
PIX *)ERROR_PTR(
"not bmf format", __func__, NULL);
164 bmph = (BMP_HEADER *)bmpfh;
169 if (compression != 0)
170 return (
PIX *)ERROR_PTR(
"cannot read compressed BMP files",
175 offset += (l_int32)bmpfh->
bfOffBits[1] << 8;
176 offset += (l_int32)bmpfh->
bfOffBits[2] << 16;
177 offset += (l_uint32)bmpfh->
bfOffBits[3] << 24;
181 ihbytes = convertOnBigEnd32(*(l_uint32 *)(bmpih));
182 width = convertOnBigEnd32(bmpih->
biWidth);
183 height = convertOnBigEnd32(bmpih->
biHeight);
185 imagebytes = convertOnBigEnd32(bmpih->
biSizeImage);
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);
213 if (ihbytes != 40 && ihbytes != 108 && ihbytes != 124) {
214 L_ERROR(
"invalid ihbytes = %d; not in {40, 108, 124}\n",
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 != 1 && depth != 2 && depth != 4 && depth != 8 &&
222 depth != 16 && depth != 24 && depth != 32) {
223 L_ERROR(
"invalid depth = %d; not in {1, 2, 4, 8, 16, 24, 32}\n",
227 fdatabpl = 4 * ((1LL * width * depth + 31)/32);
228 fdatabytes = fdatabpl * height;
229 if (imagebytes != 0 && imagebytes != fdatabytes) {
230 L_ERROR(
"invalid imagebytes = %d; not equal to fdatabytes = %d\n",
231 __func__, imagebytes, fdatabytes);
243 if (ncolors < 0 || ncolors == 1)
244 return (
PIX *)ERROR_PTR(
"invalid: cmap size < 0 or 1", __func__, NULL);
245 if (ncolors > 0 && depth > 8)
246 return (
PIX *)ERROR_PTR(
"can't have cmap for d > 8", __func__, NULL);
247 maxcolors = (depth <= 8) ? 1 << depth : 0;
248 if (ncolors > maxcolors) {
249 L_ERROR(
"cmap too large for depth %d: ncolors = %d > maxcolors = %d\n",
250 __func__, depth, ncolors, maxcolors);
253 if (size != 1LL * offset + 1LL * fdatabytes)
254 return (
PIX *)ERROR_PTR(
"size incommensurate with image data",
260 if ((cmapBuf = (l_uint8 *)LEPT_CALLOC(ncolors,
sizeof(
RGBA_QUAD)))
262 return (
PIX *)ERROR_PTR(
"cmapBuf alloc fail", __func__, NULL );
271 d = (depth == 24) ? 32 : depth;
272 if ((pix = pixCreate(width, height, d)) == NULL) {
274 return (
PIX *)ERROR_PTR(
"pix not made", __func__, NULL);
276 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5));
277 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5));
278 pixSetInputFormat(pix, IFF_BMP);
279 pixWpl = pixGetWpl(pix);
283 else if (depth == 24)
292 cmap = pixcmapCreate(L_MIN(d, 8));
293 LEPT_FREE(cmap->
array);
294 cmap->
array = (
void *)cmapBuf;
295 cmap->
n = L_MIN(ncolors, 256);
296 for (i = 0; i < cmap->
n; i++)
297 pixcmapSetAlpha (cmap, i, 255);
299 if (pixSetColormap(pix, cmap)) {
301 return (
PIX *)ERROR_PTR(
"invalid colormap", __func__, NULL);
305 fdata = (l_uint8 *)cdata + offset;
306 pixdata = pixGetData(pix);
307 if (depth != 24 && depth != 32) {
308 data = (l_uint8 *)pixdata + pixBpl * (height - 1);
309 for (i = 0; i < height; i++) {
310 memcpy(data, fdata, fdatabpl);
355 filebpp = (depth == 24) ? 3 : 4;
356 extrabytes = fdatabpl - filebpp * width;
357 line = pixdata + pixWpl * (height - 1);
358 for (i = 0; i < height; i++) {
359 for (j = 0; j < width; j++) {
361 memcpy(&pel, fdata, filebpp);
363 *((l_uint8 *)pword +
COLOR_RED) = pel[2];
373 for (k = 0; k < extrabytes; k++) {
374 memcpy(&pel, fdata, 1);
382 pixEndianByteSwap(pix);
393 if (depth == 1 && cmap) {
394 L_INFO(
"removing opaque cmap from 1 bpp\n", __func__);
463l_uint8 *fdata, *data, *fmdata;
465l_int32 ncolors, val, stepsize, w, h, d, fdepth, xres, yres, valid;
466l_int32 pixWpl, pixBpl, extrabytes, spp, fBpl, fWpl, i, j, k;
468l_uint32 offbytes, fimagebytes;
469l_uint32 *line, *pword;
474#define bmpih (&bmph->bmpih)
482 if (pfdata) *pfdata = NULL;
483 if (pfsize) *pfsize = 0;
485 return ERROR_INT(
"&fdata not defined", __func__, 1 );
487 return ERROR_INT(
"&fsize not defined", __func__, 1 );
489 return ERROR_INT(
"pixs not defined", __func__, 1);
492 if ((cmap = pixGetColormap(pixs)) != NULL) {
493 pixcmapIsValid(cmap, pixs, &valid);
495 return ERROR_INT(
"colormap is not valid", __func__, 1);
498 pixGetDimensions(pixs, &w, &h, &d);
499 spp = pixGetSpp(pixs);
500 if (spp != 1 && spp != 3 && spp != 4) {
501 L_ERROR(
"unsupported spp = %d\n", __func__, spp);
505 L_WARNING(
"2 bpp files can't be read; converting to 8 bpp\n",
507 pix = pixConvert2To8(pixs, 0, 85, 170, 255, 1);
509 }
else if (d == 24) {
510 pix = pixConvert24To32(pixs);
513 pix = pixCopy(NULL, pixs);
525 xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5);
526 yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5);
528 pixWpl = pixGetWpl(pix);
530 fWpl = (w * fdepth + 31) / 32;
532 fimagebytes = h * fBpl;
533 if (fimagebytes > 4LL * L_MAX_ALLOWED_PIXELS) {
535 return ERROR_INT(
"image data is too large", __func__, 1);
540 if (d == 32 || d == 16) {
543 }
else if ((cmap = pixGetColormap(pix))) {
544 ncolors = pixcmapGetCount(cmap);
546 cta = (l_uint8 *)cmap->
array;
549 cmaplen =
sizeof(bwmap);
551 cta = (l_uint8 *)bwmap;
553 ncolors = 1 << fdepth;
556 cta = (l_uint8 *)LEPT_CALLOC(cmaplen, 1);
557 stepsize = 255 / (ncolors - 1);
558 for (i = 0, val = 0, pquad = (
RGBA_QUAD *)cta;
560 i++, val += stepsize, pquad++) {
569 pcmptr = (l_uint8 *)pixGetColormap(pix)->
array;
570 lept_stderr(
"Pix colormap[0] = %c%c%c%d\n",
571 pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]);
572 lept_stderr(
"Pix colormap[1] = %c%c%c%d\n",
573 pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]);
578 fsize = offbytes + fimagebytes;
579 fdata = (l_uint8 *)LEPT_CALLOC(fsize, 1);
587 bmpfh->
bfSize[0] = (l_uint8)(fsize >> 0);
588 bmpfh->
bfSize[1] = (l_uint8)(fsize >> 8);
589 bmpfh->
bfSize[2] = (l_uint8)(fsize >> 16);
590 bmpfh->
bfSize[3] = (l_uint8)(fsize >> 24);
591 bmpfh->
bfOffBits[0] = (l_uint8)(offbytes >> 0);
592 bmpfh->
bfOffBits[1] = (l_uint8)(offbytes >> 8);
593 bmpfh->
bfOffBits[2] = (l_uint8)(offbytes >> 16);
594 bmpfh->
bfOffBits[3] = (l_uint8)(offbytes >> 24);
598 bmph = (BMP_HEADER *)bmpfh;
603 bmpih->
biWidth = convertOnBigEnd32(w);
604 bmpih->
biHeight = convertOnBigEnd32(h);
605 bmpih->
biPlanes = convertOnBigEnd16(1);
606 bmpih->
biBitCount = convertOnBigEnd16(fdepth);
607 bmpih->
biSizeImage = convertOnBigEnd32(fimagebytes);
610 bmpih->
biClrUsed = convertOnBigEnd32(ncolors);
616 if (heapcm) LEPT_FREE(cta);
621 if (fdepth == 1 && cmap && ((l_uint8 *)(cmap->
array))[0] == 0x0) {
626 pixEndianByteSwap(pix);
629 fmdata = fdata + offbytes;
630 if (fdepth != 24 && fdepth != 32) {
631 data = (l_uint8 *)pixGetData(pix) + pixBpl * (h - 1);
632 for (i = 0; i < h; i++) {
633 memcpy(fmdata, data, fBpl);
649 extrabytes = fBpl - spp * w;
650 line = pixGetData(pix) + pixWpl * (h - 1);
651 for (i = 0; i < h; i++) {
652 for (j = 0; j < w; j++) {
654 pel[2] = *((l_uint8 *)pword +
COLOR_RED);
659 memcpy(fmdata, &pel, spp);
663 for (k = 0; k < extrabytes; k++) {
664 memcpy(fmdata, &pel, 1);