Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /* 00017 * bmpio.c 00018 * 00019 * Read bmp from file 00020 * PIX *pixReadStreamBmp() 00021 * 00022 * Write bmp to file 00023 * l_int32 pixWriteStreamBmp() 00024 * 00025 * Read/write to memory [only on linux] 00026 * PIX *pixReadMemBmp() 00027 * l_int32 pixWriteMemBmp() 00028 */ 00029 00030 #include <string.h> 00031 #include "allheaders.h" 00032 #include "bmp.h" 00033 00034 /* --------------------------------------------*/ 00035 #if USE_BMPIO /* defined in environ.h */ 00036 /* --------------------------------------------*/ 00037 00038 RGBA_QUAD bwmap[2] = { {255,255,255,0}, {0,0,0,0} }; 00039 00040 #ifndef NO_CONSOLE_IO 00041 #define DEBUG 0 00042 #endif /* ~NO_CONSOLE_IO */ 00043 00044 00045 /*! 00046 * pixReadStreamBmp() 00047 * 00048 * Input: stream opened for read 00049 * Return: pix, or null on error 00050 * 00051 * Notes: 00052 * (1) Here are references on the bmp file format: 00053 * http://en.wikipedia.org/wiki/BMP_file_format 00054 * http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html 00055 */ 00056 PIX * 00057 pixReadStreamBmp(FILE *fp) 00058 { 00059 l_uint16 sval; 00060 l_uint32 ival; 00061 l_int16 bfType, bfSize, bfFill1, bfReserved1, bfReserved2; 00062 l_int16 offset, bfFill2, biPlanes, depth, d; 00063 l_int32 biSize, width, height, xres, yres, compression, ignore; 00064 l_int32 imagebytes, biClrUsed, biClrImportant; 00065 l_uint8 *colormapBuf; 00066 l_int32 colormapEntries; 00067 l_int32 fileBpl, extrabytes, readerror; 00068 l_int32 pixWpl, pixBpl; 00069 l_int32 i, j, k; 00070 l_uint8 pel[4]; 00071 l_uint8 *data; 00072 l_uint32 *line, *pword; 00073 PIX *pix, *pixt; 00074 PIXCMAP *cmap; 00075 00076 PROCNAME("pixReadStreamBmp"); 00077 00078 if (!fp) 00079 return (PIX *)ERROR_PTR("fp not defined", procName, NULL); 00080 00081 /* Read bitmap file header */ 00082 ignore = fread((char *)&sval, 1, 2, fp); 00083 bfType = convertOnBigEnd16(sval); 00084 if (bfType != BMP_ID) 00085 return (PIX *)ERROR_PTR("not bmf format", procName, NULL); 00086 00087 ignore = fread((char *)&sval, 1, 2, fp); 00088 bfSize = convertOnBigEnd16(sval); 00089 ignore = fread((char *)&sval, 1, 2, fp); 00090 bfFill1 = convertOnBigEnd16(sval); 00091 ignore = fread((char *)&sval, 1, 2, fp); 00092 bfReserved1 = convertOnBigEnd16(sval); 00093 ignore = fread((char *)&sval, 1, 2, fp); 00094 bfReserved2 = convertOnBigEnd16(sval); 00095 ignore = fread((char *)&sval, 1, 2, fp); 00096 offset = convertOnBigEnd16(sval); 00097 ignore = fread((char *)&sval, 1, 2, fp); 00098 bfFill2 = convertOnBigEnd16(sval); 00099 00100 /* Read bitmap info header */ 00101 ignore = fread((char *)&ival, 1, 4, fp); 00102 biSize = convertOnBigEnd32(ival); 00103 ignore = fread((char *)&ival, 1, 4, fp); 00104 width = convertOnBigEnd32(ival); 00105 ignore = fread((char *)&ival, 1, 4, fp); 00106 height = convertOnBigEnd32(ival); 00107 ignore = fread((char *)&sval, 1, 2, fp); 00108 biPlanes = convertOnBigEnd16(sval); 00109 ignore = fread((char *)&sval, 1, 2, fp); 00110 depth = convertOnBigEnd16(sval); 00111 ignore = fread((char *)&ival, 1, 4, fp); 00112 compression = convertOnBigEnd32(ival); 00113 ignore = fread((char *)&ival, 1, 4, fp); 00114 imagebytes = convertOnBigEnd32(ival); 00115 ignore = fread((char *)&ival, 1, 4, fp); 00116 xres = convertOnBigEnd32(ival); 00117 ignore = fread((char *)&ival, 1, 4, fp); 00118 yres = convertOnBigEnd32(ival); 00119 ignore = fread((char *)&ival, 1, 4, fp); 00120 biClrUsed = convertOnBigEnd32(ival); 00121 ignore = fread((char *)&ival, 1, 4, fp); 00122 biClrImportant = convertOnBigEnd32(ival); 00123 00124 if (compression != 0) 00125 return (PIX *)ERROR_PTR("cannot read compressed BMP files", 00126 procName,NULL); 00127 00128 /* A little sanity checking. It would be nice to check 00129 * if the number of bytes in the file equals the offset to 00130 * the data plus the imagedata, but this won't work when 00131 * reading from memory, because fmemopen() doesn't implement 00132 * ftell(). So we can't do that check. The imagebytes for 00133 * uncompressed images is either 0 or the size of the file data. 00134 * (The fact that it can be 0 is perhaps some legacy glitch). */ 00135 if (width < 1) 00136 return (PIX *)ERROR_PTR("width < 1", procName,NULL); 00137 if (height < 1) 00138 return (PIX *)ERROR_PTR("height < 1", procName,NULL); 00139 if (depth < 1 || depth > 32) 00140 return (PIX *)ERROR_PTR("depth not in [1 ... 32]", procName,NULL); 00141 fileBpl = 4 * ((width * depth + 31)/32); 00142 if (imagebytes != 0 && imagebytes != fileBpl * height) 00143 return (PIX *)ERROR_PTR("invalid imagebytes", procName,NULL); 00144 if (offset < BMP_FHBYTES + BMP_IHBYTES) 00145 return (PIX *)ERROR_PTR("invalid offset: too small", procName,NULL); 00146 if (offset > BMP_FHBYTES + BMP_IHBYTES + 4 * 256) 00147 return (PIX *)ERROR_PTR("invalid offset: too large", procName,NULL); 00148 00149 /* Handle the colormap */ 00150 colormapEntries = (offset - BMP_FHBYTES - BMP_IHBYTES) / sizeof(RGBA_QUAD); 00151 if (colormapEntries > 0) { 00152 if ((colormapBuf = (l_uint8 *)CALLOC(colormapEntries, 00153 sizeof(RGBA_QUAD))) == NULL) 00154 return (PIX *)ERROR_PTR("colormapBuf alloc fail", procName, NULL ); 00155 00156 /* Read colormap */ 00157 if (fread(colormapBuf, sizeof(RGBA_QUAD), colormapEntries, fp) 00158 != colormapEntries) { 00159 FREE(colormapBuf); 00160 return (PIX *)ERROR_PTR( "colormap read fail", procName, NULL); 00161 } 00162 } 00163 00164 /* Make a 32 bpp pix if depth is 24 bpp */ 00165 d = depth; 00166 if (depth == 24) 00167 d = 32; 00168 if ((pix = pixCreate(width, height, d)) == NULL) 00169 return (PIX *)ERROR_PTR( "pix not made", procName, NULL); 00170 pixSetXRes(pix, (l_int32)((l_float32)xres / 39.37 + 0.5)); /* to ppi */ 00171 pixSetYRes(pix, (l_int32)((l_float32)yres / 39.37 + 0.5)); /* to ppi */ 00172 pixWpl = pixGetWpl(pix); 00173 pixBpl = 4 * pixWpl; 00174 00175 cmap = NULL; 00176 if (colormapEntries > 256) 00177 L_WARNING("more than 256 colormap entries!", procName); 00178 if (colormapEntries > 0) { /* import the colormap to the pix cmap */ 00179 cmap = pixcmapCreate(L_MIN(d, 8)); 00180 FREE(cmap->array); /* remove generated cmap array */ 00181 cmap->array = (void *)colormapBuf; /* and replace */ 00182 cmap->n = L_MIN(colormapEntries, 256); 00183 } 00184 pixSetColormap(pix, cmap); 00185 00186 /* Seek to the start of the bitmap in the file */ 00187 fseek(fp, offset, 0); 00188 00189 if (depth != 24) { /* typ. 1 or 8 bpp */ 00190 data = (l_uint8 *)pixGetData(pix) + pixBpl * (height - 1); 00191 for (i = 0; i < height; i++) { 00192 if (fread(data, 1, fileBpl, fp) != fileBpl) { 00193 pixDestroy(&pix); 00194 return (PIX *)ERROR_PTR("BMP read fail", procName, NULL); 00195 } 00196 data -= pixBpl; 00197 } 00198 } 00199 else { /* 24 bpp file; 32 bpp pix 00200 * Note: for bmp files, pel[0] is blue, pel[1] is green, 00201 * and pel[2] is red. This is opposite to the storage 00202 * in the pix, which puts the red pixel in the 0 byte, 00203 * the green in the 1 byte and the blue in the 2 byte. 00204 * Note also that all words are endian flipped after 00205 * assignment on L_LITTLE_ENDIAN platforms. 00206 * 00207 * We can then make these assignments for little endians: 00208 * SET_DATA_BYTE(pword, 1, pel[0]); blue 00209 * SET_DATA_BYTE(pword, 2, pel[1]); green 00210 * SET_DATA_BYTE(pword, 3, pel[2]); red 00211 * This looks like: 00212 * 3 (R) 2 (G) 1 (B) 0 00213 * |-----------|------------|-----------|-----------| 00214 * and after byte flipping: 00215 * 3 2 (B) 1 (G) 0 (R) 00216 * |-----------|------------|-----------|-----------| 00217 * 00218 * For big endians we set: 00219 * SET_DATA_BYTE(pword, 2, pel[0]); blue 00220 * SET_DATA_BYTE(pword, 1, pel[1]); green 00221 * SET_DATA_BYTE(pword, 0, pel[2]); red 00222 * This looks like: 00223 * 0 (R) 1 (G) 2 (B) 3 00224 * |-----------|------------|-----------|-----------| 00225 * so in both cases we get the correct assignment in the PIX. 00226 * 00227 * Can we do a platform-independent assignment? 00228 * Yes, set the bytes without using macros: 00229 * *((l_uint8 *)pword) = pel[2]; red 00230 * *((l_uint8 *)pword + 1) = pel[1]; green 00231 * *((l_uint8 *)pword + 2) = pel[0]; blue 00232 * For little endians, before flipping, this looks again like: 00233 * 3 (R) 2 (G) 1 (B) 0 00234 * |-----------|------------|-----------|-----------| 00235 */ 00236 readerror = 0; 00237 extrabytes = fileBpl - 3 * width; 00238 line = pixGetData(pix) + pixWpl * (height - 1); 00239 for (i = 0; i < height; i++) { 00240 for (j = 0; j < width; j++) { 00241 pword = line + j; 00242 if (fread(&pel, 1, 3, fp) != 3) 00243 readerror = 1; 00244 *((l_uint8 *)pword + COLOR_RED) = pel[2]; 00245 *((l_uint8 *)pword + COLOR_GREEN) = pel[1]; 00246 *((l_uint8 *)pword + COLOR_BLUE) = pel[0]; 00247 } 00248 if (extrabytes) { 00249 for (k = 0; k < extrabytes; k++) 00250 ignore = fread(&pel, 1, 1, fp); 00251 } 00252 line -= pixWpl; 00253 } 00254 if (readerror) { 00255 pixDestroy(&pix); 00256 return (PIX *)ERROR_PTR("BMP read fail", procName, NULL); 00257 } 00258 } 00259 00260 pixEndianByteSwap(pix); 00261 00262 /* ---------------------------------------------- 00263 * The bmp colormap determines the values of black 00264 * and white pixels for binary in the following way: 00265 * if black = 1 (255), white = 0 00266 * 255, 255, 255, 0, 0, 0, 0, 0 00267 * if black = 0, white = 1 (255) 00268 * 0, 0, 0, 0, 255, 255, 255, 0 00269 * We have no need for a 1 bpp pix with a colormap! 00270 * ---------------------------------------------- */ 00271 if (depth == 1 && cmap) { 00272 /* L_INFO("Removing colormap", procName); */ 00273 pixt = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); 00274 pixDestroy(&pix); 00275 pix = pixt; /* rename */ 00276 } 00277 00278 return pix; 00279 } 00280 00281 00282 00283 /*! 00284 * pixWriteStreamBmp() 00285 * 00286 * Input: stream opened for write 00287 * pix (1, 4, 8, 32 bpp) 00288 * Return: 0 if OK, 1 on error 00289 * 00290 * Notes: 00291 * (1) We position fp at the beginning of the stream, so it 00292 * truncates any existing data 00293 * (2) 2 bpp Bmp files are apparently not valid!. We can 00294 * write and read them, but nobody else can read ours. 00295 */ 00296 l_int32 00297 pixWriteStreamBmp(FILE *fp, 00298 PIX *pix) 00299 { 00300 l_uint32 offbytes, filebytes, fileimagebytes; 00301 l_int32 width, height, depth, d, xres, yres; 00302 l_uint16 bfType, bfSize, bfFill1, bfReserved1, bfReserved2; 00303 l_uint16 bfOffBits, bfFill2, biPlanes, biBitCount; 00304 l_uint16 sval; 00305 l_uint32 biSize, biWidth, biHeight, biCompression, biSizeImage; 00306 l_uint32 biXPelsPerMeter, biYPelsPerMeter, biClrUsed, biClrImportant; 00307 l_int32 pixWpl, pixBpl, extrabytes, writeerror; 00308 l_int32 fileBpl, fileWpl; 00309 l_int32 i, j, k; 00310 l_int32 heapcm; /* extra copy of cta on the heap ? 1 : 0 */ 00311 l_uint8 *data; 00312 l_uint8 pel[4]; 00313 l_uint32 *line, *pword; 00314 PIXCMAP *cmap; 00315 l_uint8 *cta; /* address of the bmp color table array */ 00316 l_int32 cmaplen; /* number of bytes in the bmp colormap */ 00317 l_int32 ncolors, val, stepsize; 00318 RGBA_QUAD *pquad; 00319 00320 PROCNAME("pixWriteStreamBmp"); 00321 00322 if (!fp) 00323 return ERROR_INT("stream not defined", procName, 1); 00324 if (!pix) 00325 return ERROR_INT("pix not defined", procName, 1); 00326 00327 width = pixGetWidth(pix); 00328 height = pixGetHeight(pix); 00329 d = pixGetDepth(pix); 00330 if (d == 2) 00331 L_WARNING("writing 2 bpp bmp file; nobody else can read", procName); 00332 depth = d; 00333 if (d == 32) 00334 depth = 24; 00335 xres = (l_int32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5); /* to ppm */ 00336 yres = (l_int32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5); /* to ppm */ 00337 00338 pixWpl = pixGetWpl(pix); 00339 pixBpl = 4 * pixWpl; 00340 fileWpl = (width * depth + 31) / 32; 00341 fileBpl = 4 * fileWpl; 00342 fileimagebytes = height * fileBpl; 00343 00344 heapcm = 0; 00345 if (d == 32) { /* 24 bpp rgb; no colormap */ 00346 ncolors = 0; 00347 cmaplen = 0; 00348 } 00349 else if ((cmap = pixGetColormap(pix))) { /* existing colormap */ 00350 ncolors = pixcmapGetCount(cmap); 00351 cmaplen = ncolors * sizeof(RGBA_QUAD); 00352 cta = (l_uint8 *)cmap->array; 00353 } 00354 else { /* no existing colormap; make a binary or gray one */ 00355 if (d == 1) { 00356 cmaplen = sizeof(bwmap); 00357 ncolors = 2; 00358 cta = (l_uint8 *)bwmap; 00359 } 00360 else { /* d != 32; output grayscale version */ 00361 ncolors = 1 << depth; 00362 cmaplen = ncolors * sizeof(RGBA_QUAD); 00363 00364 heapcm = 1; 00365 if ((cta = (l_uint8 *)CALLOC(cmaplen, 1)) == NULL) 00366 return ERROR_INT("colormap alloc fail", procName, 1); 00367 00368 stepsize = 255 / (ncolors - 1); 00369 for (i = 0, val = 0, pquad = (RGBA_QUAD *)cta; 00370 i < ncolors; 00371 i++, val += stepsize, pquad++) { 00372 pquad->blue = pquad->green = pquad->red = val; 00373 } 00374 } 00375 } 00376 00377 #if DEBUG 00378 {l_uint8 *pcmptr; 00379 pcmptr = (l_uint8 *)pixGetColormap(pix)->array; 00380 fprintf(stderr, "Pix colormap[0] = %c%c%c%d\n", 00381 pcmptr[0], pcmptr[1], pcmptr[2], pcmptr[3]); 00382 fprintf(stderr, "Pix colormap[1] = %c%c%c%d\n", 00383 pcmptr[4], pcmptr[5], pcmptr[6], pcmptr[7]); 00384 } 00385 #endif /* DEBUG */ 00386 00387 fseek(fp, 0L, 0); 00388 00389 /* Convert to little-endian and write the file header data */ 00390 bfType = convertOnBigEnd16(BMP_ID); 00391 offbytes = BMP_FHBYTES + BMP_IHBYTES + cmaplen; 00392 filebytes = offbytes + fileimagebytes; 00393 sval = filebytes & 0x0000ffff; 00394 bfSize = convertOnBigEnd16(sval); 00395 sval = (filebytes >> 16) & 0x0000ffff; 00396 bfFill1 = convertOnBigEnd16(sval); 00397 bfReserved1 = 0; 00398 bfReserved2 = 0; 00399 sval = offbytes & 0x0000ffff; 00400 bfOffBits = convertOnBigEnd16(sval); 00401 sval = (offbytes >> 16) & 0x0000ffff; 00402 bfFill2 = convertOnBigEnd16(sval); 00403 fwrite(&bfType, 1, 2, fp); 00404 fwrite(&bfSize, 1, 2, fp); 00405 fwrite(&bfFill1, 1, 2, fp); 00406 fwrite(&bfReserved1, 1, 2, fp); 00407 fwrite(&bfReserved1, 1, 2, fp); 00408 fwrite(&bfOffBits, 1, 2, fp); 00409 fwrite(&bfFill2, 1, 2, fp); 00410 00411 /* Convert to little-endian and write the info header data */ 00412 biSize = convertOnBigEnd32(BMP_IHBYTES); 00413 biWidth = convertOnBigEnd32(width); 00414 biHeight = convertOnBigEnd32(height); 00415 biPlanes = convertOnBigEnd16(1); 00416 biBitCount = convertOnBigEnd16(depth); 00417 biCompression = 0; 00418 biSizeImage = convertOnBigEnd32(fileimagebytes); 00419 biXPelsPerMeter = convertOnBigEnd32(xres); 00420 biYPelsPerMeter = convertOnBigEnd32(yres); 00421 biClrUsed = convertOnBigEnd32(ncolors); 00422 biClrImportant = convertOnBigEnd32(ncolors); 00423 fwrite(&biSize, 1, 4, fp); 00424 fwrite(&biWidth, 1, 4, fp); 00425 fwrite(&biHeight, 1, 4, fp); 00426 fwrite(&biPlanes, 1, 2, fp); 00427 fwrite(&biBitCount, 1, 2, fp); 00428 fwrite(&biCompression, 1, 4, fp); 00429 fwrite(&biSizeImage, 1, 4, fp); 00430 fwrite(&biXPelsPerMeter, 1, 4, fp); 00431 fwrite(&biYPelsPerMeter, 1, 4, fp); 00432 fwrite(&biClrUsed, 1, 4, fp); 00433 fwrite(&biClrImportant, 1, 4, fp); 00434 00435 /* Write the colormap data */ 00436 if (ncolors > 0) { 00437 if (fwrite(cta, 1, cmaplen, fp) != cmaplen) { 00438 if (heapcm) 00439 FREE(cta); 00440 return ERROR_INT("colormap write fail", procName, 1); 00441 } 00442 if (heapcm) 00443 FREE(cta); 00444 } 00445 00446 /* When you write a binary image with a colormap 00447 * that sets BLACK to 0, you must invert the data */ 00448 if (depth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) { 00449 pixInvert(pix, pix); 00450 } 00451 00452 pixEndianByteSwap(pix); 00453 00454 writeerror = 0; 00455 if (depth != 24) { /* typ 1 or 8 bpp */ 00456 data = (l_uint8 *)pixGetData(pix) + pixBpl * (height - 1); 00457 for (i = 0; i < height; i++) { 00458 if (fwrite(data, 1, fileBpl, fp) != fileBpl) 00459 writeerror = 1; 00460 data -= pixBpl; 00461 } 00462 } 00463 else { /* 32 bpp pix; 24 bpp file 00464 * See the comments in pixReadStreamBMP() to 00465 * understand the logic behind the pixel ordering below. 00466 * Note that we have again done an endian swap on 00467 * little endian machines before arriving here, so that 00468 * the bytes are ordered on both platforms as: 00469 Red Green Blue -- 00470 |-----------|------------|-----------|-----------| 00471 */ 00472 extrabytes = fileBpl - 3 * width; 00473 line = pixGetData(pix) + pixWpl * (height - 1); 00474 for (i = 0; i < height; i++) { 00475 for (j = 0; j < width; j++) { 00476 pword = line + j; 00477 pel[2] = *((l_uint8 *)pword + COLOR_RED); 00478 pel[1] = *((l_uint8 *)pword + COLOR_GREEN); 00479 pel[0] = *((l_uint8 *)pword + COLOR_BLUE); 00480 if (fwrite(&pel, 1, 3, fp) != 3) 00481 writeerror = 1; 00482 } 00483 if (extrabytes) { 00484 for (k = 0; k < extrabytes; k++) 00485 fwrite(&pel, 1, 1, fp); 00486 } 00487 line -= pixWpl; 00488 } 00489 } 00490 00491 /* Restore to original state */ 00492 pixEndianByteSwap(pix); 00493 if (depth == 1 && cmap && ((l_uint8 *)(cmap->array))[0] == 0x0) 00494 pixInvert(pix, pix); 00495 00496 if (writeerror) 00497 return ERROR_INT("image write fail", procName, 1); 00498 00499 return 0; 00500 } 00501 00502 00503 /*---------------------------------------------------------------------* 00504 * Read/write to memory * 00505 *---------------------------------------------------------------------*/ 00506 #ifdef HAVE_CONFIG_H 00507 #include "config_auto.h" 00508 #endif /* HAVE_CONFIG_H */ 00509 00510 #if HAVE_FMEMOPEN 00511 00512 extern FILE *open_memstream(char **data, size_t *size); 00513 extern FILE *fmemopen(void *data, size_t size, const char *mode); 00514 00515 /*! 00516 * pixReadMemBmp() 00517 * 00518 * Input: cdata (const; bmp-encoded) 00519 * size (of data) 00520 * Return: pix, or null on error 00521 * 00522 * Notes: 00523 * (1) The @size byte of @data must be a null character. 00524 */ 00525 PIX * 00526 pixReadMemBmp(const l_uint8 *cdata, 00527 size_t size) 00528 { 00529 l_uint8 *data; 00530 FILE *fp; 00531 PIX *pix; 00532 00533 PROCNAME("pixReadMemBmp"); 00534 00535 if (!cdata) 00536 return (PIX *)ERROR_PTR("cdata not defined", procName, NULL); 00537 00538 data = (l_uint8 *)cdata; /* we're really not going to change this */ 00539 if ((fp = fmemopen(data, size, "r")) == NULL) 00540 return (PIX *)ERROR_PTR("stream not opened", procName, NULL); 00541 pix = pixReadStreamBmp(fp); 00542 fclose(fp); 00543 return pix; 00544 } 00545 00546 00547 /*! 00548 * pixWriteMemBmp() 00549 * 00550 * Input: &data (<return> data of tiff compressed image) 00551 * &size (<return> size of returned data) 00552 * pix 00553 * Return: 0 if OK, 1 on error 00554 * 00555 * Notes: 00556 * (1) See pixWriteStreamBmp() for usage. This version writes to 00557 * memory instead of to a file stream. 00558 */ 00559 l_int32 00560 pixWriteMemBmp(l_uint8 **pdata, 00561 size_t *psize, 00562 PIX *pix) 00563 { 00564 l_int32 ret; 00565 FILE *fp; 00566 00567 PROCNAME("pixWriteMemBmp"); 00568 00569 if (!pdata) 00570 return ERROR_INT("&data not defined", procName, 1 ); 00571 if (!psize) 00572 return ERROR_INT("&size not defined", procName, 1 ); 00573 if (!pix) 00574 return ERROR_INT("&pix not defined", procName, 1 ); 00575 00576 if ((fp = open_memstream((char **)pdata, psize)) == NULL) 00577 return ERROR_INT("stream not opened", procName, 1); 00578 ret = pixWriteStreamBmp(fp, pix); 00579 fclose(fp); 00580 return ret; 00581 } 00582 00583 #else 00584 00585 PIX * 00586 pixReadMemBmp(const l_uint8 *cdata, 00587 size_t size) 00588 { 00589 return (PIX *)ERROR_PTR( 00590 "bmp read from memory not implemented on this platform", 00591 "pixReadMemBmp", NULL); 00592 } 00593 00594 00595 l_int32 00596 pixWriteMemBmp(l_uint8 **pdata, 00597 size_t *psize, 00598 PIX *pix) 00599 { 00600 return ERROR_INT( 00601 "bmp write to memory not implemented on this platform", 00602 "pixWriteMemBmp", 1); 00603 } 00604 00605 #endif /* HAVE_FMEMOPEN */ 00606 00607 /* --------------------------------------------*/ 00608 #endif /* USE_BMPIO */ 00609 /* --------------------------------------------*/ 00610