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 * pnmio.c 00018 * 00019 * Stream interface 00020 * PIX *pixReadStreamPnm() 00021 * l_int32 readHeaderPnm() 00022 * l_int32 freadHeaderPnm() 00023 * l_int32 pixWriteStreamPnm() 00024 * l_int32 pixWriteStreamAsciiPnm() 00025 * 00026 * Read/write to memory [not on windows] 00027 * PIX *pixReadMemPnm() 00028 * l_int32 sreadHeaderPnm() 00029 * l_int32 pixWriteMemPnm() 00030 * 00031 * Local helpers 00032 * static l_int32 pnmReadNextAsciiValue(); 00033 * static l_int32 pnmSkipCommentLines(); 00034 * 00035 * These are here by popular demand, with the help of Mattias 00036 * Kregert (mattias@kregert.se), who provided the first implementation. 00037 * 00038 * The pnm formats are exceedingly simple, because they have 00039 * no compression and no colormaps. They support images that 00040 * are 1 bpp; 2, 4, 8 and 16 bpp grayscale; and rgb. 00041 * 00042 * The original pnm formats ("ascii") are included for completeness, 00043 * but their use is deprecated for all but tiny iconic images. 00044 * They are extremely wasteful of memory; for example, the P1 binary 00045 * ascii format is 16 times as big as the packed uncompressed 00046 * format, because 2 characters are used to represent every bit 00047 * (pixel) in the image. Reading is slow because we check for extra 00048 * white space and EOL at every sample value. 00049 * 00050 * The packed pnm formats ("raw") give file sizes similar to 00051 * bmp files, which are uncompressed packed. However, bmp 00052 * are more flexible, because they can support colormaps. 00053 * 00054 * We don't differentiate between the different types ("pbm", 00055 * "pgm", "ppm") at the interface level, because this is really a 00056 * "distinction without a difference." You read a file, you get 00057 * the appropriate Pix. You write a file from a Pix, you get the 00058 * appropriate type of file. If there is a colormap on the Pix, 00059 * and the Pix is more than 1 bpp, you get either an 8 bpp pgm 00060 * or a 24 bpp RGB pnm, depending on whether the colormap colors 00061 * are gray or rgb, respectively. 00062 * 00063 * This follows the general policy that the I/O routines don't 00064 * make decisions about the content of the image -- you do that 00065 * with image processing before you write it out to file. 00066 * The I/O routines just try to make the closest connection 00067 * possible between the file and the Pix in memory. 00068 */ 00069 00070 #include <string.h> 00071 #include "allheaders.h" 00072 00073 /* --------------------------------------------*/ 00074 #if USE_PNMIO /* defined in environ.h */ 00075 /* --------------------------------------------*/ 00076 00077 00078 static l_int32 pnmReadNextAsciiValue(FILE *fp, l_int32 *pval); 00079 static l_int32 pnmSkipCommentLines(FILE *fp); 00080 00081 /* a sanity check on the size read from file */ 00082 static const l_int32 MAX_PNM_WIDTH = 100000; 00083 static const l_int32 MAX_PNM_HEIGHT = 100000; 00084 00085 00086 /*--------------------------------------------------------------------* 00087 * Stream interface * 00088 *--------------------------------------------------------------------*/ 00089 /*! 00090 * pixReadStreamPnm() 00091 * 00092 * Input: stream opened for read 00093 * Return: pix, or null on error 00094 */ 00095 PIX * 00096 pixReadStreamPnm(FILE *fp) 00097 { 00098 l_uint8 val8, rval8, gval8, bval8; 00099 l_uint16 val16; 00100 l_int32 w, h, d, bpl, wpl, i, j, type; 00101 l_int32 val, rval, gval, bval; 00102 l_uint32 rgbval; 00103 l_uint32 *line, *data; 00104 PIX *pix; 00105 00106 PROCNAME("pixReadStreamPnm"); 00107 00108 if (!fp) 00109 return (PIX *)ERROR_PTR("fp not defined", procName, NULL); 00110 00111 if (freadHeaderPnm(fp, &pix, &w, &h, &d, &type, NULL, NULL)) 00112 return (PIX *)ERROR_PTR( "pix not made", procName, NULL); 00113 data = pixGetData(pix); 00114 wpl = pixGetWpl(pix); 00115 00116 /* Old "ascii" format */ 00117 if (type <= 3) { 00118 for (i = 0; i < h; i++) { 00119 for (j = 0; j < w; j++) { 00120 if (type == 1 || type == 2) { 00121 if (pnmReadNextAsciiValue(fp, &val)) 00122 return (PIX *)ERROR_PTR( "read abend", procName, pix); 00123 pixSetPixel(pix, j, i, val); 00124 } 00125 else { /* type == 3 */ 00126 if (pnmReadNextAsciiValue(fp, &rval)) 00127 return (PIX *)ERROR_PTR( "read abend", procName, pix); 00128 if (pnmReadNextAsciiValue(fp, &gval)) 00129 return (PIX *)ERROR_PTR( "read abend", procName, pix); 00130 if (pnmReadNextAsciiValue(fp, &bval)) 00131 return (PIX *)ERROR_PTR( "read abend", procName, pix); 00132 composeRGBPixel(rval, gval, bval, &rgbval); 00133 pixSetPixel(pix, j, i, rgbval); 00134 } 00135 } 00136 } 00137 return pix; 00138 } 00139 00140 /* "raw" format for 1 bpp */ 00141 if (type == 4) { 00142 bpl = (d * w + 7) / 8; 00143 for (i = 0; i < h; i++) { 00144 line = data + i * wpl; 00145 for (j = 0; j < bpl; j++) { 00146 if (fread(&val8, 1, 1, fp) != 1) 00147 return (PIX *)ERROR_PTR( "read error in 4", procName, pix); 00148 SET_DATA_BYTE(line, j, val8); 00149 } 00150 } 00151 return pix; 00152 } 00153 00154 /* "raw" format for grayscale */ 00155 if (type == 5) { 00156 bpl = (d * w + 7) / 8; 00157 for (i = 0; i < h; i++) { 00158 line = data + i * wpl; 00159 if (d != 16) { 00160 for (j = 0; j < w; j++) { 00161 if (fread(&val8, 1, 1, fp) != 1) 00162 return (PIX *)ERROR_PTR( "error in 5", procName, pix); 00163 if (d == 2) 00164 SET_DATA_DIBIT(line, j, val8); 00165 else if (d == 4) 00166 SET_DATA_QBIT(line, j, val8); 00167 else /* d == 8 */ 00168 SET_DATA_BYTE(line, j, val8); 00169 } 00170 } 00171 else { /* d == 16 */ 00172 for (j = 0; j < w; j++) { 00173 if (fread(&val16, 2, 1, fp) != 1) 00174 return (PIX *)ERROR_PTR( "16 bpp error", procName, pix); 00175 SET_DATA_TWO_BYTES(line, j, val16); 00176 } 00177 } 00178 } 00179 return pix; 00180 } 00181 00182 /* "raw" format, type == 6; rgb */ 00183 for (i = 0; i < h; i++) { 00184 line = data + i * wpl; 00185 for (j = 0; j < wpl; j++) { 00186 if (fread(&rval8, 1, 1, fp) != 1) 00187 return (PIX *)ERROR_PTR( "read error type 6", procName, pix); 00188 if (fread(&gval8, 1, 1, fp) != 1) 00189 return (PIX *)ERROR_PTR( "read error type 6", procName, pix); 00190 if (fread(&bval8, 1, 1, fp) != 1) 00191 return (PIX *)ERROR_PTR( "read error type 6", procName, pix); 00192 composeRGBPixel(rval8, gval8, bval8, &rgbval); 00193 line[j] = rgbval; 00194 } 00195 } 00196 return pix; 00197 } 00198 00199 00200 /*! 00201 * readHeaderPnm() 00202 * 00203 * Input: filename 00204 * &pix (<optional return> use null to return only header data) 00205 * &width (<return>) 00206 * &height (<return>) 00207 * &depth (<return>) 00208 * &type (<return> pnm type) 00209 * &bps (<optional return>, bits/sample) 00210 * &spp (<optional return>, samples/pixel) 00211 * Return: 0 if OK, 1 on error 00212 */ 00213 l_int32 00214 readHeaderPnm(const char *filename, 00215 PIX **ppix, 00216 l_int32 *pwidth, 00217 l_int32 *pheight, 00218 l_int32 *pdepth, 00219 l_int32 *ptype, 00220 l_int32 *pbps, 00221 l_int32 *pspp) 00222 { 00223 l_int32 ret; 00224 FILE *fp; 00225 00226 PROCNAME("readHeaderPnm"); 00227 00228 if (!filename) 00229 return ERROR_INT("filename not defined", procName, 1); 00230 if (!pwidth || !pheight || !pbps || !pspp) 00231 return ERROR_INT("input ptr(s) not defined", procName, 1); 00232 if ((fp = fopenReadStream(filename)) == NULL) 00233 return ERROR_INT("image file not found", procName, 1); 00234 ret = freadHeaderPnm(fp, ppix, pwidth, pheight, pdepth, ptype, pbps, pspp); 00235 fclose(fp); 00236 return ret; 00237 } 00238 00239 00240 /*! 00241 * freadHeaderPnm() 00242 * 00243 * Input: stream opened for read 00244 * &pix (<optional return> use null to return only header data) 00245 * &width (<return>) 00246 * &height (<return>) 00247 * &depth (<return>) 00248 * &type (<return> pnm type) 00249 * &bps (<optional return>, bits/sample) 00250 * &spp (<optional return>, samples/pixel) 00251 * Return: 0 if OK, 1 on error 00252 */ 00253 l_int32 00254 freadHeaderPnm(FILE *fp, 00255 PIX **ppix, 00256 l_int32 *pwidth, 00257 l_int32 *pheight, 00258 l_int32 *pdepth, 00259 l_int32 *ptype, 00260 l_int32 *pbps, 00261 l_int32 *pspp) 00262 { 00263 l_int32 w, h, d, type; 00264 l_int32 maxval; 00265 00266 PROCNAME("freadHeaderPnm"); 00267 00268 if (!fp) 00269 return ERROR_INT("fp not defined", procName, 1); 00270 if (!pwidth || !pheight || !pdepth || !ptype) 00271 return ERROR_INT("input ptr(s) not defined", procName, 1); 00272 00273 if (fscanf(fp, "P%d\n", &type) != 1) 00274 return ERROR_INT("invalid read for type", procName, 1); 00275 if (type < 1 || type > 6) 00276 return ERROR_INT("invalid pnm file", procName, 1); 00277 00278 if (pnmSkipCommentLines(fp)) 00279 return ERROR_INT("no data in file", procName, 1); 00280 00281 if (fscanf(fp, "%d %d\n", &w, &h) != 2) 00282 return ERROR_INT("invalid read for w,h", procName, 1); 00283 if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT) 00284 return ERROR_INT("invalid sizes", procName, 1); 00285 00286 /* Get depth of pix */ 00287 if (type == 1 || type == 4) 00288 d = 1; 00289 else if (type == 2 || type == 5) { 00290 if (fscanf(fp, "%d\n", &maxval) != 1) 00291 return ERROR_INT("invalid read for maxval (2,5)", procName, 1); 00292 if (maxval == 3) 00293 d = 2; 00294 else if (maxval == 15) 00295 d = 4; 00296 else if (maxval == 255) 00297 d = 8; 00298 else if (maxval == 0xffff) 00299 d = 16; 00300 else { 00301 fprintf(stderr, "maxval = %d\n", maxval); 00302 return ERROR_INT("invalid maxval", procName, 1); 00303 } 00304 } 00305 else { /* type == 3 || type == 6; this is rgb */ 00306 if (fscanf(fp, "%d\n", &maxval) != 1) 00307 return ERROR_INT("invalid read for maxval (3,6)", procName, 1); 00308 if (maxval != 255) 00309 L_WARNING_INT("unexpected maxval = %d", procName, maxval); 00310 d = 32; 00311 } 00312 *pwidth = w; 00313 *pheight = h; 00314 *pdepth = d; 00315 *ptype = type; 00316 if (pbps) *pbps = (d == 32) ? 8 : d; 00317 if (pspp) *pspp = (d == 32) ? 3 : 1; 00318 00319 if (!ppix) 00320 return 0; 00321 00322 if ((*ppix = pixCreate(w, h, d)) == NULL) /* return pix initialized to 0 */ 00323 return ERROR_INT( "pix not made", procName, 1); 00324 return 0; 00325 } 00326 00327 00328 /*! 00329 * pixWriteStreamPnm() 00330 * 00331 * Input: stream opened for write 00332 * pix 00333 * Return: 0 if OK; 1 on error 00334 * 00335 * Notes: 00336 * (1) This writes "raw" packed format only: 00337 * 1 bpp --> pbm (P4) 00338 * 2, 4, 8, 16 bpp, no colormap or grayscale colormap --> pgm (P5) 00339 * 2, 4, 8 bpp with color-valued colormap, or rgb --> rgb ppm (P6) 00340 * (2) 24 bpp rgb are not supported in leptonica, but this will 00341 * write them out as a packed array of bytes (3 to a pixel). 00342 */ 00343 l_int32 00344 pixWriteStreamPnm(FILE *fp, 00345 PIX *pix) 00346 { 00347 l_uint8 val8; 00348 l_uint8 pel[4]; 00349 l_uint16 val16; 00350 l_int32 h, w, d, ds, i, j, wpls, bpl, filebpl, writeerror, maxval; 00351 l_uint32 *pword, *datas, *lines; 00352 PIX *pixs; 00353 00354 PROCNAME("pixWriteStreamPnm"); 00355 00356 if (!fp) 00357 return ERROR_INT("fp not defined", procName, 1); 00358 if (!pix) 00359 return ERROR_INT("pix not defined", procName, 1); 00360 00361 pixGetDimensions(pix, &w, &h, &d); 00362 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 24 && d != 32) 00363 return ERROR_INT("d not in {1,2,4,8,16,24,32}", procName, 1); 00364 00365 /* If a colormap exists, remove and convert to grayscale or rgb */ 00366 if (pixGetColormap(pix) != NULL) 00367 pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); 00368 else 00369 pixs = pixClone(pix); 00370 ds = pixGetDepth(pixs); 00371 datas = pixGetData(pixs); 00372 wpls = pixGetWpl(pixs); 00373 00374 writeerror = 0; 00375 if (ds == 1) { /* binary */ 00376 fprintf(fp, "P4\n# Raw PBM file written by leptonica " 00377 "(www.leptonica.com)\n%d %d\n", w, h); 00378 00379 bpl = (w + 7) / 8; 00380 for (i = 0; i < h; i++) { 00381 lines = datas + i * wpls; 00382 for (j = 0; j < bpl; j++) { 00383 val8 = GET_DATA_BYTE(lines, j); 00384 fwrite(&val8, 1, 1, fp); 00385 } 00386 } 00387 } 00388 else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */ 00389 maxval = (1 << ds) - 1; 00390 fprintf(fp, "P5\n# Raw PGM file written by leptonica " 00391 "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval); 00392 00393 if (ds != 16) { 00394 for (i = 0; i < h; i++) { 00395 lines = datas + i * wpls; 00396 for (j = 0; j < w; j++) { 00397 if (ds == 2) 00398 val8 = GET_DATA_DIBIT(lines, j); 00399 else if (ds == 4) 00400 val8 = GET_DATA_QBIT(lines, j); 00401 else /* ds == 8 */ 00402 val8 = GET_DATA_BYTE(lines, j); 00403 fwrite(&val8, 1, 1, fp); 00404 } 00405 } 00406 } 00407 else { /* ds == 16 */ 00408 for (i = 0; i < h; i++) { 00409 lines = datas + i * wpls; 00410 for (j = 0; j < w; j++) { 00411 val16 = GET_DATA_TWO_BYTES(lines, j); 00412 fwrite(&val16, 2, 1, fp); 00413 } 00414 } 00415 } 00416 } 00417 else { /* rgb color */ 00418 fprintf(fp, "P6\n# Raw PPM file written by leptonica " 00419 "(www.leptonica.com)\n%d %d\n255\n", w, h); 00420 00421 if (d == 24) { /* packed, 3 bytes to a pixel */ 00422 filebpl = 3 * w; 00423 for (i = 0; i < h; i++) { /* write out each raster line */ 00424 lines = datas + i * wpls; 00425 if (fwrite(lines, 1, filebpl, fp) != filebpl) 00426 writeerror = 1; 00427 } 00428 } 00429 else { /* 32 bpp rgb */ 00430 for (i = 0; i < h; i++) { 00431 lines = datas + i * wpls; 00432 for (j = 0; j < wpls; j++) { 00433 pword = lines + j; 00434 pel[0] = *((l_uint8 *)pword + 3); /* red */ 00435 pel[1] = *((l_uint8 *)pword + 2); /* green */ 00436 pel[2] = *((l_uint8 *)pword + 1); /* blue */ 00437 if (fwrite(&pel, 1, 3, fp) != 3) 00438 writeerror = 1; 00439 } 00440 } 00441 } 00442 } 00443 00444 pixDestroy(&pixs); 00445 if (writeerror) 00446 return ERROR_INT("image write fail", procName, 1); 00447 return 0; 00448 } 00449 00450 00451 /*! 00452 * pixWriteStreamAsciiPnm() 00453 * 00454 * Input: stream opened for write 00455 * pix 00456 * Return: 0 if OK; 1 on error 00457 * 00458 * Writes "ascii" format only: 00459 * 1 bpp --> pbm (P1) 00460 * 2, 4, 8, 16 bpp, no colormap or grayscale colormap --> pgm (P2) 00461 * 2, 4, 8 bpp with color-valued colormap, or rgb --> rgb ppm (P3) 00462 */ 00463 l_int32 00464 pixWriteStreamAsciiPnm(FILE *fp, 00465 PIX *pix) 00466 { 00467 char buffer[256]; 00468 l_uint8 cval[3]; 00469 l_int32 h, w, d, ds, i, j, k, maxval, count; 00470 l_uint32 val; 00471 PIX *pixs; 00472 00473 PROCNAME("pixWriteStreamAsciiPnm"); 00474 00475 if (!fp) 00476 return ERROR_INT("fp not defined", procName, 1); 00477 if (!pix) 00478 return ERROR_INT("pix not defined", procName, 1); 00479 00480 pixGetDimensions(pix, &w, &h, &d); 00481 if (d != 1 && d != 2 && d != 4 && d != 8 && d != 16 && d != 32) 00482 return ERROR_INT("d not in {1,2,4,8,16,32}", procName, 1); 00483 00484 /* If a colormap exists, remove and convert to grayscale or rgb */ 00485 if (pixGetColormap(pix) != NULL) 00486 pixs = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); 00487 else 00488 pixs = pixClone(pix); 00489 ds = pixGetDepth(pixs); 00490 00491 if (ds == 1) { /* binary */ 00492 fprintf(fp, "P1\n# Ascii PBM file written by leptonica " 00493 "(www.leptonica.com)\n%d %d\n", w, h); 00494 00495 count = 0; 00496 for (i = 0; i < h; i++) { 00497 for (j = 0; j < w; j++) { 00498 pixGetPixel(pixs, j, i, &val); 00499 if (val == 0) 00500 fputc('0', fp); 00501 else /* val == 1 */ 00502 fputc('1', fp); 00503 fputc(' ', fp); 00504 count += 2; 00505 if (count >= 70) 00506 fputc('\n', fp); 00507 } 00508 } 00509 } 00510 else if (ds == 2 || ds == 4 || ds == 8 || ds == 16) { /* grayscale */ 00511 maxval = (1 << ds) - 1; 00512 fprintf(fp, "P2\n# Ascii PGM file written by leptonica " 00513 "(www.leptonica.com)\n%d %d\n%d\n", w, h, maxval); 00514 00515 count = 0; 00516 for (i = 0; i < h; i++) { 00517 for (j = 0; j < w; j++) { 00518 pixGetPixel(pixs, j, i, &val); 00519 if (ds == 2) { 00520 sprintf(buffer, "%1d ", val); 00521 fwrite(buffer, 1, 2, fp); 00522 count += 2; 00523 } 00524 else if (ds == 4) { 00525 sprintf(buffer, "%2d ", val); 00526 fwrite(buffer, 1, 3, fp); 00527 count += 3; 00528 } 00529 else if (ds == 8) { 00530 sprintf(buffer, "%3d ", val); 00531 fwrite(buffer, 1, 4, fp); 00532 count += 4; 00533 } 00534 else { /* ds == 16 */ 00535 sprintf(buffer, "%5d ", val); 00536 fwrite(buffer, 1, 6, fp); 00537 count += 6; 00538 } 00539 if (count >= 60) { 00540 fputc('\n', fp); 00541 count = 0; 00542 } 00543 } 00544 } 00545 } 00546 else { /* rgb color */ 00547 fprintf(fp, "P3\n# Ascii PPM file written by leptonica " 00548 "(www.leptonica.com)\n%d %d\n255\n", w, h); 00549 00550 count = 0; 00551 for (i = 0; i < h; i++) { 00552 for (j = 0; j < w; j++) { 00553 pixGetPixel(pixs, j, i, &val); 00554 cval[0] = GET_DATA_BYTE(&val, COLOR_RED); 00555 cval[1] = GET_DATA_BYTE(&val, COLOR_GREEN); 00556 cval[2] = GET_DATA_BYTE(&val, COLOR_BLUE); 00557 for (k = 0; k < 3; k++) { 00558 sprintf(buffer, "%3d ", cval[k]); 00559 fwrite(buffer, 1, 4, fp); 00560 count += 4; 00561 if (count >= 60) { 00562 fputc('\n', fp); 00563 count = 0; 00564 } 00565 } 00566 } 00567 } 00568 } 00569 00570 pixDestroy(&pixs); 00571 return 0; 00572 } 00573 00574 00575 /*---------------------------------------------------------------------* 00576 * Read/write to memory * 00577 *---------------------------------------------------------------------*/ 00578 #ifdef HAVE_CONFIG_H 00579 #include "config_auto.h" 00580 #endif /* HAVE_CONFIG_H */ 00581 00582 #if HAVE_FMEMOPEN 00583 00584 extern FILE *open_memstream(char **data, size_t *size); 00585 extern FILE *fmemopen(void *data, size_t size, const char *mode); 00586 00587 /*! 00588 * pixReadMemPnm() 00589 * 00590 * Input: cdata (const; pnm-encoded) 00591 * size (of data) 00592 * Return: pix, or null on error 00593 * 00594 * Notes: 00595 * (1) The @size byte of @data must be a null character. 00596 */ 00597 PIX * 00598 pixReadMemPnm(const l_uint8 *cdata, 00599 size_t size) 00600 { 00601 l_uint8 *data; 00602 FILE *fp; 00603 PIX *pix; 00604 00605 PROCNAME("pixReadMemPnm"); 00606 00607 if (!cdata) 00608 return (PIX *)ERROR_PTR("cdata not defined", procName, NULL); 00609 00610 data = (l_uint8 *)cdata; /* we're really not going to change this */ 00611 if ((fp = fmemopen(data, size, "r")) == NULL) 00612 return (PIX *)ERROR_PTR("stream not opened", procName, NULL); 00613 pix = pixReadStreamPnm(fp); 00614 fclose(fp); 00615 return pix; 00616 } 00617 00618 00619 /*! 00620 * sreadHeaderPnm() 00621 * 00622 * Input: cdata (const; pnm-encoded) 00623 * size (of data) 00624 * &width (<return>) 00625 * &height (<return>) 00626 * &depth (<return>) 00627 * &type (<return> pnm type) 00628 * &bps (<optional return>, bits/sample) 00629 * &spp (<optional return>, samples/pixel) 00630 * Return: 0 if OK, 1 on error 00631 */ 00632 l_int32 00633 sreadHeaderPnm(const l_uint8 *cdata, 00634 size_t size, 00635 l_int32 *pwidth, 00636 l_int32 *pheight, 00637 l_int32 *pdepth, 00638 l_int32 *ptype, 00639 l_int32 *pbps, 00640 l_int32 *pspp) 00641 { 00642 l_int32 ret; 00643 l_uint8 *data; 00644 FILE *fp; 00645 00646 PROCNAME("sreadHeaderPnm"); 00647 00648 if (!cdata) 00649 return ERROR_INT("cdata not defined", procName, 1); 00650 00651 data = (l_uint8 *)cdata; /* we're really not going to change this */ 00652 if ((fp = fmemopen(data, size, "r")) == NULL) 00653 return ERROR_INT("stream not opened", procName, 1); 00654 ret = freadHeaderPnm(fp, NULL, pwidth, pheight, pdepth, ptype, pbps, pspp); 00655 fclose(fp); 00656 if (ret) 00657 return ERROR_INT("header data read failed", procName, 1); 00658 return 0; 00659 } 00660 00661 00662 /*! 00663 * pixWriteMemPnm() 00664 * 00665 * Input: &data (<return> data of tiff compressed image) 00666 * &size (<return> size of returned data) 00667 * pix 00668 * Return: 0 if OK, 1 on error 00669 * 00670 * Notes: 00671 * (1) See pixWriteStreamPnm() for usage. This version writes to 00672 * memory instead of to a file stream. 00673 */ 00674 l_int32 00675 pixWriteMemPnm(l_uint8 **pdata, 00676 size_t *psize, 00677 PIX *pix) 00678 { 00679 l_int32 ret; 00680 FILE *fp; 00681 00682 PROCNAME("pixWriteMemPnm"); 00683 00684 if (!pdata) 00685 return ERROR_INT("&data not defined", procName, 1 ); 00686 if (!psize) 00687 return ERROR_INT("&size not defined", procName, 1 ); 00688 if (!pix) 00689 return ERROR_INT("&pix not defined", procName, 1 ); 00690 00691 if ((fp = open_memstream((char **)pdata, psize)) == NULL) 00692 return ERROR_INT("stream not opened", procName, 1); 00693 ret = pixWriteStreamPnm(fp, pix); 00694 fclose(fp); 00695 return ret; 00696 } 00697 00698 #else 00699 00700 PIX * 00701 pixReadMemPnm(const l_uint8 *cdata, 00702 size_t size) 00703 { 00704 return (PIX *)ERROR_PTR( 00705 "pnm read from memory not implemented on this platform", 00706 "pixReadMemPnm", NULL); 00707 } 00708 00709 00710 l_int32 00711 sreadHeaderPnm(const l_uint8 *cdata, 00712 size_t size, 00713 l_int32 *pwidth, 00714 l_int32 *pheight, 00715 l_int32 *pdepth, 00716 l_int32 *ptype, 00717 l_int32 *pbps, 00718 l_int32 *pspp) 00719 { 00720 return ERROR_INT( 00721 "pnm read header from memory not implemented on this platform", 00722 "sreadHeaderPnm", 1); 00723 } 00724 00725 00726 l_int32 00727 pixWriteMemPnm(l_uint8 **pdata, 00728 size_t *psize, 00729 PIX *pix) 00730 { 00731 return ERROR_INT( 00732 "pnm write to memory not implemented on this platform", 00733 "pixWriteMemPnm", 1); 00734 } 00735 00736 #endif /* HAVE_FMEMOPEN */ 00737 00738 00739 /*--------------------------------------------------------------------* 00740 * Static helpers * 00741 *--------------------------------------------------------------------*/ 00742 /*! 00743 * pnmReadNextAsciiValue() 00744 * 00745 * Return: 0 if OK, 1 on error or EOF. 00746 * 00747 * Notes: 00748 * (1) This reads the next sample value in ascii from the the file. 00749 */ 00750 static l_int32 00751 pnmReadNextAsciiValue(FILE *fp, 00752 l_int32 *pval) 00753 { 00754 l_int32 c, ignore; 00755 00756 PROCNAME("pnmReadNextAsciiValue"); 00757 00758 if (!fp) 00759 return ERROR_INT("stream not open", procName, 1); 00760 if (!pval) 00761 return ERROR_INT("&val not defined", procName, 1); 00762 *pval = 0; 00763 do { /* skip whitespace */ 00764 if ((c = fgetc(fp)) == EOF) 00765 return 1; 00766 } while (c == ' ' || c == '\t' || c == '\n' || c == '\r'); 00767 00768 fseek(fp, -1L, SEEK_CUR); /* back up one byte */ 00769 ignore = fscanf(fp, "%d", pval); 00770 return 0; 00771 } 00772 00773 00774 /*! 00775 * pnmSkipCommentLines() 00776 * 00777 * Return: 0 if OK, 1 on error or EOF 00778 * 00779 * Notes: 00780 * (1) Comment lines begin with '#' 00781 * (2) Usage: caller should check return value for EOF 00782 */ 00783 static l_int32 00784 pnmSkipCommentLines(FILE *fp) 00785 { 00786 l_int32 c; 00787 00788 PROCNAME("pnmSkipCommentLines"); 00789 00790 if (!fp) 00791 return ERROR_INT("stream not open", procName, 1); 00792 if ((c = fgetc(fp)) == EOF) 00793 return 1; 00794 if (c == '#') { 00795 do { /* each line starting with '#' */ 00796 do { /* this entire line */ 00797 if ((c = fgetc(fp)) == EOF) 00798 return 1; 00799 } while (c != '\n'); 00800 if ((c = fgetc(fp)) == EOF) 00801 return 1; 00802 } while (c == '#'); 00803 } 00804 00805 /* Back up one byte */ 00806 fseek(fp, -1L, SEEK_CUR); 00807 return 0; 00808 } 00809 00810 /* --------------------------------------------*/ 00811 #endif /* USE_PNMIO */ 00812 /* --------------------------------------------*/