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 * pixcomp.c 00018 * 00019 * Pixcomp creation and destruction 00020 * PIXC *pixcompCreateFromPix() 00021 * PIXC *pixcompCreateFromString() 00022 * PIXC *pixcompCreateFromFile() 00023 * void pixcompDestroy() 00024 00025 * Pixcomp accessors 00026 * l_int32 pixcompGetDimensions() 00027 * l_int32 pixcompDetermineFormat() 00028 * 00029 * Pixcomp conversion to Pix 00030 * PIX *pixCreateFromPixcomp() 00031 * 00032 * Pixacomp creation and destruction 00033 * PIXAC *pixacompCreate() 00034 * PIXAC *pixacompCreateInitialized() 00035 * PIXAC *pixacompCreateFromPixa() 00036 * PIXAC *pixacompCreateFromFiles() 00037 * PIXAC *pixacompCreateFromSA() 00038 * void pixacompDestroy() 00039 * 00040 * Pixacomp addition/replacement 00041 * l_int32 pixacompAddPix() 00042 * l_int32 pixacompAddPixcomp() 00043 * l_int32 pixacompExtendArray() 00044 * l_int32 pixacompReplacePix() 00045 * l_int32 pixacompReplacePixcomp() 00046 * l_int32 pixacompAddBox() 00047 * 00048 * Pixacomp accessors 00049 * l_int32 pixacompGetCount() 00050 * PIXC *pixacompGetPixcomp() 00051 * PIX *pixacompGetPix() 00052 * l_int32 pixacompGetPixDimensions() 00053 * BOXA *pixacompGetBoxa() 00054 * l_int32 pixacompGetBoxaCount() 00055 * BOX *pixacompGetBox() 00056 * l_int32 pixacompGetBoxGeometry() 00057 * 00058 * Pixacomp conversion to Pixa 00059 * PIXA *pixaCreateFromPixacomp() 00060 * 00061 * Pixacomp serialized I/O 00062 * PIXAC *pixacompRead() 00063 * PIXAC *pixacompReadStream() 00064 * l_int32 pixacompWrite() 00065 * l_int32 pixacompWriteStream() 00066 * 00067 * Output for debugging 00068 * l_int32 pixacompWriteStreamInfo() 00069 * l_int32 pixcompWriteStreamInfo() 00070 * PIX *pixacompDisplayTiledAndScaled() 00071 * 00072 * The Pixacomp is an array of Pixcomp, where each Pixcomp is a compressed 00073 * string of the image. We don't use reference counting here. 00074 * The basic application is to allow a large array of highly 00075 * compressible images to reside in memory. We purposely don't 00076 * reuse the Pixa for this, to avoid confusion and programming errors. 00077 * 00078 * Three compression formats are used: g4, png and jpeg. 00079 * The compression type can be either specified or defaulted. 00080 * If specified and it is not possible to compress (for example, 00081 * you specify a jpeg on a 1 bpp image or one with a colormap), 00082 * the compression type defaults to png. 00083 * 00084 * The serialized version of the Pixacomp is similar to that for 00085 * a Pixa, except that each Pixcomp can be compressed by one of 00086 * tiffg4, png, or jpeg. Unlike serialization of the Pixa, 00087 * serialization of the Pixacomp does not require any imaging 00088 * libraries because it simply reads and writes the compressed data. 00089 * 00090 * For random insertion and replacement of pixcomp into a pixcomp, 00091 * initialize a fully populated array using pixacompCreateInitialized(). 00092 * Then use pixacompReplacePix() or pixacompReplacePixcomp() for 00093 * the random insertion. 00094 */ 00095 00096 #include <string.h> 00097 #include "allheaders.h" 00098 00099 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* n'import quoi */ 00100 00101 /* These two globals are defined in writefile.c */ 00102 extern l_int32 NumImageFileFormatExtensions; 00103 extern const char *ImageFileFormatExtensions[]; 00104 00105 00106 /*---------------------------------------------------------------------* 00107 * Pixcomp creation and destruction * 00108 *---------------------------------------------------------------------*/ 00109 /*! 00110 * pixcompCreateFromPix() 00111 * 00112 * Input: pix 00113 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00114 * Return: pixc, or null on error 00115 * 00116 * Notes: 00117 * (1) Use @comptype == IFF_DEFAULT to have the compression 00118 * type automatically determined. 00119 */ 00120 PIXC * 00121 pixcompCreateFromPix(PIX *pix, 00122 l_int32 comptype) 00123 { 00124 size_t size; 00125 char *text; 00126 l_int32 ret, format; 00127 l_uint8 *data; 00128 PIXC *pixc; 00129 00130 PROCNAME("pixcompCreateFromPix"); 00131 00132 if (!pix) 00133 return (PIXC *)ERROR_PTR("pix not defined", procName, NULL); 00134 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00135 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00136 return (PIXC *)ERROR_PTR("invalid comptype", procName, NULL); 00137 00138 if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL) 00139 return (PIXC *)ERROR_PTR("pixc not made", procName, NULL); 00140 pixGetDimensions(pix, &pixc->w, &pixc->h, &pixc->d); 00141 pixGetResolution(pix, &pixc->xres, &pixc->yres); 00142 if (pixGetColormap(pix)) 00143 pixc->cmapflag = 1; 00144 if ((text = pixGetText(pix)) != NULL) 00145 pixc->text = stringNew(text); 00146 00147 pixcompDetermineFormat(comptype, pixc->d, pixc->cmapflag, &format); 00148 pixc->comptype = format; 00149 ret = pixWriteMem(&data, &size, pix, format); 00150 if (ret) { 00151 L_ERROR("write to memory failed", procName); 00152 pixcompDestroy(&pixc); 00153 return NULL; 00154 } 00155 pixc->data = data; 00156 pixc->size = size; 00157 00158 return pixc; 00159 } 00160 00161 00162 /*! 00163 * pixcompCreateFromString() 00164 * 00165 * Input: data (compressed string) 00166 * size (number of bytes) 00167 * copyflag (L_INSERT or L_COPY) 00168 * Return: pixc, or null on error 00169 * 00170 * Notes: 00171 * (1) This works when the compressed string is png, jpeg or tiffg4. 00172 * (2) The copyflag determines if the data in the new Pixcomp is 00173 * a copy of the input data. 00174 */ 00175 PIXC * 00176 pixcompCreateFromString(l_uint8 *data, 00177 size_t size, 00178 l_int32 copyflag) 00179 { 00180 l_int32 format, w, h, d, bps, spp, iscmap; 00181 PIXC *pixc; 00182 00183 PROCNAME("pixcompCreateFromString"); 00184 00185 if (!data) 00186 return (PIXC *)ERROR_PTR("data not defined", procName, NULL); 00187 if (copyflag != L_INSERT && copyflag != L_COPY) 00188 return (PIXC *)ERROR_PTR("invalid copyflag", procName, NULL); 00189 00190 if (pixReadHeaderMem(data, size, &format, &w, &h, &bps, &spp, &iscmap) == 1) 00191 return (PIXC *)ERROR_PTR("header data not read", procName, NULL); 00192 if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL) 00193 return (PIXC *)ERROR_PTR("pixc not made", procName, NULL); 00194 d = (spp == 3) ? 32 : bps * spp; 00195 pixc->w = w; 00196 pixc->h = h; 00197 pixc->d = d; 00198 pixc->comptype = format; 00199 pixc->cmapflag = iscmap; 00200 if (copyflag == L_INSERT) 00201 pixc->data = data; 00202 else 00203 pixc->data = l_binaryCopy(data, size); 00204 pixc->size = size; 00205 return pixc; 00206 } 00207 00208 00209 /*! 00210 * pixcompCreateFromFile() 00211 * 00212 * Input: filename 00213 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00214 * Return: pixc, or null on error 00215 * 00216 * Notes: 00217 * (1) Use @comptype == IFF_DEFAULT to have the compression 00218 * type automatically determined. 00219 * (2) If the comptype is invalid for this file, the default will 00220 * be substituted. 00221 */ 00222 PIXC * 00223 pixcompCreateFromFile(const char *filename, 00224 l_int32 comptype) 00225 { 00226 l_int32 format; 00227 size_t nbytes; 00228 l_uint8 *data; 00229 PIX *pix; 00230 PIXC *pixc; 00231 00232 PROCNAME("pixcompCreateFromFile"); 00233 00234 if (!filename) 00235 return (PIXC *)ERROR_PTR("filename not defined", procName, NULL); 00236 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00237 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00238 return (PIXC *)ERROR_PTR("invalid comptype", procName, NULL); 00239 00240 findFileFormat(filename, &format); 00241 if (format == IFF_UNKNOWN) 00242 return (PIXC *)ERROR_PTR("image file not readable", procName, NULL); 00243 00244 /* Can we accept the encoded file directly? Remember that 00245 * png is the "universal" compression type, so if requested 00246 * it takes precedence. Otherwise, if the file is already 00247 * compressed in g4 or jpeg, just accept the string. */ 00248 if ((format == IFF_TIFF_G4 && comptype != IFF_PNG) || 00249 (format == IFF_JFIF_JPEG && comptype != IFF_PNG)) 00250 comptype = format; 00251 if (comptype != IFF_DEFAULT && comptype == format) { 00252 data = l_binaryRead(filename, &nbytes); 00253 if ((pixc = pixcompCreateFromString(data, nbytes, L_INSERT)) == NULL) { 00254 FREE(data); 00255 return (PIXC *)ERROR_PTR("pixc not made (string)", procName, NULL); 00256 } 00257 return pixc; 00258 } 00259 00260 /* Need to recompress in the default format */ 00261 if ((pix = pixRead(filename)) == NULL) 00262 return (PIXC *)ERROR_PTR("pix not read", procName, NULL); 00263 if ((pixc = pixcompCreateFromPix(pix, comptype)) == NULL) { 00264 pixDestroy(&pix); 00265 return (PIXC *)ERROR_PTR("pixc not made", procName, NULL); 00266 } 00267 pixDestroy(&pix); 00268 return pixc; 00269 } 00270 00271 00272 /*! 00273 * pixcompDestroy() 00274 * 00275 * Input: &pixc <will be nulled> 00276 * Return: void 00277 * 00278 * Notes: 00279 * (1) Always nulls the input ptr. 00280 */ 00281 void 00282 pixcompDestroy(PIXC **ppixc) 00283 { 00284 PIXC *pixc; 00285 00286 PROCNAME("pixcompDestroy"); 00287 00288 if (!ppixc) { 00289 L_WARNING("ptr address is null!", procName); 00290 return; 00291 } 00292 00293 if ((pixc = *ppixc) == NULL) 00294 return; 00295 00296 FREE(pixc->data); 00297 if (pixc->text) 00298 FREE(pixc->text); 00299 FREE(pixc); 00300 *ppixc = NULL; 00301 return; 00302 } 00303 00304 00305 /*---------------------------------------------------------------------* 00306 * Pixcomp accessors * 00307 *---------------------------------------------------------------------*/ 00308 /*! 00309 * pixcompGetDimensions() 00310 * 00311 * Input: pixc 00312 * &w, &h, &d (<optional return>) 00313 * Return: 0 if OK, 1 on error 00314 */ 00315 l_int32 00316 pixcompGetDimensions(PIXC *pixc, 00317 l_int32 *pw, 00318 l_int32 *ph, 00319 l_int32 *pd) 00320 { 00321 PROCNAME("pixcompGetDimensions"); 00322 00323 if (!pixc) 00324 return ERROR_INT("pixc not defined", procName, 1); 00325 if (pw) *pw = pixc->w; 00326 if (ph) *ph = pixc->h; 00327 if (pd) *pd = pixc->d; 00328 return 0; 00329 } 00330 00331 00332 /*! 00333 * pixcompDetermineFormat() 00334 * 00335 * Input: comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00336 * d (pix depth) 00337 * cmapflag (1 if pix to be compressed as a colormap; 0 otherwise) 00338 * &format (return IFF_TIFF, IFF_PNG or IFF_JFIF_JPEG) 00339 * Return: 0 if OK; 1 on error 00340 * 00341 * Notes: 00342 * (1) This determines the best format for a pix, given both 00343 * the request (@comptype) and the image characteristics. 00344 * (2) If @comptype == IFF_DEFAULT, this does not necessarily result 00345 * in png encoding. Instead, it returns one of the three formats 00346 * that is both valid and most likely to give best compression. 00347 * (3) If the pix cannot be compressed by the input value of 00348 * @comptype, this selects IFF_PNG, which can compress all pix. 00349 */ 00350 l_int32 00351 pixcompDetermineFormat(l_int32 comptype, 00352 l_int32 d, 00353 l_int32 cmapflag, 00354 l_int32 *pformat) 00355 { 00356 00357 PROCNAME("pixcompDetermineFormat"); 00358 00359 if (!pformat) 00360 return ERROR_INT("&format not defined", procName, 1); 00361 *pformat = IFF_PNG; /* init value and default */ 00362 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00363 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00364 return ERROR_INT("invalid comptype", procName, 1); 00365 00366 if (comptype == IFF_DEFAULT) { 00367 if (d == 1) 00368 *pformat = IFF_TIFF_G4; 00369 else if (d == 16) 00370 *pformat = IFF_PNG; 00371 else if (d >= 8 && !cmapflag) 00372 *pformat = IFF_JFIF_JPEG; 00373 } 00374 else if (comptype == IFF_TIFF_G4 && d == 1) 00375 *pformat = IFF_TIFF_G4; 00376 else if (comptype == IFF_JFIF_JPEG && d >= 8 && !cmapflag) 00377 *pformat = IFF_JFIF_JPEG; 00378 00379 return 0; 00380 } 00381 00382 00383 /*---------------------------------------------------------------------* 00384 * Pixcomp conversion to Pix * 00385 *---------------------------------------------------------------------*/ 00386 /*! 00387 * pixCreateFromPixcomp() 00388 * 00389 * Input: pixc 00390 * Return: pix, or null on error 00391 */ 00392 PIX * 00393 pixCreateFromPixcomp(PIXC *pixc) 00394 { 00395 l_int32 w, h, d, cmapinpix, format; 00396 PIX *pix; 00397 00398 PROCNAME("pixCreateFromPixcomp"); 00399 00400 if (!pixc) 00401 return (PIX *)ERROR_PTR("pixc not defined", procName, NULL); 00402 00403 if ((pix = pixReadMem(pixc->data, pixc->size)) == NULL) 00404 return (PIX *)ERROR_PTR("pix not read", procName, NULL); 00405 pixSetResolution(pix, pixc->xres, pixc->yres); 00406 if (pixc->text) 00407 pixSetText(pix, pixc->text); 00408 00409 /* Check fields for consistency */ 00410 pixGetDimensions(pix, &w, &h, &d); 00411 if (pixc->w != w) { 00412 L_INFO_INT2("pix width %d != pixc width %d", procName, w, pixc->w); 00413 L_ERROR_INT("pix width %d != pixc width", procName, w); 00414 } 00415 if (pixc->h != h) 00416 L_ERROR_INT("pix height %d != pixc height", procName, h); 00417 if (pixc->d != d) { 00418 if (pixc->d == 16) /* we strip 16 --> 8 bpp by default */ 00419 L_WARNING_INT("pix depth %d != pixc depth 16", procName, d); 00420 else 00421 L_ERROR_INT("pix depth %d != pixc depth", procName, d); 00422 } 00423 cmapinpix = (pixGetColormap(pix) != NULL); 00424 if ((cmapinpix && !pixc->cmapflag) || (!cmapinpix && pixc->cmapflag)) 00425 L_ERROR("pix cmap flag inconsistent", procName); 00426 format = pixGetInputFormat(pix); 00427 if (format != pixc->comptype) { 00428 L_ERROR_INT("pix comptype %d not equal to pixc comptype", 00429 procName, format); 00430 } 00431 00432 return pix; 00433 } 00434 00435 00436 00437 /*---------------------------------------------------------------------* 00438 * Pixacomp creation and destruction * 00439 *---------------------------------------------------------------------*/ 00440 /*! 00441 * pixacompCreate() 00442 * 00443 * Input: n (initial number of ptrs) 00444 * Return: pixac, or null on error 00445 */ 00446 PIXAC * 00447 pixacompCreate(l_int32 n) 00448 { 00449 PIXAC *pixac; 00450 00451 PROCNAME("pixacompCreate"); 00452 00453 if (n <= 0) 00454 n = INITIAL_PTR_ARRAYSIZE; 00455 00456 if ((pixac = (PIXAC *)CALLOC(1, sizeof(PIXAC))) == NULL) 00457 return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL); 00458 pixac->n = 0; 00459 pixac->nalloc = n; 00460 00461 if ((pixac->pixc = (PIXC **)CALLOC(n, sizeof(PIXC *))) == NULL) 00462 return (PIXAC *)ERROR_PTR("pixc ptrs not made", procName, NULL); 00463 if ((pixac->boxa = boxaCreate(n)) == NULL) 00464 return (PIXAC *)ERROR_PTR("boxa not made", procName, NULL); 00465 00466 return pixac; 00467 } 00468 00469 00470 /*! 00471 * pixacompCreateInitialized() 00472 * 00473 * Input: n (initial number of ptrs) 00474 * pix (initialize each ptr in pixacomp to this pix) 00475 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00476 * Return: pixac, or null on error 00477 * 00478 * Notes: 00479 * (1) Initializes a pixacomp to be fully populated with @pix. 00480 * (2) Typically use a very small @pix (w = h = 1) with 00481 * @comptype == IFF_TIFF_G4 for the initialization. 00482 * (3) Example usage: 00483 * Pix *pix = pixCreate(1, 1, 1); 00484 * Pixacomp *pixac = pixacompCreateInitialized(50, pix, IFF_TIFF_G4); 00485 * for (i = 0; i < 50; i++) { 00486 * Pix *pixt = ... 00487 * if (pixt) 00488 * pixacompReplacePix(pixac, i, pixt, IFF_TIFF_G4); 00489 * pixDestroy(&pixt); 00490 * } 00491 * The result is a fully populated pixac with selected pixt 00492 * replacing the placeholders. 00493 */ 00494 PIXAC * 00495 pixacompCreateInitialized(l_int32 n, 00496 PIX *pix, 00497 l_int32 comptype) 00498 { 00499 l_int32 i; 00500 PIXC *pixc; 00501 PIXAC *pixac; 00502 00503 PROCNAME("pixacompCreateInitialized"); 00504 00505 if (n <= 0) 00506 return (PIXAC *)ERROR_PTR("n must be > 0", procName, NULL); 00507 if (!pix) 00508 return (PIXAC *)ERROR_PTR("pix not defined", procName, NULL); 00509 00510 if ((pixac = pixacompCreate(n)) == NULL) 00511 return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL); 00512 for (i = 0; i < n; i++) { 00513 pixc = pixcompCreateFromPix(pix, comptype); 00514 pixacompAddPixcomp(pixac, pixc); 00515 } 00516 00517 return pixac; 00518 } 00519 00520 00521 /*! 00522 * pixacompCreateFromPixa() 00523 * 00524 * Input: pixa 00525 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00526 * accesstype (L_COPY, L_CLONE, L_COPY_CLONE; for boxa) 00527 * Return: 0 if OK, 1 on error 00528 * 00529 * Notes: 00530 * (1) If @format == IFF_DEFAULT, the conversion format for each 00531 * image is chosen automatically. Otherwise, we use the 00532 * specified format unless it can't be done (e.g., jpeg 00533 * for a 1, 2 or 4 bpp pix, or a pix with a colormap), 00534 * in which case we use the default (assumed best) compression. 00535 */ 00536 PIXAC * 00537 pixacompCreateFromPixa(PIXA *pixa, 00538 l_int32 comptype, 00539 l_int32 accesstype) 00540 { 00541 l_int32 i, n; 00542 BOXA *boxa; 00543 PIX *pix; 00544 PIXAC *pixac; 00545 00546 PROCNAME("pixacompCreateFromPixa"); 00547 00548 if (!pixa) 00549 return (PIXAC *)ERROR_PTR("pixa not defined", procName, NULL); 00550 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00551 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00552 return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL); 00553 if (accesstype != L_COPY && accesstype != L_CLONE && 00554 accesstype != L_COPY_CLONE) 00555 return (PIXAC *)ERROR_PTR("invalid accesstype", procName, NULL); 00556 00557 n = pixaGetCount(pixa); 00558 if ((pixac = pixacompCreate(n)) == NULL) 00559 return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL); 00560 for (i = 0; i < n; i++) { 00561 pix = pixaGetPix(pixa, i, L_CLONE); 00562 pixacompAddPix(pixac, pix, comptype); 00563 pixDestroy(&pix); 00564 } 00565 if ((boxa = pixaGetBoxa(pixa, accesstype)) != NULL) { 00566 if (pixac->boxa) { 00567 boxaDestroy(&pixac->boxa); 00568 pixac->boxa = boxa; 00569 } 00570 } 00571 00572 return pixac; 00573 } 00574 00575 00576 /*! 00577 * pixacompCreateFromFiles() 00578 * 00579 * Input: dirname 00580 * substr (<optional> substring filter on filenames; can be null) 00581 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00582 * Return: pixac, or null on error 00583 * 00584 * Notes: 00585 * (1) @dirname is the full path for the directory. 00586 * (2) @substr is the part of the file name (excluding 00587 * the directory) that is to be matched. All matching 00588 * filenames are read into the Pixa. If substr is NULL, 00589 * all filenames are read into the Pixa. 00590 * (3) Use @comptype == IFF_DEFAULT to have the compression 00591 * type automatically determined for each file. 00592 * (4) If the comptype is invalid for a file, the default will 00593 * be substituted. 00594 */ 00595 PIXAC * 00596 pixacompCreateFromFiles(const char *dirname, 00597 const char *substr, 00598 l_int32 comptype) 00599 { 00600 PIXAC *pixac; 00601 SARRAY *sa; 00602 00603 PROCNAME("pixacompCreateFromFiles"); 00604 00605 if (!dirname) 00606 return (PIXAC *)ERROR_PTR("dirname not defined", procName, NULL); 00607 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00608 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00609 return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL); 00610 00611 if ((sa = getSortedPathnamesInDirectory(dirname, substr, 0, 0)) == NULL) 00612 return (PIXAC *)ERROR_PTR("sa not made", procName, NULL); 00613 pixac = pixacompCreateFromSA(sa, comptype); 00614 sarrayDestroy(&sa); 00615 return pixac; 00616 } 00617 00618 00619 /*! 00620 * pixacompCreateFromSA() 00621 * 00622 * Input: sarray (full pathnames for all files) 00623 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00624 * Return: pixac, or null on error 00625 * 00626 * Notes: 00627 * (1) Use @comptype == IFF_DEFAULT to have the compression 00628 * type automatically determined for each file. 00629 * (2) If the comptype is invalid for a file, the default will 00630 * be substituted. 00631 */ 00632 PIXAC * 00633 pixacompCreateFromSA(SARRAY *sa, 00634 l_int32 comptype) 00635 { 00636 char *str; 00637 l_int32 i, n; 00638 PIXC *pixc; 00639 PIXAC *pixac; 00640 00641 PROCNAME("pixacompCreateFromSA"); 00642 00643 if (!sa) 00644 return (PIXAC *)ERROR_PTR("sarray not defined", procName, NULL); 00645 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00646 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00647 return (PIXAC *)ERROR_PTR("invalid comptype", procName, NULL); 00648 00649 n = sarrayGetCount(sa); 00650 pixac = pixacompCreate(n); 00651 for (i = 0; i < n; i++) { 00652 str = sarrayGetString(sa, i, L_NOCOPY); 00653 if ((pixc = pixcompCreateFromFile(str, comptype)) == NULL) { 00654 L_WARNING_STRING("pixc not read from file %s", procName, str); 00655 continue; 00656 } 00657 pixacompAddPixcomp(pixac, pixc); 00658 } 00659 return pixac; 00660 } 00661 00662 00663 /*! 00664 * pixacompDestroy() 00665 * 00666 * Input: &pixac (<to be nulled>) 00667 * Return: void 00668 * 00669 * Notes: 00670 * (1) Always nulls the input ptr. 00671 */ 00672 void 00673 pixacompDestroy(PIXAC **ppixac) 00674 { 00675 l_int32 i; 00676 PIXAC *pixac; 00677 00678 PROCNAME("pixacompDestroy"); 00679 00680 if (ppixac == NULL) { 00681 L_WARNING("ptr address is NULL!", procName); 00682 return; 00683 } 00684 00685 if ((pixac = *ppixac) == NULL) 00686 return; 00687 00688 for (i = 0; i < pixac->n; i++) 00689 pixcompDestroy(&pixac->pixc[i]); 00690 FREE(pixac->pixc); 00691 boxaDestroy(&pixac->boxa); 00692 FREE(pixac); 00693 00694 *ppixac = NULL; 00695 return; 00696 } 00697 00698 00699 /*---------------------------------------------------------------------* 00700 * Pixacomp addition * 00701 *---------------------------------------------------------------------*/ 00702 /*! 00703 * pixacompAddPix() 00704 * 00705 * Input: pixac 00706 * pix (to be added) 00707 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00708 * Return: 0 if OK; 1 on error 00709 */ 00710 l_int32 00711 pixacompAddPix(PIXAC *pixac, 00712 PIX *pix, 00713 l_int32 comptype) 00714 { 00715 l_int32 cmapflag, format; 00716 PIXC *pixc; 00717 00718 PROCNAME("pixacompAddPix"); 00719 00720 if (!pixac) 00721 return ERROR_INT("pixac not defined", procName, 1); 00722 if (!pix) 00723 return ERROR_INT("pix not defined", procName, 1); 00724 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00725 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00726 return ERROR_INT("invalid format", procName, 1); 00727 00728 cmapflag = pixGetColormap(pix) ? 1 : 0; 00729 pixcompDetermineFormat(comptype, pixGetDepth(pix), cmapflag, &format); 00730 if ((pixc = pixcompCreateFromPix(pix, format)) == NULL) 00731 return ERROR_INT("pixc not made", procName, 1); 00732 pixacompAddPixcomp(pixac, pixc); 00733 return 0; 00734 } 00735 00736 00737 /*! 00738 * pixacompAddPixcomp() 00739 * 00740 * Input: pixac 00741 * pixc (to be added by insertion) 00742 * Return: 0 if OK; 1 on error 00743 */ 00744 l_int32 00745 pixacompAddPixcomp(PIXAC *pixac, 00746 PIXC *pixc) 00747 { 00748 l_int32 n; 00749 00750 PROCNAME("pixacompAddPixcomp"); 00751 00752 if (!pixac) 00753 return ERROR_INT("pixac not defined", procName, 1); 00754 if (!pixc) 00755 return ERROR_INT("pixc not defined", procName, 1); 00756 00757 n = pixac->n; 00758 if (n >= pixac->nalloc) 00759 pixacompExtendArray(pixac); 00760 pixac->pixc[n] = pixc; 00761 pixac->n++; 00762 00763 return 0; 00764 } 00765 00766 00767 /*! 00768 * pixacompExtendArray() 00769 * 00770 * Input: pixac 00771 * Return: 0 if OK; 1 on error 00772 * 00773 * Notes: 00774 * (1) We extend the boxa array simultaneously. This is 00775 * necessary in case we are NOT adding boxes simultaneously 00776 * with adding pixc. We always want the sizes of the 00777 * pixac and boxa ptr arrays to be equal. 00778 */ 00779 l_int32 00780 pixacompExtendArray(PIXAC *pixac) 00781 { 00782 PROCNAME("pixacompExtendArray"); 00783 00784 if (!pixac) 00785 return ERROR_INT("pixac not defined", procName, 1); 00786 00787 if ((pixac->pixc = (PIXC **)reallocNew((void **)&pixac->pixc, 00788 sizeof(PIXC *) * pixac->nalloc, 00789 2 * sizeof(PIXC *) * pixac->nalloc)) == NULL) 00790 return ERROR_INT("new ptr array not returned", procName, 1); 00791 pixac->nalloc = 2 * pixac->nalloc; 00792 boxaExtendArray(pixac->boxa); 00793 return 0; 00794 } 00795 00796 00797 /*! 00798 * pixacompReplacePix() 00799 * 00800 * Input: pixac 00801 * index (of pixc within pixac to be replaced) 00802 * pix (owned by the caller) 00803 * comptype (IFF_DEFAULT, IFF_TIFF_G4, IFF_PNG, IFF_JFIF_JPEG) 00804 * Return: 0 if OK; 1 on error 00805 * 00806 * Notes: 00807 * (1) The input @pix is converted to a pixc, which is then inserted 00808 * into the pixac. 00809 */ 00810 l_int32 00811 pixacompReplacePix(PIXAC *pixac, 00812 l_int32 index, 00813 PIX *pix, 00814 l_int32 comptype) 00815 { 00816 l_int32 n; 00817 PIXC *pixc; 00818 00819 PROCNAME("pixacompReplacePix"); 00820 00821 if (!pixac) 00822 return ERROR_INT("pixac not defined", procName, 1); 00823 n = pixacompGetCount(pixac); 00824 if (index < 0 || index >= n) 00825 return ERROR_INT("array index out of bounds", procName, 1); 00826 if (!pix) 00827 return ERROR_INT("pix not defined", procName, 1); 00828 if (comptype != IFF_DEFAULT && comptype != IFF_TIFF_G4 && 00829 comptype != IFF_PNG && comptype != IFF_JFIF_JPEG) 00830 return ERROR_INT("invalid format", procName, 1); 00831 00832 pixc = pixcompCreateFromPix(pix, comptype); 00833 pixacompReplacePixcomp(pixac, index, pixc); 00834 return 0; 00835 } 00836 00837 00838 /*! 00839 * pixacompReplacePixcomp() 00840 * 00841 * Input: pixac 00842 * index (of pixc within pixac to be replaced) 00843 * pixc (to replace existing one, which is destroyed) 00844 * Return: 0 if OK; 1 on error 00845 * 00846 * Notes: 00847 * (1) The inserted @pixc is now owned by the pixac. The caller 00848 * must not destroy it. 00849 */ 00850 l_int32 00851 pixacompReplacePixcomp(PIXAC *pixac, 00852 l_int32 index, 00853 PIXC *pixc) 00854 { 00855 l_int32 n; 00856 PIXC *pixct; 00857 00858 PROCNAME("pixacompReplacePixcomp"); 00859 00860 if (!pixac) 00861 return ERROR_INT("pixac not defined", procName, 1); 00862 n = pixacompGetCount(pixac); 00863 if (index < 0 || index >= n) 00864 return ERROR_INT("array index out of bounds", procName, 1); 00865 if (!pixc) 00866 return ERROR_INT("pixc not defined", procName, 1); 00867 00868 pixct = pixacompGetPixcomp(pixac, index); 00869 pixcompDestroy(&pixct); 00870 pixac->pixc[index] = pixc; /* replace */ 00871 00872 return 0; 00873 } 00874 00875 00876 /*! 00877 * pixacompAddBox() 00878 * 00879 * Input: pixac 00880 * box 00881 * copyflag (L_INSERT, L_COPY) 00882 * Return: 0 if OK, 1 on error 00883 */ 00884 l_int32 00885 pixacompAddBox(PIXAC *pixac, 00886 BOX *box, 00887 l_int32 copyflag) 00888 { 00889 PROCNAME("pixacompAddBox"); 00890 00891 if (!pixac) 00892 return ERROR_INT("pixac not defined", procName, 1); 00893 if (!box) 00894 return ERROR_INT("box not defined", procName, 1); 00895 if (copyflag != L_INSERT && copyflag != L_COPY) 00896 return ERROR_INT("invalid copyflag", procName, 1); 00897 00898 boxaAddBox(pixac->boxa, box, copyflag); 00899 return 0; 00900 } 00901 00902 00903 /*---------------------------------------------------------------------* 00904 * Pixacomp accessors * 00905 *---------------------------------------------------------------------*/ 00906 /*! 00907 * pixacompGetCount() 00908 * 00909 * Input: pixac 00910 * Return: count, or 0 if no pixa 00911 */ 00912 l_int32 00913 pixacompGetCount(PIXAC *pixac) 00914 { 00915 PROCNAME("pixacompGetCount"); 00916 00917 if (!pixac) 00918 return ERROR_INT("pixac not defined", procName, 0); 00919 00920 return pixac->n; 00921 } 00922 00923 00924 /*! 00925 * pixacompGetPixcomp() 00926 * 00927 * Input: pixac 00928 * index (to the index-th pix) 00929 * Return: pixc, or null on error 00930 * 00931 * Notes: 00932 * (1) Important: this is just a ptr to the pixc owned by the pixac. 00933 * Do not destroy unless you are replacing the pixc. 00934 */ 00935 PIXC * 00936 pixacompGetPixcomp(PIXAC *pixac, 00937 l_int32 index) 00938 { 00939 PROCNAME("pixacompGetPixcomp"); 00940 00941 if (!pixac) 00942 return (PIXC *)ERROR_PTR("pixac not defined", procName, NULL); 00943 if (index < 0 || index >= pixac->n) 00944 return (PIXC *)ERROR_PTR("index not valid", procName, NULL); 00945 00946 return pixac->pixc[index]; 00947 } 00948 00949 00950 /*! 00951 * pixacompGetPix() 00952 * 00953 * Input: pixac 00954 * index (to the index-th pix) 00955 * Return: pix, or null on error 00956 */ 00957 PIX * 00958 pixacompGetPix(PIXAC *pixac, 00959 l_int32 index) 00960 { 00961 PIXC *pixc; 00962 00963 PROCNAME("pixacompGetPix"); 00964 00965 if (!pixac) 00966 return (PIX *)ERROR_PTR("pixac not defined", procName, NULL); 00967 if (index < 0 || index >= pixac->n) 00968 return (PIX *)ERROR_PTR("index not valid", procName, NULL); 00969 00970 pixc = pixacompGetPixcomp(pixac, index); 00971 return pixCreateFromPixcomp(pixc); 00972 } 00973 00974 00975 /*! 00976 * pixacompGetPixDimensions() 00977 * 00978 * Input: pixa 00979 * index (to the index-th box) 00980 * &w, &h, &d (<optional return>; each can be null) 00981 * Return: 0 if OK, 1 on error 00982 */ 00983 l_int32 00984 pixacompGetPixDimensions(PIXAC *pixac, 00985 l_int32 index, 00986 l_int32 *pw, 00987 l_int32 *ph, 00988 l_int32 *pd) 00989 { 00990 PIXC *pixc; 00991 00992 PROCNAME("pixacompGetPixDimensions"); 00993 00994 if (!pixac) 00995 return ERROR_INT("pixac not defined", procName, 1); 00996 if (index < 0 || index >= pixac->n) 00997 return ERROR_INT("index not valid", procName, 1); 00998 00999 if ((pixc = pixac->pixc[index]) == NULL) 01000 return ERROR_INT("pixc not found!", procName, 1); 01001 pixcompGetDimensions(pixc, pw, ph, pd); 01002 return 0; 01003 } 01004 01005 01006 /*! 01007 * pixacompGetBoxa() 01008 * 01009 * Input: pixac 01010 * accesstype (L_COPY, L_CLONE, L_COPY_CLONE) 01011 * Return: boxa, or null on error 01012 */ 01013 BOXA * 01014 pixacompGetBoxa(PIXAC *pixac, 01015 l_int32 accesstype) 01016 { 01017 PROCNAME("pixacompGetBoxa"); 01018 01019 if (!pixac) 01020 return (BOXA *)ERROR_PTR("pixac not defined", procName, NULL); 01021 if (!pixac->boxa) 01022 return (BOXA *)ERROR_PTR("boxa not defined", procName, NULL); 01023 if (accesstype != L_COPY && accesstype != L_CLONE && 01024 accesstype != L_COPY_CLONE) 01025 return (BOXA *)ERROR_PTR("invalid accesstype", procName, NULL); 01026 01027 return boxaCopy(pixac->boxa, accesstype); 01028 } 01029 01030 01031 /*! 01032 * pixacompGetBoxaCount() 01033 * 01034 * Input: pixac 01035 * Return: count, or 0 on error 01036 */ 01037 l_int32 01038 pixacompGetBoxaCount(PIXAC *pixac) 01039 { 01040 PROCNAME("pixacompGetBoxaCount"); 01041 01042 if (!pixac) 01043 return ERROR_INT("pixac not defined", procName, 0); 01044 01045 return boxaGetCount(pixac->boxa); 01046 } 01047 01048 01049 /*! 01050 * pixacompGetBox() 01051 * 01052 * Input: pixac 01053 * index (to the index-th pix) 01054 * accesstype (L_COPY or L_CLONE) 01055 * Return: box (if null, not automatically an error), or null on error 01056 * 01057 * Notes: 01058 * (1) There is always a boxa with a pixac, and it is initialized so 01059 * that each box ptr is NULL. 01060 * (2) In general, we expect that there is either a box associated 01061 * with each pixc, or no boxes at all in the boxa. 01062 * (3) Having no boxes is thus not an automatic error. Whether it 01063 * is an actual error is determined by the calling program. 01064 * If the caller expects to get a box, it is an error; see, e.g., 01065 * pixacGetBoxGeometry(). 01066 */ 01067 BOX * 01068 pixacompGetBox(PIXAC *pixac, 01069 l_int32 index, 01070 l_int32 accesstype) 01071 { 01072 BOX *box; 01073 01074 PROCNAME("pixacompGetBox"); 01075 01076 if (!pixac) 01077 return (BOX *)ERROR_PTR("pixac not defined", procName, NULL); 01078 if (!pixac->boxa) 01079 return (BOX *)ERROR_PTR("boxa not defined", procName, NULL); 01080 if (index < 0 || index >= pixac->boxa->n) 01081 return (BOX *)ERROR_PTR("index not valid", procName, NULL); 01082 if (accesstype != L_COPY && accesstype != L_CLONE) 01083 return (BOX *)ERROR_PTR("invalid accesstype", procName, NULL); 01084 01085 box = pixac->boxa->box[index]; 01086 if (box) { 01087 if (accesstype == L_COPY) 01088 return boxCopy(box); 01089 else /* accesstype == L_CLONE */ 01090 return boxClone(box); 01091 } 01092 else 01093 return NULL; 01094 } 01095 01096 01097 /*! 01098 * pixacompGetBoxGeometry() 01099 * 01100 * Input: pixac 01101 * index (to the index-th box) 01102 * &x, &y, &w, &h (<optional return>; each can be null) 01103 * Return: 0 if OK, 1 on error 01104 */ 01105 l_int32 01106 pixacompGetBoxGeometry(PIXAC *pixac, 01107 l_int32 index, 01108 l_int32 *px, 01109 l_int32 *py, 01110 l_int32 *pw, 01111 l_int32 *ph) 01112 { 01113 BOX *box; 01114 01115 PROCNAME("pixacompGetBoxGeometry"); 01116 01117 if (!pixac) 01118 return ERROR_INT("pixac not defined", procName, 1); 01119 if (index < 0 || index >= pixac->n) 01120 return ERROR_INT("index not valid", procName, 1); 01121 01122 if ((box = pixacompGetBox(pixac, index, L_CLONE)) == NULL) 01123 return ERROR_INT("box not found!", procName, 1); 01124 boxGetGeometry(box, px, py, pw, ph); 01125 boxDestroy(&box); 01126 return 0; 01127 } 01128 01129 01130 /*---------------------------------------------------------------------* 01131 * Pixacomp conversion to Pixa * 01132 *---------------------------------------------------------------------*/ 01133 /*! 01134 * pixaCreateFromPixacomp() 01135 * 01136 * Input: pixac 01137 * accesstype (L_COPY, L_CLONE, L_COPY_CLONE; for boxa) 01138 * Return: pixa if OK, or null on error 01139 */ 01140 PIXA * 01141 pixaCreateFromPixacomp(PIXAC *pixac, 01142 l_int32 accesstype) 01143 { 01144 l_int32 i, n; 01145 PIX *pix; 01146 PIXA *pixa; 01147 01148 PROCNAME("pixaCreateFromPixacomp"); 01149 01150 if (!pixac) 01151 return (PIXA *)ERROR_PTR("pixac not defined", procName, NULL); 01152 if (accesstype != L_COPY && accesstype != L_CLONE && 01153 accesstype != L_COPY_CLONE) 01154 return (PIXA *)ERROR_PTR("invalid accesstype", procName, NULL); 01155 01156 n = pixacompGetCount(pixac); 01157 if ((pixa = pixaCreate(n)) == NULL) 01158 return (PIXA *)ERROR_PTR("pixa not made", procName, NULL); 01159 for (i = 0; i < n; i++) { 01160 if ((pix = pixacompGetPix(pixac, i)) == NULL) { 01161 L_WARNING_INT("pix %d not made", procName, i); 01162 continue; 01163 } 01164 pixaAddPix(pixa, pix, L_INSERT); 01165 } 01166 if (pixa->boxa) { 01167 boxaDestroy(&pixa->boxa); 01168 pixa->boxa = pixacompGetBoxa(pixac, accesstype); 01169 } 01170 01171 return pixa; 01172 } 01173 01174 01175 /*---------------------------------------------------------------------* 01176 * Pixacomp serialized I/O * 01177 *---------------------------------------------------------------------*/ 01178 /*! 01179 * pixacompRead() 01180 * 01181 * Input: filename 01182 * Return: pixac, or null on error 01183 * 01184 * Notes: 01185 * (1) Unlike the situation with serialized Pixa, where the image 01186 * data is stored in png format, the Pixacomp image data 01187 * can be stored in tiffg4, png and jpg formats. 01188 */ 01189 PIXAC * 01190 pixacompRead(const char *filename) 01191 { 01192 FILE *fp; 01193 PIXAC *pixac; 01194 01195 PROCNAME("pixacompRead"); 01196 01197 if (!filename) 01198 return (PIXAC *)ERROR_PTR("filename not defined", procName, NULL); 01199 if ((fp = fopenReadStream(filename)) == NULL) 01200 return (PIXAC *)ERROR_PTR("stream not opened", procName, NULL); 01201 01202 if ((pixac = pixacompReadStream(fp)) == NULL) { 01203 fclose(fp); 01204 return (PIXAC *)ERROR_PTR("pixac not read", procName, NULL); 01205 } 01206 01207 fclose(fp); 01208 return pixac; 01209 } 01210 01211 01212 /*! 01213 * pixacompReadStream() 01214 * 01215 * Input: stream 01216 * Return: pixac, or null on error 01217 */ 01218 PIXAC * 01219 pixacompReadStream(FILE *fp) 01220 { 01221 l_uint8 *data; 01222 l_int32 n, i, w, h, d, ignore; 01223 l_int32 comptype, size, cmapflag, version, xres, yres; 01224 BOXA *boxa; 01225 PIXC *pixc; 01226 PIXAC *pixac; 01227 01228 PROCNAME("pixacompReadStream"); 01229 01230 if (!fp) 01231 return (PIXAC *)ERROR_PTR("stream not defined", procName, NULL); 01232 01233 if (fscanf(fp, "\nPixacomp Version %d\n", &version) != 1) 01234 return (PIXAC *)ERROR_PTR("not a pixacomp file", procName, NULL); 01235 if (version != PIXACOMP_VERSION_NUMBER) 01236 return (PIXAC *)ERROR_PTR("invalid pixacomp version", procName, NULL); 01237 if (fscanf(fp, "Number of pixcomp = %d", &n) != 1) 01238 return (PIXAC *)ERROR_PTR("not a pixacomp file", procName, NULL); 01239 01240 if ((pixac = pixacompCreate(n)) == NULL) 01241 return (PIXAC *)ERROR_PTR("pixac not made", procName, NULL); 01242 if ((boxa = boxaReadStream(fp)) == NULL) 01243 return (PIXAC *)ERROR_PTR("boxa not made", procName, NULL); 01244 boxaDestroy(&pixac->boxa); /* empty */ 01245 pixac->boxa = boxa; 01246 01247 for (i = 0; i < n; i++) { 01248 if ((pixc = (PIXC *)CALLOC(1, sizeof(PIXC))) == NULL) 01249 return (PIXAC *)ERROR_PTR("pixc not made", procName, NULL); 01250 if (fscanf(fp, " Pixcomp[%d]: w = %d, h = %d, d = %d\n", 01251 &ignore, &w, &h, &d) != 4) 01252 return (PIXAC *)ERROR_PTR("size reading", procName, NULL); 01253 if (fscanf(fp, " comptype = %d, size = %d, cmapflag = %d\n", 01254 &comptype, &size, &cmapflag) != 3) 01255 return (PIXAC *)ERROR_PTR("comptype/size reading", procName, NULL); 01256 if (fscanf(fp, " xres = %d, yres = %d\n", &xres, &yres) != 2) 01257 return (PIXAC *)ERROR_PTR("res reading", procName, NULL); 01258 if ((data = (l_uint8 *)CALLOC(1, size)) == NULL) 01259 return (PIXAC *)ERROR_PTR("calloc fail for data", procName, NULL); 01260 if (fread(data, 1, size, fp) != size) 01261 return (PIXAC *)ERROR_PTR("error reading data", procName, NULL); 01262 pixc->w = w; 01263 pixc->h = h; 01264 pixc->d = d; 01265 pixc->xres = xres; 01266 pixc->yres = yres; 01267 pixc->comptype = comptype; 01268 pixc->cmapflag = cmapflag; 01269 pixc->data = data; 01270 pixc->size = size; 01271 pixacompAddPixcomp(pixac, pixc); 01272 } 01273 return pixac; 01274 } 01275 01276 01277 /*! 01278 * pixacompWrite() 01279 * 01280 * Input: filename 01281 * pixac 01282 * Return: 0 if OK, 1 on error 01283 * 01284 * Notes: 01285 * (1) Unlike the situation with serialized Pixa, where the image 01286 * data is stored in png format, the Pixacomp image data 01287 * can be stored in tiffg4, png and jpg formats. 01288 */ 01289 l_int32 01290 pixacompWrite(const char *filename, 01291 PIXAC *pixac) 01292 { 01293 FILE *fp; 01294 01295 PROCNAME("pixacompWrite"); 01296 01297 if (!filename) 01298 return ERROR_INT("filename not defined", procName, 1); 01299 if (!pixac) 01300 return ERROR_INT("pixacomp not defined", procName, 1); 01301 01302 if ((fp = fopenWriteStream(filename, "wb")) == NULL) 01303 return ERROR_INT("stream not opened", procName, 1); 01304 if (pixacompWriteStream(fp, pixac)) 01305 return ERROR_INT("pixacomp not written to stream", procName, 1); 01306 fclose(fp); 01307 return 0; 01308 } 01309 01310 01311 /*! 01312 * pixacompWriteStream() 01313 * 01314 * Input: stream 01315 * pixac 01316 * Return: 0 if OK, 1 on error 01317 */ 01318 l_int32 01319 pixacompWriteStream(FILE *fp, 01320 PIXAC *pixac) 01321 { 01322 l_int32 n, i; 01323 PIXC *pixc; 01324 01325 PROCNAME("pixacompWriteStream"); 01326 01327 if (!fp) 01328 return ERROR_INT("stream not defined", procName, 1); 01329 if (!pixac) 01330 return ERROR_INT("pixac not defined", procName, 1); 01331 01332 n = pixacompGetCount(pixac); 01333 fprintf(fp, "\nPixacomp Version %d\n", PIXACOMP_VERSION_NUMBER); 01334 fprintf(fp, "Number of pixcomp = %d", n); 01335 boxaWriteStream(fp, pixac->boxa); 01336 for (i = 0; i < n; i++) { 01337 if ((pixc = pixacompGetPixcomp(pixac, i)) == NULL) 01338 return ERROR_INT("pixc not found", procName, 1); 01339 fprintf(fp, " Pixcomp[%d]: w = %d, h = %d, d = %d\n", 01340 i, pixc->w, pixc->h, pixc->d); 01341 fprintf(fp, " comptype = %d, size = %ld, cmapflag = %d\n", 01342 pixc->comptype, pixc->size, pixc->cmapflag); 01343 fprintf(fp, " xres = %d, yres = %d\n", pixc->xres, pixc->yres); 01344 fwrite(pixc->data, 1, pixc->size, fp); 01345 } 01346 return 0; 01347 } 01348 01349 01350 /*--------------------------------------------------------------------* 01351 * Output for debugging * 01352 *--------------------------------------------------------------------*/ 01353 /*! 01354 * pixacompWriteStreamInfo() 01355 * 01356 * Input: fp (file stream) 01357 * pixac 01358 * text (<optional> identifying string; can be null) 01359 * Return: 0 if OK, 1 on error 01360 */ 01361 l_int32 01362 pixacompWriteStreamInfo(FILE *fp, 01363 PIXAC *pixac, 01364 const char *text) 01365 { 01366 l_int32 i, n, nboxes; 01367 PIXC *pixc; 01368 01369 PROCNAME("pixacompWriteStreamInfo"); 01370 01371 if (!fp) 01372 return ERROR_INT("fp not defined", procName, 1); 01373 if (!pixac) 01374 return ERROR_INT("pixac not defined", procName, 1); 01375 01376 if (text) 01377 fprintf(fp, "Pixacomp Info for %s:\n", text); 01378 else 01379 fprintf(fp, "Pixacomp Info:\n"); 01380 n = pixacompGetCount(pixac); 01381 nboxes = pixacompGetBoxaCount(pixac); 01382 fprintf(fp, "Number of pixcomp: %d\n", n); 01383 fprintf(fp, "Size of pixcomp array alloc: %d\n", pixac->nalloc); 01384 if (nboxes > 0) 01385 fprintf(fp, "Boxa has %d boxes\n", nboxes); 01386 else 01387 fprintf(fp, "Boxa is empty\n"); 01388 for (i = 0; i < n; i++) { 01389 pixc = pixacompGetPixcomp(pixac, i); 01390 pixcompWriteStreamInfo(fp, pixc, NULL); 01391 } 01392 return 0; 01393 } 01394 01395 01396 /*! 01397 * pixcompWriteStreamInfo() 01398 * 01399 * Input: fp (file stream) 01400 * pixc 01401 * text (<optional> identifying string; can be null) 01402 * Return: 0 if OK, 1 on error 01403 */ 01404 l_int32 01405 pixcompWriteStreamInfo(FILE *fp, 01406 PIXC *pixc, 01407 const char *text) 01408 { 01409 PROCNAME("pixcompWriteStreamInfo"); 01410 01411 if (!fp) 01412 return ERROR_INT("fp not defined", procName, 1); 01413 if (!pixc) 01414 return ERROR_INT("pixc not defined", procName, 1); 01415 01416 if (text) 01417 fprintf(fp, " Pixcomp Info for %s:", text); 01418 else 01419 fprintf(fp, " Pixcomp Info:"); 01420 fprintf(fp, " width = %d, height = %d, depth = %d\n", 01421 pixc->w, pixc->h, pixc->d); 01422 fprintf(fp, " xres = %d, yres = %d, size in bytes = %ld\n", 01423 pixc->xres, pixc->yres, pixc->size); 01424 if (pixc->cmapflag) 01425 fprintf(fp, " has colormap\n"); 01426 else 01427 fprintf(fp, " no colormap\n"); 01428 if (pixc->comptype < NumImageFileFormatExtensions) 01429 fprintf(fp, " comptype = %s (%d)\n", 01430 ImageFileFormatExtensions[pixc->comptype], pixc->comptype); 01431 else 01432 fprintf(fp, " Error!! Invalid comptype index: %d\n", pixc->comptype); 01433 return 0; 01434 } 01435 01436 01437 /*! 01438 * pixacompDisplayTiledAndScaled() 01439 * 01440 * Input: pixac 01441 * outdepth (output depth: 1, 8 or 32 bpp) 01442 * tilewidth (each pix is scaled to this width) 01443 * ncols (number of tiles in each row) 01444 * background (0 for white, 1 for black; this is the color 01445 * of the spacing between the images) 01446 * spacing (between images, and on outside) 01447 * border (width of additional black border on each image; 01448 * use 0 for no border) 01449 * Return: pix of tiled images, or null on error 01450 * 01451 * Notes: 01452 * (1) This is the same function as pixaDisplayTiledAndScaled(), 01453 * except it works on a Pixacomp instead of a Pix. It is particularly 01454 * useful for showing the images in a Pixacomp at reduced resolution. 01455 * (2) This can be used to tile a number of renderings of 01456 * an image that are at different scales and depths. 01457 * (3) Each image, after scaling and optionally adding the 01458 * black border, has width 'tilewidth'. Thus, the border does 01459 * not affect the spacing between the image tiles. The 01460 * maximum allowed border width is tilewidth / 5. 01461 */ 01462 PIX * 01463 pixacompDisplayTiledAndScaled(PIXAC *pixac, 01464 l_int32 outdepth, 01465 l_int32 tilewidth, 01466 l_int32 ncols, 01467 l_int32 background, 01468 l_int32 spacing, 01469 l_int32 border) 01470 { 01471 l_int32 x, y, w, h, wd, hd, d; 01472 l_int32 i, n, nrows, maxht, ninrow, irow, bordval; 01473 l_int32 *rowht; 01474 l_float32 scalefact; 01475 PIX *pix, *pixn, *pixt, *pixb, *pixd; 01476 PIXA *pixan; 01477 01478 PROCNAME("pixacompDisplayTiledAndScaled"); 01479 01480 if (!pixac) 01481 return (PIX *)ERROR_PTR("pixac not defined", procName, NULL); 01482 if (outdepth != 1 && outdepth != 8 && outdepth != 32) 01483 return (PIX *)ERROR_PTR("outdepth not in {1, 8, 32}", procName, NULL); 01484 if (border < 0 || border > tilewidth / 5) 01485 border = 0; 01486 01487 if ((n = pixacompGetCount(pixac)) == 0) 01488 return (PIX *)ERROR_PTR("no components", procName, NULL); 01489 01490 /* Normalize scale and depth for each pix; optionally add border */ 01491 pixan = pixaCreate(n); 01492 bordval = (outdepth == 1) ? 1 : 0; 01493 for (i = 0; i < n; i++) { 01494 if ((pix = pixacompGetPix(pixac, i)) == NULL) { 01495 L_WARNING_INT("pix %d not made", procName, i); 01496 continue; 01497 } 01498 01499 pixGetDimensions(pix, &w, &h, &d); 01500 scalefact = (l_float32)(tilewidth - 2 * border) / (l_float32)w; 01501 if (d == 1 && outdepth > 1 && scalefact < 1.0) 01502 pixt = pixScaleToGray(pix, scalefact); 01503 else 01504 pixt = pixScale(pix, scalefact, scalefact); 01505 01506 if (outdepth == 1) 01507 pixn = pixConvertTo1(pixt, 128); 01508 else if (outdepth == 8) 01509 pixn = pixConvertTo8(pixt, FALSE); 01510 else /* outdepth == 32 */ 01511 pixn = pixConvertTo32(pixt); 01512 pixDestroy(&pixt); 01513 01514 if (border) 01515 pixb = pixAddBorder(pixn, border, bordval); 01516 else 01517 pixb = pixClone(pixn); 01518 01519 pixaAddPix(pixan, pixb, L_INSERT); 01520 pixDestroy(&pix); 01521 pixDestroy(&pixn); 01522 } 01523 if ((n = pixaGetCount(pixan)) == 0) { /* should not have changed! */ 01524 pixaDestroy(&pixan); 01525 return (PIX *)ERROR_PTR("no components", procName, NULL); 01526 } 01527 01528 /* Determine the size of each row and of pixd */ 01529 wd = tilewidth * ncols + spacing * (ncols + 1); 01530 nrows = (n + ncols - 1) / ncols; 01531 if ((rowht = (l_int32 *)CALLOC(nrows, sizeof(l_int32))) == NULL) 01532 return (PIX *)ERROR_PTR("rowht array not made", procName, NULL); 01533 maxht = 0; 01534 ninrow = 0; 01535 irow = 0; 01536 for (i = 0; i < n; i++) { 01537 pix = pixaGetPix(pixan, i, L_CLONE); 01538 ninrow++; 01539 pixGetDimensions(pix, &w, &h, NULL); 01540 maxht = L_MAX(h, maxht); 01541 if (ninrow == ncols) { 01542 rowht[irow] = maxht; 01543 maxht = ninrow = 0; /* reset */ 01544 irow++; 01545 } 01546 pixDestroy(&pix); 01547 } 01548 if (ninrow > 0) { /* last fencepost */ 01549 rowht[irow] = maxht; 01550 irow++; /* total number of rows */ 01551 } 01552 nrows = irow; 01553 hd = spacing * (nrows + 1); 01554 for (i = 0; i < nrows; i++) 01555 hd += rowht[i]; 01556 01557 pixd = pixCreate(wd, hd, outdepth); 01558 if ((background == 1 && outdepth == 1) || 01559 (background == 0 && outdepth != 1)) 01560 pixSetAll(pixd); 01561 01562 /* Now blit images to pixd */ 01563 x = y = spacing; 01564 irow = 0; 01565 for (i = 0; i < n; i++) { 01566 pix = pixaGetPix(pixan, i, L_CLONE); 01567 pixGetDimensions(pix, &w, &h, NULL); 01568 if (i && ((i % ncols) == 0)) { /* start new row */ 01569 x = spacing; 01570 y += spacing + rowht[irow]; 01571 irow++; 01572 } 01573 pixRasterop(pixd, x, y, w, h, PIX_SRC, pix, 0, 0); 01574 x += tilewidth + spacing; 01575 pixDestroy(&pix); 01576 } 01577 01578 pixaDestroy(&pixan); 01579 FREE(rowht); 01580 return pixd; 01581 } 01582 01583