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 * fpix1.c 00018 * 00019 * This file has basic constructors, destructors and field accessors 00020 * for FPix, FPixa and DPix. It also has uncompressed read/write. 00021 * 00022 * FPix Create/copy/destroy 00023 * FPIX *fpixCreate() 00024 * FPIX *fpixCreateTemplate() 00025 * FPIX *fpixClone() 00026 * FPIX *fpixCopy() 00027 * l_int32 fpixResizeImageData() 00028 * void fpixDestroy() 00029 * 00030 * FPix accessors 00031 * l_int32 fpixGetDimensions() 00032 * l_int32 fpixSetDimensions() 00033 * l_int32 fpixGetWpl() 00034 * l_int32 fpixSetWpl() 00035 * l_int32 fpixGetRefcount() 00036 * l_int32 fpixChangeRefcount() 00037 * l_int32 fpixGetResolution() 00038 * l_int32 fpixSetResolution() 00039 * l_int32 fpixCopyResolution() 00040 * l_float32 *fpixGetData() 00041 * l_int32 fpixSetData() 00042 * l_int32 fpixGetPixel() 00043 * l_int32 fpixSetPixel() 00044 * 00045 * FPixa Create/copy/destroy 00046 * FPIXA *fpixaCreate() 00047 * FPIXA *fpixaCopy() 00048 * void fpixaDestroy() 00049 * 00050 * FPixa addition 00051 * l_int32 fpixaAddFPix() 00052 * l_int32 fpixaExtendArray() 00053 * l_int32 fpixaExtendArrayToSize() 00054 * 00055 * FPixa accessors 00056 * l_int32 fpixaGetCount() 00057 * l_int32 fpixaChangeRefcount() 00058 * FPIX *fpixaGetFPix() 00059 * l_int32 fpixaGetFPixDimensions() 00060 * l_int32 fpixaGetPixel() 00061 * l_int32 fpixaSetPixel() 00062 * 00063 * DPix Create/copy/destroy 00064 * DPIX *dpixCreate() 00065 * DPIX *dpixCreateTemplate() 00066 * DPIX *dpixClone() 00067 * DPIX *dpixCopy() 00068 * l_int32 dpixResizeImageData() 00069 * void dpixDestroy() 00070 * 00071 * DPix accessors 00072 * l_int32 dpixGetDimensions() 00073 * l_int32 dpixSetDimensions() 00074 * l_int32 dpixGetWpl() 00075 * l_int32 dpixSetWpl() 00076 * l_int32 dpixGetRefcount() 00077 * l_int32 dpixChangeRefcount() 00078 * l_int32 dpixGetResolution() 00079 * l_int32 dpixSetResolution() 00080 * l_int32 dpixCopyResolution() 00081 * l_float64 *dpixGetData() 00082 * l_int32 dpixSetData() 00083 * l_int32 dpixGetPixel() 00084 * l_int32 dpixSetPixel() 00085 * 00086 * FPix serialized I/O 00087 * FPIX *fpixRead() 00088 * FPIX *fpixReadStream() 00089 * l_int32 fpixWrite() 00090 * l_int32 fpixWriteStream() 00091 * FPIX *fpixEndianByteSwap() 00092 * 00093 * DPix serialized I/O 00094 * DPIX *dpixRead() 00095 * DPIX *dpixReadStream() 00096 * l_int32 dpixWrite() 00097 * l_int32 dpixWriteStream() 00098 * DPIX *dpixEndianByteSwap() 00099 * 00100 * Print FPix (subsampled, for debugging) 00101 * l_int32 fpixPrintStream() 00102 */ 00103 00104 #include <string.h> 00105 #include "allheaders.h" 00106 00107 static const l_int32 INITIAL_PTR_ARRAYSIZE = 20; /* must be > 0 */ 00108 00109 00110 /*--------------------------------------------------------------------* 00111 * FPix Create/copy/destroy * 00112 *--------------------------------------------------------------------*/ 00113 /*! 00114 * fpixCreate() 00115 * 00116 * Input: width, height 00117 * Return: fpixd (with data allocated and initialized to 0), 00118 * or null on error 00119 * 00120 * Notes: 00121 * (1) Makes a FPix of specified size, with the data array 00122 * allocated and initialized to 0. 00123 */ 00124 FPIX * 00125 fpixCreate(l_int32 width, 00126 l_int32 height) 00127 { 00128 l_float32 *data; 00129 FPIX *fpixd; 00130 00131 PROCNAME("fpixCreate"); 00132 00133 if (width <= 0) 00134 return (FPIX *)ERROR_PTR("width must be > 0", procName, NULL); 00135 if (height <= 0) 00136 return (FPIX *)ERROR_PTR("height must be > 0", procName, NULL); 00137 00138 if ((fpixd = (FPIX *)CALLOC(1, sizeof(FPIX))) == NULL) 00139 return (FPIX *)ERROR_PTR("CALLOC fail for fpixd", procName, NULL); 00140 fpixSetDimensions(fpixd, width, height); 00141 fpixSetWpl(fpixd, width); 00142 fpixd->refcount = 1; 00143 00144 data = (l_float32 *)CALLOC(width * height, sizeof(l_float32)); 00145 if (!data) 00146 return (FPIX *)ERROR_PTR("CALLOC fail for data", procName, NULL); 00147 fpixSetData(fpixd, data); 00148 00149 return fpixd; 00150 } 00151 00152 00153 /*! 00154 * fpixCreateTemplate() 00155 * 00156 * Input: fpixs 00157 * Return: fpixd, or null on error 00158 * 00159 * Notes: 00160 * (1) Makes a FPix of the same size as the input FPix, with the 00161 * data array allocated and initialized to 0. 00162 * (2) Copies the resolution. 00163 */ 00164 FPIX * 00165 fpixCreateTemplate(FPIX *fpixs) 00166 { 00167 l_int32 w, h; 00168 FPIX *fpixd; 00169 00170 PROCNAME("fpixCreateTemplate"); 00171 00172 if (!fpixs) 00173 return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL); 00174 00175 fpixGetDimensions(fpixs, &w, &h); 00176 fpixd = fpixCreate(w, h); 00177 fpixCopyResolution(fpixd, fpixs); 00178 return fpixd; 00179 } 00180 00181 00182 /*! 00183 * fpixClone() 00184 * 00185 * Input: fpix 00186 * Return: same fpix (ptr), or null on error 00187 * 00188 * Notes: 00189 * (1) See pixClone() for definition and usage. 00190 */ 00191 FPIX * 00192 fpixClone(FPIX *fpix) 00193 { 00194 PROCNAME("fpixClone"); 00195 00196 if (!fpix) 00197 return (FPIX *)ERROR_PTR("fpix not defined", procName, NULL); 00198 fpixChangeRefcount(fpix, 1); 00199 00200 return fpix; 00201 } 00202 00203 00204 /*! 00205 * fpixCopy() 00206 * 00207 * Input: fpixd (<optional>; can be null, or equal to fpixs, 00208 * or different from fpixs) 00209 * fpixs 00210 * Return: fpixd, or null on error 00211 * 00212 * Notes: 00213 * (1) There are three cases: 00214 * (a) fpixd == null (makes a new fpix; refcount = 1) 00215 * (b) fpixd == fpixs (no-op) 00216 * (c) fpixd != fpixs (data copy; no change in refcount) 00217 * If the refcount of fpixd > 1, case (c) will side-effect 00218 * these handles. 00219 * (2) The general pattern of use is: 00220 * fpixd = fpixCopy(fpixd, fpixs); 00221 * This will work for all three cases. 00222 * For clarity when the case is known, you can use: 00223 * (a) fpixd = fpixCopy(NULL, fpixs); 00224 * (c) fpixCopy(fpixd, fpixs); 00225 * (3) For case (c), we check if fpixs and fpixd are the same size. 00226 * If so, the data is copied directly. 00227 * Otherwise, the data is reallocated to the correct size 00228 * and the copy proceeds. The refcount of fpixd is unchanged. 00229 * (4) This operation, like all others that may involve a pre-existing 00230 * fpixd, will side-effect any existing clones of fpixd. 00231 */ 00232 FPIX * 00233 fpixCopy(FPIX *fpixd, /* can be null */ 00234 FPIX *fpixs) 00235 { 00236 l_int32 w, h, bytes; 00237 l_float32 *datas, *datad; 00238 00239 PROCNAME("fpixCopy"); 00240 00241 if (!fpixs) 00242 return (FPIX *)ERROR_PTR("fpixs not defined", procName, NULL); 00243 if (fpixs == fpixd) 00244 return fpixd; 00245 00246 /* Total bytes in image data */ 00247 fpixGetDimensions(fpixs, &w, &h); 00248 bytes = 4 * w * h; 00249 00250 /* If we're making a new fpix ... */ 00251 if (!fpixd) { 00252 if ((fpixd = fpixCreateTemplate(fpixs)) == NULL) 00253 return (FPIX *)ERROR_PTR("fpixd not made", procName, NULL); 00254 datas = fpixGetData(fpixs); 00255 datad = fpixGetData(fpixd); 00256 memcpy((char *)datad, (char *)datas, bytes); 00257 return fpixd; 00258 } 00259 00260 /* Reallocate image data if sizes are different */ 00261 fpixResizeImageData(fpixd, fpixs); 00262 00263 /* Copy data */ 00264 fpixCopyResolution(fpixd, fpixs); 00265 datas = fpixGetData(fpixs); 00266 datad = fpixGetData(fpixd); 00267 memcpy((char*)datad, (char*)datas, bytes); 00268 return fpixd; 00269 } 00270 00271 00272 /*! 00273 * fpixResizeImageData() 00274 * 00275 * Input: fpixd, fpixs 00276 * Return: 0 if OK, 1 on error 00277 * 00278 * Notes: 00279 * (1) If the data sizes differ, this destroys the existing 00280 * data in fpixd and allocates a new, uninitialized, data array 00281 * of the same size as the data in fpixs. Otherwise, this 00282 * doesn't do anything. 00283 */ 00284 l_int32 00285 fpixResizeImageData(FPIX *fpixd, 00286 FPIX *fpixs) 00287 { 00288 l_int32 ws, hs, wd, hd, bytes; 00289 l_float32 *data; 00290 00291 PROCNAME("fpixResizeImageData"); 00292 00293 if (!fpixs) 00294 return ERROR_INT("fpixs not defined", procName, 1); 00295 if (!fpixd) 00296 return ERROR_INT("fpixd not defined", procName, 1); 00297 00298 fpixGetDimensions(fpixs, &ws, &hs); 00299 fpixGetDimensions(fpixd, &wd, &hd); 00300 if (ws == wd && hs == hd) /* nothing to do */ 00301 return 0; 00302 00303 fpixSetDimensions(fpixd, ws, hs); 00304 fpixSetWpl(fpixd, ws); 00305 bytes = 4 * ws * hs; 00306 data = fpixGetData(fpixd); 00307 if (data) FREE(data); 00308 if ((data = (l_float32 *)MALLOC(bytes)) == NULL) 00309 return ERROR_INT("MALLOC fail for data", procName, 1); 00310 fpixSetData(fpixd, data); 00311 return 0; 00312 } 00313 00314 00315 /*! 00316 * fpixDestroy() 00317 * 00318 * Input: &fpix <will be nulled> 00319 * Return: void 00320 * 00321 * Notes: 00322 * (1) Decrements the ref count and, if 0, destroys the fpix. 00323 * (2) Always nulls the input ptr. 00324 */ 00325 void 00326 fpixDestroy(FPIX **pfpix) 00327 { 00328 l_float32 *data; 00329 FPIX *fpix; 00330 00331 PROCNAME("fpixDestroy"); 00332 00333 if (!pfpix) { 00334 L_WARNING("ptr address is null!", procName); 00335 return; 00336 } 00337 00338 if ((fpix = *pfpix) == NULL) 00339 return; 00340 00341 /* Decrement the ref count. If it is 0, destroy the fpix. */ 00342 fpixChangeRefcount(fpix, -1); 00343 if (fpixGetRefcount(fpix) <= 0) { 00344 if ((data = fpixGetData(fpix)) != NULL) 00345 FREE(data); 00346 FREE(fpix); 00347 } 00348 00349 *pfpix = NULL; 00350 return; 00351 } 00352 00353 00354 /*--------------------------------------------------------------------* 00355 * FPix Accessors * 00356 *--------------------------------------------------------------------*/ 00357 /*! 00358 * fpixGetDimensions() 00359 * 00360 * Input: fpix 00361 * &w, &h (<optional return>; each can be null) 00362 * Return: 0 if OK, 1 on error 00363 */ 00364 l_int32 00365 fpixGetDimensions(FPIX *fpix, 00366 l_int32 *pw, 00367 l_int32 *ph) 00368 { 00369 PROCNAME("fpixGetDimensions"); 00370 00371 if (!fpix) 00372 return ERROR_INT("fpix not defined", procName, 1); 00373 if (pw) *pw = fpix->w; 00374 if (ph) *ph = fpix->h; 00375 return 0; 00376 } 00377 00378 00379 /*! 00380 * fpixSetDimensions() 00381 * 00382 * Input: fpix 00383 * w, h 00384 * Return: 0 if OK, 1 on error 00385 */ 00386 l_int32 00387 fpixSetDimensions(FPIX *fpix, 00388 l_int32 w, 00389 l_int32 h) 00390 { 00391 PROCNAME("fpixSetDimensions"); 00392 00393 if (!fpix) 00394 return ERROR_INT("fpix not defined", procName, 1); 00395 fpix->w = w; 00396 fpix->h = h; 00397 return 0; 00398 } 00399 00400 00401 l_int32 00402 fpixGetWpl(FPIX *fpix) 00403 { 00404 PROCNAME("fpixGetWpl"); 00405 00406 if (!fpix) 00407 return ERROR_INT("fpix not defined", procName, 1); 00408 return fpix->wpl; 00409 } 00410 00411 00412 l_int32 00413 fpixSetWpl(FPIX *fpix, 00414 l_int32 wpl) 00415 { 00416 PROCNAME("fpixSetWpl"); 00417 00418 if (!fpix) 00419 return ERROR_INT("fpix not defined", procName, 1); 00420 00421 fpix->wpl = wpl; 00422 return 0; 00423 } 00424 00425 00426 l_int32 00427 fpixGetRefcount(FPIX *fpix) 00428 { 00429 PROCNAME("fpixGetRefcount"); 00430 00431 if (!fpix) 00432 return ERROR_INT("fpix not defined", procName, UNDEF); 00433 return fpix->refcount; 00434 } 00435 00436 00437 l_int32 00438 fpixChangeRefcount(FPIX *fpix, 00439 l_int32 delta) 00440 { 00441 PROCNAME("fpixChangeRefcount"); 00442 00443 if (!fpix) 00444 return ERROR_INT("fpix not defined", procName, 1); 00445 00446 fpix->refcount += delta; 00447 return 0; 00448 } 00449 00450 00451 l_int32 00452 fpixGetResolution(FPIX *fpix, 00453 l_int32 *pxres, 00454 l_int32 *pyres) 00455 { 00456 PROCNAME("fpixGetResolution"); 00457 00458 if (!fpix) 00459 return ERROR_INT("fpix not defined", procName, 1); 00460 if (pxres) *pxres = fpix->xres; 00461 if (pyres) *pyres = fpix->yres; 00462 return 0; 00463 } 00464 00465 00466 l_int32 00467 fpixSetResolution(FPIX *fpix, 00468 l_int32 xres, 00469 l_int32 yres) 00470 { 00471 PROCNAME("fpixSetResolution"); 00472 00473 if (!fpix) 00474 return ERROR_INT("fpix not defined", procName, 1); 00475 00476 fpix->xres = xres; 00477 fpix->yres = yres; 00478 return 0; 00479 } 00480 00481 00482 l_int32 00483 fpixCopyResolution(FPIX *fpixd, 00484 FPIX *fpixs) 00485 { 00486 l_int32 xres, yres; 00487 PROCNAME("fpixCopyResolution"); 00488 00489 if (!fpixs || !fpixd) 00490 return ERROR_INT("fpixs and fpixd not both defined", procName, 1); 00491 00492 fpixGetResolution(fpixs, &xres, &yres); 00493 fpixSetResolution(fpixd, xres, yres); 00494 return 0; 00495 } 00496 00497 00498 l_float32 * 00499 fpixGetData(FPIX *fpix) 00500 { 00501 PROCNAME("fpixGetData"); 00502 00503 if (!fpix) 00504 return (l_float32 *)ERROR_PTR("fpix not defined", procName, NULL); 00505 return fpix->data; 00506 } 00507 00508 00509 l_int32 00510 fpixSetData(FPIX *fpix, 00511 l_float32 *data) 00512 { 00513 PROCNAME("fpixSetData"); 00514 00515 if (!fpix) 00516 return ERROR_INT("fpix not defined", procName, 1); 00517 00518 fpix->data = data; 00519 return 0; 00520 } 00521 00522 00523 /*! 00524 * fpixGetPixel() 00525 * 00526 * Input: fpix 00527 * (x,y) pixel coords 00528 * &val (<return> pixel value) 00529 * Return: 0 if OK; 1 on error 00530 */ 00531 l_int32 00532 fpixGetPixel(FPIX *fpix, 00533 l_int32 x, 00534 l_int32 y, 00535 l_float32 *pval) 00536 { 00537 l_int32 w, h; 00538 00539 PROCNAME("fpixGetPixel"); 00540 00541 if (!pval) 00542 return ERROR_INT("pval not defined", procName, 1); 00543 *pval = 0.0; 00544 if (!fpix) 00545 return ERROR_INT("fpix not defined", procName, 1); 00546 00547 fpixGetDimensions(fpix, &w, &h); 00548 if (x < 0 || x >= w) 00549 return ERROR_INT("x out of bounds", procName, 1); 00550 if (y < 0 || y >= h) 00551 return ERROR_INT("y out of bounds", procName, 1); 00552 00553 *pval = *(fpix->data + y * w + x); 00554 return 0; 00555 } 00556 00557 00558 /*! 00559 * fpixSetPixel() 00560 * 00561 * Input: fpix 00562 * (x,y) pixel coords 00563 * val (pixel value) 00564 * Return: 0 if OK; 1 on error 00565 */ 00566 l_int32 00567 fpixSetPixel(FPIX *fpix, 00568 l_int32 x, 00569 l_int32 y, 00570 l_float32 val) 00571 { 00572 l_int32 w, h; 00573 00574 PROCNAME("fpixSetPixel"); 00575 00576 if (!fpix) 00577 return ERROR_INT("fpix not defined", procName, 1); 00578 00579 fpixGetDimensions(fpix, &w, &h); 00580 if (x < 0 || x >= w) 00581 return ERROR_INT("x out of bounds", procName, 1); 00582 if (y < 0 || y >= h) 00583 return ERROR_INT("y out of bounds", procName, 1); 00584 00585 *(fpix->data + y * w + x) = val; 00586 return 0; 00587 } 00588 00589 00590 /*--------------------------------------------------------------------* 00591 * FPixa Create/copy/destroy * 00592 *--------------------------------------------------------------------*/ 00593 /*! 00594 * fpixaCreate() 00595 * 00596 * Input: n (initial number of ptrs) 00597 * Return: fpixa, or null on error 00598 */ 00599 FPIXA * 00600 fpixaCreate(l_int32 n) 00601 { 00602 FPIXA *fpixa; 00603 00604 PROCNAME("fpixaCreate"); 00605 00606 if (n <= 0) 00607 n = INITIAL_PTR_ARRAYSIZE; 00608 00609 if ((fpixa = (FPIXA *)CALLOC(1, sizeof(FPIXA))) == NULL) 00610 return (FPIXA *)ERROR_PTR("pixa not made", procName, NULL); 00611 fpixa->n = 0; 00612 fpixa->nalloc = n; 00613 fpixa->refcount = 1; 00614 00615 if ((fpixa->fpix = (FPIX **)CALLOC(n, sizeof(FPIX *))) == NULL) 00616 return (FPIXA *)ERROR_PTR("fpix ptrs not made", procName, NULL); 00617 00618 return fpixa; 00619 } 00620 00621 00622 /*! 00623 * fpixaCopy() 00624 * 00625 * Input: fpixas 00626 * copyflag: 00627 * L_COPY makes a new fpixa and copies each fpix 00628 * L_CLONE gives a new ref-counted handle to the input fpixa 00629 * L_COPY_CLONE makes a new fpixa with clones of all fpix 00630 * Return: new fpixa, or null on error 00631 */ 00632 FPIXA * 00633 fpixaCopy(FPIXA *fpixa, 00634 l_int32 copyflag) 00635 { 00636 l_int32 i; 00637 FPIX *fpixc; 00638 FPIXA *fpixac; 00639 00640 PROCNAME("fpixaCopy"); 00641 00642 if (!fpixa) 00643 return (FPIXA *)ERROR_PTR("fpixa not defined", procName, NULL); 00644 00645 if (copyflag == L_CLONE) { 00646 fpixaChangeRefcount(fpixa, 1); 00647 return fpixa; 00648 } 00649 00650 if (copyflag != L_COPY && copyflag != L_COPY_CLONE) 00651 return (FPIXA *)ERROR_PTR("invalid copyflag", procName, NULL); 00652 00653 if ((fpixac = fpixaCreate(fpixa->n)) == NULL) 00654 return (FPIXA *)ERROR_PTR("fpixac not made", procName, NULL); 00655 for (i = 0; i < fpixa->n; i++) { 00656 if (copyflag == L_COPY) 00657 fpixc = fpixaGetFPix(fpixa, i, L_COPY); 00658 else /* copy-clone */ 00659 fpixc = fpixaGetFPix(fpixa, i, L_CLONE); 00660 fpixaAddFPix(fpixac, fpixc, L_INSERT); 00661 } 00662 00663 return fpixac; 00664 } 00665 00666 00667 /*! 00668 * fpixaDestroy() 00669 * 00670 * Input: &fpixa (<can be nulled>) 00671 * Return: void 00672 * 00673 * Notes: 00674 * (1) Decrements the ref count and, if 0, destroys the fpixa. 00675 * (2) Always nulls the input ptr. 00676 */ 00677 void 00678 fpixaDestroy(FPIXA **pfpixa) 00679 { 00680 l_int32 i; 00681 FPIXA *fpixa; 00682 00683 PROCNAME("fpixaDestroy"); 00684 00685 if (pfpixa == NULL) { 00686 L_WARNING("ptr address is NULL!", procName); 00687 return; 00688 } 00689 00690 if ((fpixa = *pfpixa) == NULL) 00691 return; 00692 00693 /* Decrement the refcount. If it is 0, destroy the pixa. */ 00694 fpixaChangeRefcount(fpixa, -1); 00695 if (fpixa->refcount <= 0) { 00696 for (i = 0; i < fpixa->n; i++) 00697 fpixDestroy(&fpixa->fpix[i]); 00698 FREE(fpixa->fpix); 00699 FREE(fpixa); 00700 } 00701 00702 *pfpixa = NULL; 00703 return; 00704 } 00705 00706 00707 /*--------------------------------------------------------------------* 00708 * FPixa addition * 00709 *--------------------------------------------------------------------*/ 00710 /*! 00711 * fpixaAddFPix() 00712 * 00713 * Input: fpixa 00714 * fpix (to be added) 00715 * copyflag (L_INSERT, L_COPY, L_CLONE) 00716 * Return: 0 if OK; 1 on error 00717 */ 00718 l_int32 00719 fpixaAddFPix(FPIXA *fpixa, 00720 FPIX *fpix, 00721 l_int32 copyflag) 00722 { 00723 l_int32 n; 00724 FPIX *fpixc; 00725 00726 PROCNAME("fpixaAddFPix"); 00727 00728 if (!fpixa) 00729 return ERROR_INT("fpixa not defined", procName, 1); 00730 if (!fpix) 00731 return ERROR_INT("fpix not defined", procName, 1); 00732 00733 if (copyflag == L_INSERT) 00734 fpixc = fpix; 00735 else if (copyflag == L_COPY) 00736 fpixc = fpixCopy(NULL, fpix); 00737 else if (copyflag == L_CLONE) 00738 fpixc = fpixClone(fpix); 00739 else 00740 return ERROR_INT("invalid copyflag", procName, 1); 00741 if (!fpixc) 00742 return ERROR_INT("fpixc not made", procName, 1); 00743 00744 n = fpixaGetCount(fpixa); 00745 if (n >= fpixa->nalloc) 00746 fpixaExtendArray(fpixa); 00747 fpixa->fpix[n] = fpixc; 00748 fpixa->n++; 00749 00750 return 0; 00751 } 00752 00753 00754 /*! 00755 * fpixaExtendArray() 00756 * 00757 * Input: fpixa 00758 * Return: 0 if OK; 1 on error 00759 * 00760 * Notes: 00761 * (1) Doubles the size of the fpixa ptr array. 00762 */ 00763 l_int32 00764 fpixaExtendArray(FPIXA *fpixa) 00765 { 00766 PROCNAME("fpixaExtendArray"); 00767 00768 if (!fpixa) 00769 return ERROR_INT("fpixa not defined", procName, 1); 00770 00771 return fpixaExtendArrayToSize(fpixa, 2 * fpixa->nalloc); 00772 } 00773 00774 00775 /*! 00776 * fpixaExtendArrayToSize() 00777 * 00778 * Input: fpixa 00779 * Return: 0 if OK; 1 on error 00780 * 00781 * Notes: 00782 * (1) If necessary, reallocs new fpixa ptrs array to @size. 00783 */ 00784 l_int32 00785 fpixaExtendArrayToSize(FPIXA *fpixa, 00786 l_int32 size) 00787 { 00788 PROCNAME("fpixaExtendArrayToSize"); 00789 00790 if (!fpixa) 00791 return ERROR_INT("fpixa not defined", procName, 1); 00792 00793 if (size > fpixa->nalloc) { 00794 if ((fpixa->fpix = (FPIX **)reallocNew((void **)&fpixa->fpix, 00795 sizeof(FPIX *) * fpixa->nalloc, 00796 size * sizeof(FPIX *))) == NULL) 00797 return ERROR_INT("new ptr array not returned", procName, 1); 00798 fpixa->nalloc = size; 00799 } 00800 return 0; 00801 } 00802 00803 00804 /*--------------------------------------------------------------------* 00805 * FPixa accessors * 00806 *--------------------------------------------------------------------*/ 00807 /*! 00808 * fpixaGetCount() 00809 * 00810 * Input: fpixa 00811 * Return: count, or 0 if no pixa 00812 */ 00813 l_int32 00814 fpixaGetCount(FPIXA *fpixa) 00815 { 00816 PROCNAME("fpixaGetCount"); 00817 00818 if (!fpixa) 00819 return ERROR_INT("fpixa not defined", procName, 0); 00820 00821 return fpixa->n; 00822 } 00823 00824 00825 /*! 00826 * fpixaChangeRefcount() 00827 * 00828 * Input: fpixa 00829 * Return: 0 if OK, 1 on error 00830 */ 00831 l_int32 00832 fpixaChangeRefcount(FPIXA *fpixa, 00833 l_int32 delta) 00834 { 00835 PROCNAME("fpixaChangeRefcount"); 00836 00837 if (!fpixa) 00838 return ERROR_INT("fpixa not defined", procName, 1); 00839 00840 fpixa->refcount += delta; 00841 return 0; 00842 } 00843 00844 00845 /*! 00846 * fpixaGetFPix() 00847 * 00848 * Input: fpixa 00849 * index (to the index-th fpix) 00850 * accesstype (L_COPY or L_CLONE) 00851 * Return: fpix, or null on error 00852 */ 00853 FPIX * 00854 fpixaGetFPix(FPIXA *fpixa, 00855 l_int32 index, 00856 l_int32 accesstype) 00857 { 00858 PROCNAME("fpixaGetFPix"); 00859 00860 if (!fpixa) 00861 return (FPIX *)ERROR_PTR("fpixa not defined", procName, NULL); 00862 if (index < 0 || index >= fpixa->n) 00863 return (FPIX *)ERROR_PTR("index not valid", procName, NULL); 00864 00865 if (accesstype == L_COPY) 00866 return fpixCopy(NULL, fpixa->fpix[index]); 00867 else if (accesstype == L_CLONE) 00868 return fpixClone(fpixa->fpix[index]); 00869 else 00870 return (FPIX *)ERROR_PTR("invalid accesstype", procName, NULL); 00871 } 00872 00873 00874 /*! 00875 * fpixaGetFPixDimensions() 00876 * 00877 * Input: fpixa 00878 * index (to the index-th box) 00879 * &w, &h (<optional return>; each can be null) 00880 * Return: 0 if OK, 1 on error 00881 */ 00882 l_int32 00883 fpixaGetFPixDimensions(FPIXA *fpixa, 00884 l_int32 index, 00885 l_int32 *pw, 00886 l_int32 *ph) 00887 { 00888 FPIX *fpix; 00889 00890 PROCNAME("fpixaGetFPixDimensions"); 00891 00892 if (!fpixa) 00893 return ERROR_INT("fpixa not defined", procName, 1); 00894 if (index < 0 || index >= fpixa->n) 00895 return ERROR_INT("index not valid", procName, 1); 00896 00897 if ((fpix = fpixaGetFPix(fpixa, index, L_CLONE)) == NULL) 00898 return ERROR_INT("fpix not found!", procName, 1); 00899 fpixGetDimensions(fpix, pw, ph); 00900 fpixDestroy(&fpix); 00901 return 0; 00902 } 00903 00904 00905 /*! 00906 * fpixaGetPixel() 00907 * 00908 * Input: fpixa 00909 * index (into fpixa array) 00910 * (x,y) pixel coords 00911 * &val (<return> pixel value) 00912 * Return: 0 if OK; 1 on error 00913 */ 00914 l_int32 00915 fpixaGetPixel(FPIXA *fpixa, 00916 l_int32 index, 00917 l_int32 x, 00918 l_int32 y, 00919 l_float32 *pval) 00920 { 00921 l_int32 n, ret; 00922 FPIX *fpix; 00923 00924 PROCNAME("fpixaGetPixel"); 00925 00926 if (!pval) 00927 return ERROR_INT("pval not defined", procName, 1); 00928 *pval = 0.0; 00929 if (!fpixa) 00930 return ERROR_INT("fpixa not defined", procName, 1); 00931 n = fpixaGetCount(fpixa); 00932 if (index < 0 || index >= n) 00933 return ERROR_INT("invalid index into fpixa", procName, 1); 00934 00935 fpix = fpixaGetFPix(fpixa, index, L_CLONE); 00936 ret = fpixGetPixel(fpix, x, y, pval); 00937 fpixDestroy(&fpix); 00938 return ret; 00939 } 00940 00941 00942 /*! 00943 * fpixaSetPixel() 00944 * 00945 * Input: fpixa 00946 * index (into fpixa array) 00947 * (x,y) pixel coords 00948 * val (pixel value) 00949 * Return: 0 if OK; 1 on error 00950 */ 00951 l_int32 00952 fpixaSetPixel(FPIXA *fpixa, 00953 l_int32 index, 00954 l_int32 x, 00955 l_int32 y, 00956 l_float32 val) 00957 { 00958 l_int32 n, ret; 00959 FPIX *fpix; 00960 00961 PROCNAME("fpixaSetPixel"); 00962 00963 if (!fpixa) 00964 return ERROR_INT("fpixa not defined", procName, 1); 00965 n = fpixaGetCount(fpixa); 00966 if (index < 0 || index >= n) 00967 return ERROR_INT("invalid index into fpixa", procName, 1); 00968 00969 fpix = fpixaGetFPix(fpixa, index, L_CLONE); 00970 ret = fpixSetPixel(fpix, x, y, val); 00971 fpixDestroy(&fpix); 00972 return ret; 00973 } 00974 00975 00976 /*--------------------------------------------------------------------* 00977 * DPix Create/copy/destroy * 00978 *--------------------------------------------------------------------*/ 00979 /*! 00980 * dpixCreate() 00981 * 00982 * Input: width, height 00983 * Return: dpix (with data allocated and initialized to 0), 00984 * or null on error 00985 * 00986 * Notes: 00987 * (1) Makes a DPix of specified size, with the data array 00988 * allocated and initialized to 0. 00989 */ 00990 DPIX * 00991 dpixCreate(l_int32 width, 00992 l_int32 height) 00993 { 00994 l_float64 *data; 00995 DPIX *dpix; 00996 00997 PROCNAME("dpixCreate"); 00998 00999 if (width <= 0) 01000 return (DPIX *)ERROR_PTR("width must be > 0", procName, NULL); 01001 if (height <= 0) 01002 return (DPIX *)ERROR_PTR("height must be > 0", procName, NULL); 01003 01004 if ((dpix = (DPIX *)CALLOC(1, sizeof(DPIX))) == NULL) 01005 return (DPIX *)ERROR_PTR("CALLOC fail for dpix", procName, NULL); 01006 dpixSetDimensions(dpix, width, height); 01007 dpixSetWpl(dpix, width); /* Note: 8 byte words here */ 01008 dpix->refcount = 1; 01009 01010 data = (l_float64 *)CALLOC(width * height, sizeof(l_float64)); 01011 if (!data) 01012 return (DPIX *)ERROR_PTR("CALLOC fail for data", procName, NULL); 01013 dpixSetData(dpix, data); 01014 01015 return dpix; 01016 } 01017 01018 01019 /*! 01020 * dpixCreateTemplate() 01021 * 01022 * Input: dpixs 01023 * Return: dpixd, or null on error 01024 * 01025 * Notes: 01026 * (1) Makes a DPix of the same size as the input DPix, with the 01027 * data array allocated and initialized to 0. 01028 * (2) Copies the resolution. 01029 */ 01030 DPIX * 01031 dpixCreateTemplate(DPIX *dpixs) 01032 { 01033 l_int32 w, h; 01034 DPIX *dpixd; 01035 01036 PROCNAME("dpixCreateTemplate"); 01037 01038 if (!dpixs) 01039 return (DPIX *)ERROR_PTR("dpixs not defined", procName, NULL); 01040 01041 dpixGetDimensions(dpixs, &w, &h); 01042 dpixd = dpixCreate(w, h); 01043 dpixCopyResolution(dpixd, dpixs); 01044 return dpixd; 01045 } 01046 01047 01048 /*! 01049 * dpixClone() 01050 * 01051 * Input: dpix 01052 * Return: same dpix (ptr), or null on error 01053 * 01054 * Notes: 01055 * (1) See pixClone() for definition and usage. 01056 */ 01057 DPIX * 01058 dpixClone(DPIX *dpix) 01059 { 01060 PROCNAME("dpixClone"); 01061 01062 if (!dpix) 01063 return (DPIX *)ERROR_PTR("dpix not defined", procName, NULL); 01064 dpixChangeRefcount(dpix, 1); 01065 01066 return dpix; 01067 } 01068 01069 01070 /*! 01071 * dpixCopy() 01072 * 01073 * Input: dpixd (<optional>; can be null, or equal to dpixs, 01074 * or different from dpixs) 01075 * dpixs 01076 * Return: dpixd, or null on error 01077 * 01078 * Notes: 01079 * (1) There are three cases: 01080 * (a) dpixd == null (makes a new dpix; refcount = 1) 01081 * (b) dpixd == dpixs (no-op) 01082 * (c) dpixd != dpixs (data copy; no change in refcount) 01083 * If the refcount of dpixd > 1, case (c) will side-effect 01084 * these handles. 01085 * (2) The general pattern of use is: 01086 * dpixd = dpixCopy(dpixd, dpixs); 01087 * This will work for all three cases. 01088 * For clarity when the case is known, you can use: 01089 * (a) dpixd = dpixCopy(NULL, dpixs); 01090 * (c) dpixCopy(dpixd, dpixs); 01091 * (3) For case (c), we check if dpixs and dpixd are the same size. 01092 * If so, the data is copied directly. 01093 * Otherwise, the data is reallocated to the correct size 01094 * and the copy proceeds. The refcount of dpixd is unchanged. 01095 * (4) This operation, like all others that may involve a pre-existing 01096 * dpixd, will side-effect any existing clones of dpixd. 01097 */ 01098 DPIX * 01099 dpixCopy(DPIX *dpixd, /* can be null */ 01100 DPIX *dpixs) 01101 { 01102 l_int32 w, h, bytes; 01103 l_float64 *datas, *datad; 01104 01105 PROCNAME("dpixCopy"); 01106 01107 if (!dpixs) 01108 return (DPIX *)ERROR_PTR("dpixs not defined", procName, NULL); 01109 if (dpixs == dpixd) 01110 return dpixd; 01111 01112 /* Total bytes in image data */ 01113 dpixGetDimensions(dpixs, &w, &h); 01114 bytes = 8 * w * h; 01115 01116 /* If we're making a new dpix ... */ 01117 if (!dpixd) { 01118 if ((dpixd = dpixCreateTemplate(dpixs)) == NULL) 01119 return (DPIX *)ERROR_PTR("dpixd not made", procName, NULL); 01120 datas = dpixGetData(dpixs); 01121 datad = dpixGetData(dpixd); 01122 memcpy((char *)datad, (char *)datas, bytes); 01123 return dpixd; 01124 } 01125 01126 /* Reallocate image data if sizes are different */ 01127 dpixResizeImageData(dpixd, dpixs); 01128 01129 /* Copy data */ 01130 dpixCopyResolution(dpixd, dpixs); 01131 datas = dpixGetData(dpixs); 01132 datad = dpixGetData(dpixd); 01133 memcpy((char*)datad, (char*)datas, bytes); 01134 return dpixd; 01135 } 01136 01137 01138 /*! 01139 * dpixResizeImageData() 01140 * 01141 * Input: dpixd, dpixs 01142 * Return: 0 if OK, 1 on error 01143 */ 01144 l_int32 01145 dpixResizeImageData(DPIX *dpixd, 01146 DPIX *dpixs) 01147 { 01148 l_int32 ws, hs, wd, hd, bytes; 01149 l_float64 *data; 01150 01151 PROCNAME("dpixResizeImageData"); 01152 01153 if (!dpixs) 01154 return ERROR_INT("dpixs not defined", procName, 1); 01155 if (!dpixd) 01156 return ERROR_INT("dpixd not defined", procName, 1); 01157 01158 dpixGetDimensions(dpixs, &ws, &hs); 01159 dpixGetDimensions(dpixd, &wd, &hd); 01160 if (ws == wd && hs == hd) /* nothing to do */ 01161 return 0; 01162 01163 dpixSetDimensions(dpixd, ws, hs); 01164 dpixSetWpl(dpixd, ws); /* Note: 8 byte words */ 01165 bytes = 8 * ws * hs; 01166 data = dpixGetData(dpixd); 01167 if (data) FREE(data); 01168 if ((data = (l_float64 *)MALLOC(bytes)) == NULL) 01169 return ERROR_INT("MALLOC fail for data", procName, 1); 01170 dpixSetData(dpixd, data); 01171 return 0; 01172 } 01173 01174 01175 /*! 01176 * dpixDestroy() 01177 * 01178 * Input: &dpix <will be nulled> 01179 * Return: void 01180 * 01181 * Notes: 01182 * (1) Decrements the ref count and, if 0, destroys the dpix. 01183 * (2) Always nulls the input ptr. 01184 */ 01185 void 01186 dpixDestroy(DPIX **pdpix) 01187 { 01188 l_float64 *data; 01189 DPIX *dpix; 01190 01191 PROCNAME("dpixDestroy"); 01192 01193 if (!pdpix) { 01194 L_WARNING("ptr address is null!", procName); 01195 return; 01196 } 01197 01198 if ((dpix = *pdpix) == NULL) 01199 return; 01200 01201 /* Decrement the ref count. If it is 0, destroy the dpix. */ 01202 dpixChangeRefcount(dpix, -1); 01203 if (dpixGetRefcount(dpix) <= 0) { 01204 if ((data = dpixGetData(dpix)) != NULL) 01205 FREE(data); 01206 FREE(dpix); 01207 } 01208 01209 *pdpix = NULL; 01210 return; 01211 } 01212 01213 01214 /*--------------------------------------------------------------------* 01215 * DPix Accessors * 01216 *--------------------------------------------------------------------*/ 01217 /*! 01218 * dpixGetDimensions() 01219 * 01220 * Input: dpix 01221 * &w, &h (<optional return>; each can be null) 01222 * Return: 0 if OK, 1 on error 01223 */ 01224 l_int32 01225 dpixGetDimensions(DPIX *dpix, 01226 l_int32 *pw, 01227 l_int32 *ph) 01228 { 01229 PROCNAME("dpixGetDimensions"); 01230 01231 if (!dpix) 01232 return ERROR_INT("dpix not defined", procName, 1); 01233 if (pw) *pw = dpix->w; 01234 if (ph) *ph = dpix->h; 01235 return 0; 01236 } 01237 01238 01239 /*! 01240 * dpixSetDimensions() 01241 * 01242 * Input: dpix 01243 * w, h 01244 * Return: 0 if OK, 1 on error 01245 */ 01246 l_int32 01247 dpixSetDimensions(DPIX *dpix, 01248 l_int32 w, 01249 l_int32 h) 01250 { 01251 PROCNAME("dpixSetDimensions"); 01252 01253 if (!dpix) 01254 return ERROR_INT("dpix not defined", procName, 1); 01255 dpix->w = w; 01256 dpix->h = h; 01257 return 0; 01258 } 01259 01260 01261 l_int32 01262 dpixGetWpl(DPIX *dpix) 01263 { 01264 PROCNAME("dpixGetWpl"); 01265 01266 if (!dpix) 01267 return ERROR_INT("dpix not defined", procName, 1); 01268 return dpix->wpl; 01269 } 01270 01271 01272 l_int32 01273 dpixSetWpl(DPIX *dpix, 01274 l_int32 wpl) 01275 { 01276 PROCNAME("dpixSetWpl"); 01277 01278 if (!dpix) 01279 return ERROR_INT("dpix not defined", procName, 1); 01280 01281 dpix->wpl = wpl; 01282 return 0; 01283 } 01284 01285 01286 l_int32 01287 dpixGetRefcount(DPIX *dpix) 01288 { 01289 PROCNAME("dpixGetRefcount"); 01290 01291 if (!dpix) 01292 return ERROR_INT("dpix not defined", procName, UNDEF); 01293 return dpix->refcount; 01294 } 01295 01296 01297 l_int32 01298 dpixChangeRefcount(DPIX *dpix, 01299 l_int32 delta) 01300 { 01301 PROCNAME("dpixChangeRefcount"); 01302 01303 if (!dpix) 01304 return ERROR_INT("dpix not defined", procName, 1); 01305 01306 dpix->refcount += delta; 01307 return 0; 01308 } 01309 01310 01311 l_int32 01312 dpixGetResolution(DPIX *dpix, 01313 l_int32 *pxres, 01314 l_int32 *pyres) 01315 { 01316 PROCNAME("dpixGetResolution"); 01317 01318 if (!dpix) 01319 return ERROR_INT("dpix not defined", procName, 1); 01320 if (pxres) *pxres = dpix->xres; 01321 if (pyres) *pyres = dpix->yres; 01322 return 0; 01323 } 01324 01325 01326 l_int32 01327 dpixSetResolution(DPIX *dpix, 01328 l_int32 xres, 01329 l_int32 yres) 01330 { 01331 PROCNAME("dpixSetResolution"); 01332 01333 if (!dpix) 01334 return ERROR_INT("dpix not defined", procName, 1); 01335 01336 dpix->xres = xres; 01337 dpix->yres = yres; 01338 return 0; 01339 } 01340 01341 01342 l_int32 01343 dpixCopyResolution(DPIX *dpixd, 01344 DPIX *dpixs) 01345 { 01346 l_int32 xres, yres; 01347 PROCNAME("dpixCopyResolution"); 01348 01349 if (!dpixs || !dpixd) 01350 return ERROR_INT("dpixs and dpixd not both defined", procName, 1); 01351 01352 dpixGetResolution(dpixs, &xres, &yres); 01353 dpixSetResolution(dpixd, xres, yres); 01354 return 0; 01355 } 01356 01357 01358 l_float64 * 01359 dpixGetData(DPIX *dpix) 01360 { 01361 PROCNAME("dpixGetData"); 01362 01363 if (!dpix) 01364 return (l_float64 *)ERROR_PTR("dpix not defined", procName, NULL); 01365 return dpix->data; 01366 } 01367 01368 01369 l_int32 01370 dpixSetData(DPIX *dpix, 01371 l_float64 *data) 01372 { 01373 PROCNAME("dpixSetData"); 01374 01375 if (!dpix) 01376 return ERROR_INT("dpix not defined", procName, 1); 01377 01378 dpix->data = data; 01379 return 0; 01380 } 01381 01382 01383 /*! 01384 * dpixGetPixel() 01385 * 01386 * Input: dpix 01387 * (x,y) pixel coords 01388 * &val (<return> pixel value) 01389 * Return: 0 if OK; 1 on error 01390 */ 01391 l_int32 01392 dpixGetPixel(DPIX *dpix, 01393 l_int32 x, 01394 l_int32 y, 01395 l_float64 *pval) 01396 { 01397 l_int32 w, h; 01398 01399 PROCNAME("dpixGetPixel"); 01400 01401 if (!pval) 01402 return ERROR_INT("pval not defined", procName, 1); 01403 *pval = 0.0; 01404 if (!dpix) 01405 return ERROR_INT("dpix not defined", procName, 1); 01406 01407 dpixGetDimensions(dpix, &w, &h); 01408 if (x < 0 || x >= w) 01409 return ERROR_INT("x out of bounds", procName, 1); 01410 if (y < 0 || y >= h) 01411 return ERROR_INT("y out of bounds", procName, 1); 01412 01413 *pval = *(dpix->data + y * w + x); 01414 return 0; 01415 } 01416 01417 01418 /*! 01419 * dpixSetPixel() 01420 * 01421 * Input: dpix 01422 * (x,y) pixel coords 01423 * val (pixel value) 01424 * Return: 0 if OK; 1 on error 01425 */ 01426 l_int32 01427 dpixSetPixel(DPIX *dpix, 01428 l_int32 x, 01429 l_int32 y, 01430 l_float64 val) 01431 { 01432 l_int32 w, h; 01433 01434 PROCNAME("dpixSetPixel"); 01435 01436 if (!dpix) 01437 return ERROR_INT("dpix not defined", procName, 1); 01438 01439 dpixGetDimensions(dpix, &w, &h); 01440 if (x < 0 || x >= w) 01441 return ERROR_INT("x out of bounds", procName, 1); 01442 if (y < 0 || y >= h) 01443 return ERROR_INT("y out of bounds", procName, 1); 01444 01445 *(dpix->data + y * w + x) = val; 01446 return 0; 01447 } 01448 01449 01450 /*--------------------------------------------------------------------* 01451 * FPix serialized I/O * 01452 *--------------------------------------------------------------------*/ 01453 /*! 01454 * fpixRead() 01455 * 01456 * Input: filename 01457 * Return: fpix, or null on error 01458 */ 01459 FPIX * 01460 fpixRead(const char *filename) 01461 { 01462 FILE *fp; 01463 FPIX *fpix; 01464 01465 PROCNAME("fpixRead"); 01466 01467 if (!filename) 01468 return (FPIX *)ERROR_PTR("filename not defined", procName, NULL); 01469 if ((fp = fopenReadStream(filename)) == NULL) 01470 return (FPIX *)ERROR_PTR("stream not opened", procName, NULL); 01471 01472 if ((fpix = fpixReadStream(fp)) == NULL) { 01473 fclose(fp); 01474 return (FPIX *)ERROR_PTR("fpix not read", procName, NULL); 01475 } 01476 01477 fclose(fp); 01478 return fpix; 01479 } 01480 01481 01482 /*! 01483 * fpixReadStream() 01484 * 01485 * Input: stream 01486 * Return: fpix, or null on error 01487 */ 01488 FPIX * 01489 fpixReadStream(FILE *fp) 01490 { 01491 l_int32 w, h, nbytes, version; 01492 l_float32 *data; 01493 FPIX *fpix; 01494 01495 PROCNAME("fpixReadStream"); 01496 01497 if (!fp) 01498 return (FPIX *)ERROR_PTR("stream not defined", procName, NULL); 01499 01500 if (fscanf(fp, "\nFPix Version %d\n", &version) != 1) 01501 return (FPIX *)ERROR_PTR("not a fpix file", procName, NULL); 01502 if (version != FPIX_VERSION_NUMBER) 01503 return (FPIX *)ERROR_PTR("invalid fpix version", procName, NULL); 01504 if (fscanf(fp, "w = %d, h = %d, nbytes = %d\n", &w, &h, &nbytes) != 3) 01505 return (FPIX *)ERROR_PTR("read fail for data size", procName, NULL); 01506 01507 if ((fpix = fpixCreate(w, h)) == NULL) 01508 return (FPIX *)ERROR_PTR("fpix not made", procName, NULL); 01509 data = fpixGetData(fpix); 01510 if (fread(data, 1, nbytes, fp) != nbytes) 01511 return (FPIX *)ERROR_PTR("read error for nbytes", procName, NULL); 01512 01513 /* Convert to little-endian if necessary */ 01514 fpixEndianByteSwap(fpix, fpix); 01515 return fpix; 01516 } 01517 01518 01519 /*! 01520 * fpixWrite() 01521 * 01522 * Input: filename 01523 * fpix 01524 * Return: 0 if OK, 1 on error 01525 */ 01526 l_int32 01527 fpixWrite(const char *filename, 01528 FPIX *fpix) 01529 { 01530 FILE *fp; 01531 01532 PROCNAME("fpixWrite"); 01533 01534 if (!filename) 01535 return ERROR_INT("filename not defined", procName, 1); 01536 if (!fpix) 01537 return ERROR_INT("fpix not defined", procName, 1); 01538 01539 if ((fp = fopenWriteStream(filename, "wb")) == NULL) 01540 return ERROR_INT("stream not opened", procName, 1); 01541 if (fpixWriteStream(fp, fpix)) 01542 return ERROR_INT("fpix not written to stream", procName, 1); 01543 fclose(fp); 01544 01545 return 0; 01546 } 01547 01548 01549 /*! 01550 * fpixWriteStream() 01551 * 01552 * Input: stream (opened for "wb") 01553 * fpix 01554 * Return: 0 if OK, 1 on error 01555 */ 01556 l_int32 01557 fpixWriteStream(FILE *fp, 01558 FPIX *fpix) 01559 { 01560 l_int32 w, h, nbytes; 01561 l_float32 *data; 01562 FPIX *fpixt; 01563 01564 PROCNAME("fpixWriteStream"); 01565 01566 if (!fp) 01567 return ERROR_INT("stream not defined", procName, 1); 01568 if (!fpix) 01569 return ERROR_INT("fpix not defined", procName, 1); 01570 01571 /* Convert to little-endian if necessary */ 01572 fpixt = fpixEndianByteSwap(NULL, fpix); 01573 01574 fpixGetDimensions(fpixt, &w, &h); 01575 data = fpixGetData(fpixt); 01576 nbytes = 4 * h * fpixGetWpl(fpixt); 01577 fprintf(fp, "\nFPix Version %d\n", FPIX_VERSION_NUMBER); 01578 fprintf(fp, "w = %d, h = %d, nbytes = %d\n", w, h, nbytes); 01579 fwrite(data, 1, nbytes, fp); 01580 01581 fpixDestroy(&fpixt); 01582 return 0; 01583 } 01584 01585 01586 /*! 01587 * fpixEndianByteSwap() 01588 * 01589 * Input: fpixd (can be equal to fpixs or NULL) 01590 * fpixs 01591 * Return: fpixd always 01592 * 01593 * Notes: 01594 * (1) On big-endian hardware, this does byte-swapping on each of 01595 * the 4-byte floats in the fpix data. On little-endians, 01596 * the data is unchanged. This is used for serialization 01597 * of fpix; the data is serialized in little-endian byte 01598 * order because most hardware is little-endian. 01599 * (2) The operation can be either in-place or, if fpixd == NULL, 01600 * a new fpix is made. If not in-place, caller must catch 01601 * the returned pointer. 01602 */ 01603 FPIX * 01604 fpixEndianByteSwap(FPIX *fpixd, 01605 FPIX *fpixs) 01606 { 01607 PROCNAME("fpixEndianByteSwap"); 01608 01609 if (!fpixs) 01610 return (FPIX *)ERROR_PTR("fpixs not defined", procName, fpixd); 01611 if (fpixd && (fpixs != fpixd)) 01612 return (FPIX *)ERROR_PTR("fpixd != fpixs", procName, fpixd); 01613 01614 #ifdef L_BIG_ENDIAN 01615 { 01616 l_uint32 *data; 01617 l_int32 i, j, w, h; 01618 l_uint32 word; 01619 01620 fpixGetDimensions(fpixs, &w, &h); 01621 fpixd = fpixCopy(fpixd, fpixs); /* no copy if fpixd == fpixs */ 01622 01623 data = (l_uint32 *)fpixGetData(fpixd); 01624 for (i = 0; i < h; i++) { 01625 for (j = 0; j < w; j++, data++) { 01626 word = *data; 01627 *data = (word >> 24) | 01628 ((word >> 8) & 0x0000ff00) | 01629 ((word << 8) & 0x00ff0000) | 01630 (word << 24); 01631 } 01632 } 01633 return fpixd; 01634 } 01635 #else /* L_LITTLE_ENDIAN */ 01636 01637 if (fpixd) 01638 return fpixd; /* no-op */ 01639 else 01640 return fpixClone(fpixs); 01641 01642 #endif /* L_BIG_ENDIAN */ 01643 } 01644 01645 01646 /*--------------------------------------------------------------------* 01647 * DPix serialized I/O * 01648 *--------------------------------------------------------------------*/ 01649 /*! 01650 * dpixRead() 01651 * 01652 * Input: filename 01653 * Return: dpix, or null on error 01654 */ 01655 DPIX * 01656 dpixRead(const char *filename) 01657 { 01658 FILE *fp; 01659 DPIX *dpix; 01660 01661 PROCNAME("dpixRead"); 01662 01663 if (!filename) 01664 return (DPIX *)ERROR_PTR("filename not defined", procName, NULL); 01665 if ((fp = fopenReadStream(filename)) == NULL) 01666 return (DPIX *)ERROR_PTR("stream not opened", procName, NULL); 01667 01668 if ((dpix = dpixReadStream(fp)) == NULL) { 01669 fclose(fp); 01670 return (DPIX *)ERROR_PTR("dpix not read", procName, NULL); 01671 } 01672 01673 fclose(fp); 01674 return dpix; 01675 } 01676 01677 01678 /*! 01679 * dpixReadStream() 01680 * 01681 * Input: stream 01682 * Return: dpix, or null on error 01683 */ 01684 DPIX * 01685 dpixReadStream(FILE *fp) 01686 { 01687 l_int32 w, h, nbytes, version; 01688 l_float64 *data; 01689 DPIX *dpix; 01690 01691 PROCNAME("dpixReadStream"); 01692 01693 if (!fp) 01694 return (DPIX *)ERROR_PTR("stream not defined", procName, NULL); 01695 01696 if (fscanf(fp, "\nDPix Version %d\n", &version) != 1) 01697 return (DPIX *)ERROR_PTR("not a dpix file", procName, NULL); 01698 if (version != DPIX_VERSION_NUMBER) 01699 return (DPIX *)ERROR_PTR("invalid dpix version", procName, NULL); 01700 if (fscanf(fp, "w = %d, h = %d, nbytes = %d\n", &w, &h, &nbytes) != 3) 01701 return (DPIX *)ERROR_PTR("read fail for data size", procName, NULL); 01702 01703 if ((dpix = dpixCreate(w, h)) == NULL) 01704 return (DPIX *)ERROR_PTR("dpix not made", procName, NULL); 01705 data = dpixGetData(dpix); 01706 if (fread(data, 1, nbytes, fp) != nbytes) 01707 return (DPIX *)ERROR_PTR("read error for nbytes", procName, NULL); 01708 01709 /* Convert to little-endian if necessary */ 01710 dpixEndianByteSwap(dpix, dpix); 01711 return dpix; 01712 } 01713 01714 01715 /*! 01716 * dpixWrite() 01717 * 01718 * Input: filename 01719 * dpix 01720 * Return: 0 if OK, 1 on error 01721 */ 01722 l_int32 01723 dpixWrite(const char *filename, 01724 DPIX *dpix) 01725 { 01726 FILE *fp; 01727 01728 PROCNAME("dpixWrite"); 01729 01730 if (!filename) 01731 return ERROR_INT("filename not defined", procName, 1); 01732 if (!dpix) 01733 return ERROR_INT("dpix not defined", procName, 1); 01734 01735 if ((fp = fopenWriteStream(filename, "wb")) == NULL) 01736 return ERROR_INT("stream not opened", procName, 1); 01737 if (dpixWriteStream(fp, dpix)) 01738 return ERROR_INT("dpix not written to stream", procName, 1); 01739 fclose(fp); 01740 01741 return 0; 01742 } 01743 01744 01745 /*! 01746 * dpixWriteStream() 01747 * 01748 * Input: stream (opened for "wb") 01749 * dpix 01750 * Return: 0 if OK, 1 on error 01751 */ 01752 l_int32 01753 dpixWriteStream(FILE *fp, 01754 DPIX *dpix) 01755 { 01756 l_int32 w, h, nbytes; 01757 l_float64 *data; 01758 DPIX *dpixt; 01759 01760 PROCNAME("dpixWriteStream"); 01761 01762 if (!fp) 01763 return ERROR_INT("stream not defined", procName, 1); 01764 if (!dpix) 01765 return ERROR_INT("dpix not defined", procName, 1); 01766 01767 /* Convert to little-endian if necessary */ 01768 dpixt = dpixEndianByteSwap(NULL, dpix); 01769 01770 dpixGetDimensions(dpixt, &w, &h); 01771 data = dpixGetData(dpixt); 01772 nbytes = 8 * h * dpixGetWpl(dpixt); 01773 fprintf(fp, "\nDPix Version %d\n", DPIX_VERSION_NUMBER); 01774 fprintf(fp, "w = %d, h = %d, nbytes = %d\n", w, h, nbytes); 01775 fwrite(data, 1, nbytes, fp); 01776 01777 dpixDestroy(&dpixt); 01778 return 0; 01779 } 01780 01781 01782 /*! 01783 * dpixEndianByteSwap() 01784 * 01785 * Input: dpixd (can be equal to dpixs or NULL) 01786 * dpixs 01787 * Return: dpixd always 01788 * 01789 * Notes: 01790 * (1) On big-endian hardware, this does byte-swapping on each of 01791 * the 4-byte words in the dpix data. On little-endians, 01792 * the data is unchanged. This is used for serialization 01793 * of dpix; the data is serialized in little-endian byte 01794 * order because most hardware is little-endian. 01795 * (2) The operation can be either in-place or, if dpixd == NULL, 01796 * a new dpix is made. If not in-place, caller must catch 01797 * the returned pointer. 01798 */ 01799 DPIX * 01800 dpixEndianByteSwap(DPIX *dpixd, 01801 DPIX *dpixs) 01802 { 01803 PROCNAME("dpixEndianByteSwap"); 01804 01805 if (!dpixs) 01806 return (DPIX *)ERROR_PTR("dpixs not defined", procName, dpixd); 01807 if (dpixd && (dpixs != dpixd)) 01808 return (DPIX *)ERROR_PTR("dpixd != dpixs", procName, dpixd); 01809 01810 #ifdef L_BIG_ENDIAN 01811 { 01812 l_uint32 *data; 01813 l_int32 i, j, w, h; 01814 l_uint32 word; 01815 01816 dpixGetDimensions(dpixs, &w, &h); 01817 dpixd = dpixCopy(dpixd, dpixs); /* no copy if dpixd == dpixs */ 01818 01819 data = (l_uint32 *)dpixGetData(dpixd); 01820 for (i = 0; i < h; i++) { 01821 for (j = 0; j < 2 * w; j++, data++) { 01822 word = *data; 01823 *data = (word >> 24) | 01824 ((word >> 8) & 0x0000ff00) | 01825 ((word << 8) & 0x00ff0000) | 01826 (word << 24); 01827 } 01828 } 01829 return dpixd; 01830 } 01831 #else /* L_LITTLE_ENDIAN */ 01832 01833 if (dpixd) 01834 return dpixd; /* no-op */ 01835 else 01836 return dpixClone(dpixs); 01837 01838 #endif /* L_BIG_ENDIAN */ 01839 } 01840 01841 01842 /*--------------------------------------------------------------------* 01843 * Print FPix (subsampled, for debugging) * 01844 *--------------------------------------------------------------------*/ 01845 /*! 01846 * fpixPrintStream() 01847 * 01848 * Input: stream 01849 * fpix 01850 * factor (subsampled) 01851 * Return: 0 if OK, 1 on error 01852 * 01853 * Notes: 01854 * (1) Subsampled printout of fpix for debugging. 01855 */ 01856 l_int32 01857 fpixPrintStream(FILE *fp, 01858 FPIX *fpix, 01859 l_int32 factor) 01860 { 01861 l_int32 i, j, w, h, count; 01862 l_float32 val; 01863 01864 PROCNAME("fpixPrintStream"); 01865 01866 if (!fp) 01867 return ERROR_INT("stream not defined", procName, 1); 01868 if (!fpix) 01869 return ERROR_INT("fpix not defined", procName, 1); 01870 if (factor < 1) 01871 return ERROR_INT("sampling factor < 1f", procName, 1); 01872 01873 fpixGetDimensions(fpix, &w, &h); 01874 fprintf(fp, "\nFPix: w = %d, h = %d\n", w, h); 01875 for (i = 0; i < h; i += factor) { 01876 for (count = 0, j = 0; j < w; j += factor, count++) { 01877 fpixGetPixel(fpix, j, i, &val); 01878 fprintf(fp, "val[%d, %d] = %f ", i, j, val); 01879 if ((count + 1) % 3 == 0) fprintf(fp, "\n"); 01880 } 01881 if (count % 3) fprintf(fp, "\n"); 01882 } 01883 fprintf(fp, "\n"); 01884 return 0; 01885 } 01886