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 * pix1.c 00018 * 00019 * The pixN.c {N = 1,2,3,4,5} files are sorted by the type of operation. 00020 * The primary functions in these files are: 00021 * 00022 * pix1.c: constructors, destructors and field accessors 00023 * pix2.c: pixel poking of image, pad and border pixels 00024 * pix3.c: masking and logical ops, counting, mirrored tiling 00025 * pix4.c: histograms, statistics, fg/bg estimation 00026 * pix5.c: property measurements, rectangle extraction 00027 * 00028 * 00029 * This file has the basic constructors, destructors and field accessors 00030 * 00031 * Pix memory management (allows custom allocator and deallocator) 00032 * static void *pix_malloc() 00033 * static void pix_free() 00034 * void setPixMemoryManager() 00035 * 00036 * Pix creation 00037 * PIX *pixCreate() 00038 * PIX *pixCreateNoInit() 00039 * PIX *pixCreateTemplate() 00040 * PIX *pixCreateTemplateNoInit() 00041 * PIX *pixCreateHeader() 00042 * PIX *pixClone() 00043 * 00044 * Pix destruction 00045 * void pixDestroy() 00046 * static void pixFree() 00047 * 00048 * Pix copy 00049 * PIX *pixCopy() 00050 * l_int32 pixResizeImageData() 00051 * l_int32 pixCopyColormap() 00052 * l_int32 pixSizesEqual() 00053 * l_int32 pixTransferAllData() 00054 * 00055 * Pix accessors 00056 * l_int32 pixGetWidth() 00057 * l_int32 pixSetWidth() 00058 * l_int32 pixGetHeight() 00059 * l_int32 pixSetHeight() 00060 * l_int32 pixGetDepth() 00061 * l_int32 pixSetDepth() 00062 * l_int32 pixGetDimensions() 00063 * l_int32 pixSetDimensions() 00064 * l_int32 pixCopyDimensions() 00065 * l_int32 pixGetWpl() 00066 * l_int32 pixSetWpl() 00067 * l_int32 pixGetRefcount() 00068 * l_int32 pixChangeRefcount() 00069 * l_uint32 pixGetXRes() 00070 * l_int32 pixSetXRes() 00071 * l_uint32 pixGetYRes() 00072 * l_int32 pixSetYRes() 00073 * l_int32 pixGetResolution() 00074 * l_int32 pixSetResolution() 00075 * l_int32 pixCopyResolution() 00076 * l_int32 pixScaleResolution() 00077 * l_int32 pixGetInputFormat() 00078 * l_int32 pixSetInputFormat() 00079 * l_int32 pixCopyInputFormat() 00080 * char *pixGetText() 00081 * l_int32 pixSetText() 00082 * l_int32 pixAddText() 00083 * l_int32 pixCopyText() 00084 * PIXCMAP *pixGetColormap() 00085 * l_int32 pixSetColormap() 00086 * l_int32 pixDestroyColormap() 00087 * l_uint32 *pixGetData() 00088 * l_int32 pixSetData() 00089 * l_uint32 *pixExtractData() 00090 * l_int32 pixFreeData() 00091 * 00092 * Pix line ptrs 00093 * void **pixGetLinePtrs() 00094 * 00095 * Pix debug 00096 * l_int32 pixPrintStreamInfo() 00097 * 00098 * 00099 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00100 * Important notes on direct management of pix image data 00101 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 00102 * 00103 * Custom allocator and deallocator 00104 * -------------------------------- 00105 * 00106 * At the lowest level, you can specify the function that does the 00107 * allocation and deallocation of the data field in the pix. 00108 * By default, this is malloc and free. However, by calling 00109 * setPixMemoryManager(), custom functions can be substituted. 00110 * When using this, keep two things in mind: 00111 * 00112 * (1) Call setPixMemoryManager() before any pix have been allocated 00113 * (2) Destroy all pix as usual, in order to prevent leaks. 00114 * 00115 * In pixalloc.c, we provide an example custom allocator and deallocator. 00116 * To use it, you must call pmsCreate() before any pix have been allocated 00117 * and pmsDestroy() at the end after all pix have been destroyed. 00118 * 00119 * 00120 * Direct manipulation of the pix data field 00121 * ----------------------------------------- 00122 * 00123 * Memory management of the (image) data field in the pix is 00124 * handled differently from that in the colormap or text fields. 00125 * For colormap and text, the functions pixSetColormap() and 00126 * pixSetText() remove the existing heap data and insert the 00127 * new data. For the image data, pixSetData() just reassigns the 00128 * data field; any existing data will be lost if there isn't 00129 * another handle for it. 00130 * 00131 * Why is pixSetData() limited in this way? Because the image 00132 * data can be very large, we need flexible ways to handle it, 00133 * particularly when you want to re-use the data in a different 00134 * context without making a copy. Here are some different 00135 * things you might want to do: 00136 * 00137 * (1) Use pixCopy(pixd, pixs) where pixd is not the same size 00138 * as pixs. This will remove the data in pixd, allocate a 00139 * new data field in pixd, and copy the data from pixs, leaving 00140 * pixs unchanged. 00141 * 00142 * (2) Use pixTransferAllData(pixd, &pixs, ...) to transfer the 00143 * data from pixs to pixd without making a copy of it. If 00144 * pixs is not cloned, this will do the transfer and destroy pixs. 00145 * But if the refcount of pixs is greater than 1, it just copies 00146 * the data and decrements the ref count. 00147 * 00148 * (3) Use pixExtractData() to extract the image data from the pix 00149 * without copying if possible. This could be used, for example, 00150 * to convert from a pix to some other data structure with minimal 00151 * heap allocation. After the data is extracated, the pixels can 00152 * be munged and used in another context. However, the danger 00153 * here is that the pix might have a refcount > 1, in which case 00154 * a copy of the data must be made and the input pix left unchanged. 00155 * If there are no clones, the image data can be extracted without 00156 * a copy, and the data ptr in the pix must be nulled before 00157 * destroying it because the pix will no longer 'own' the data. 00158 * 00159 * We have provided accessors and functions here that should be 00160 * sufficient so that you can do anything you want without 00161 * explicitly referencing any of the pix member fields. 00162 * 00163 * However, to avoid memory smashes and leaks when doing special operations 00164 * on the pix data field, look carefully at the behavior of the image 00165 * data accessors and keep in mind that when you invoke pixDestroy(), 00166 * the pix considers itself the owner of all its heap data. 00167 */ 00168 00169 #include <stdio.h> 00170 #include <stdlib.h> 00171 #include <string.h> 00172 #include "allheaders.h" 00173 00174 static void pixFree(PIX *pix); 00175 00176 00177 /*-------------------------------------------------------------------------* 00178 * Pix Memory Management * 00179 * * 00180 * These functions give you the freedom to specify at compile or run * 00181 * time the allocator and deallocator to be used for pix. It has no * 00182 * effect on memory management for other data structs, which are * 00183 * controlled by the #defines in environ.h. Likewise, the #defines * 00184 * in environ.h have no effect on the pix memory management. * 00185 * The default functions are malloc and free. Use setPixMemoryManager() * 00186 * to specify other functions to use. * 00187 *-------------------------------------------------------------------------*/ 00188 struct PixMemoryManager 00189 { 00190 void *(*allocator)(size_t); 00191 void (*deallocator)(void *); 00192 }; 00193 00194 static struct PixMemoryManager pix_mem_manager = { 00195 &malloc, 00196 &free 00197 }; 00198 00199 static void * 00200 pix_malloc(size_t size) 00201 { 00202 #ifndef _MSC_VER 00203 return (*pix_mem_manager.allocator)(size); 00204 #else /* _MSC_VER */ 00205 /* Under MSVC++, pix_mem_manager is initialized after a call 00206 * to pix_malloc. Just ignore the custom allocator feature. */ 00207 return malloc(size); 00208 #endif /* _MSC_VER */ 00209 } 00210 00211 static void 00212 pix_free(void *ptr) 00213 { 00214 #ifndef _MSC_VER 00215 (*pix_mem_manager.deallocator)(ptr); 00216 return; 00217 #else /* _MSC_VER */ 00218 /* Under MSVC++, pix_mem_manager is initialized after a call 00219 * to pix_malloc. Just ignore the custom allocator feature. */ 00220 free(ptr); 00221 return; 00222 #endif /* _MSC_VER */ 00223 } 00224 00225 /*! 00226 * setPixMemoryManager() 00227 * 00228 * Input: allocator (<optional>; use null to skip) 00229 * deallocator (<optional>; use null to skip) 00230 * Return: void 00231 * 00232 * Notes: 00233 * (1) Use this to change the alloc and/or dealloc functions; 00234 * e.g., setPixMemoryManager(my_malloc, my_free). 00235 */ 00236 #ifndef _MSC_VER 00237 void 00238 setPixMemoryManager(void *(allocator(size_t)), 00239 void (deallocator(void *))) 00240 { 00241 if (allocator) pix_mem_manager.allocator = allocator; 00242 if (deallocator) pix_mem_manager.deallocator = deallocator; 00243 return; 00244 } 00245 #else /* _MSC_VER */ 00246 /* MSVC++ wants type (*fun)(types...) syntax */ 00247 void 00248 setPixMemoryManager(void *((*allocator)(size_t)), 00249 void ((*deallocator)(void *))) 00250 { 00251 if (allocator) pix_mem_manager.allocator = allocator; 00252 if (deallocator) pix_mem_manager.deallocator = deallocator; 00253 return; 00254 } 00255 #endif /* _MSC_VER */ 00256 00257 00258 /*--------------------------------------------------------------------* 00259 * Pix Creation * 00260 *--------------------------------------------------------------------*/ 00261 /*! 00262 * pixCreate() 00263 * 00264 * Input: width, height, depth 00265 * Return: pixd (with data allocated and initialized to 0), 00266 * or null on error 00267 */ 00268 PIX * 00269 pixCreate(l_int32 width, 00270 l_int32 height, 00271 l_int32 depth) 00272 { 00273 PIX *pixd; 00274 00275 PROCNAME("pixCreate"); 00276 00277 if ((pixd = pixCreateNoInit(width, height, depth)) == NULL) 00278 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00279 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h); 00280 return pixd; 00281 } 00282 00283 00284 /*! 00285 * pixCreateNoInit() 00286 * 00287 * Input: width, height, depth 00288 * Return: pixd (with data allocated but not initialized), 00289 * or null on error 00290 * 00291 * Notes: 00292 * (1) Must set pad bits to avoid reading unitialized data, because 00293 * some optimized routines (e.g., pixConnComp()) read from pad bits. 00294 */ 00295 PIX * 00296 pixCreateNoInit(l_int32 width, 00297 l_int32 height, 00298 l_int32 depth) 00299 { 00300 l_int32 wpl; 00301 PIX *pixd; 00302 l_uint32 *data; 00303 00304 PROCNAME("pixCreateNoInit"); 00305 if ((pixd = pixCreateHeader(width, height, depth)) == NULL) 00306 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00307 wpl = pixGetWpl(pixd); 00308 if ((data = (l_uint32 *)pix_malloc(4 * wpl * height)) == NULL) 00309 return (PIX *)ERROR_PTR("pix_malloc fail for data", procName, NULL); 00310 pixSetData(pixd, data); 00311 pixSetPadBits(pixd, 0); 00312 return pixd; 00313 } 00314 00315 00316 /*! 00317 * pixCreateTemplate() 00318 * 00319 * Input: pixs 00320 * Return: pixd, or null on error 00321 * 00322 * Notes: 00323 * (1) Makes a Pix of the same size as the input Pix, with the 00324 * data array allocated and initialized to 0. 00325 * (2) Copies the other fields, including colormap if it exists. 00326 */ 00327 PIX * 00328 pixCreateTemplate(PIX *pixs) 00329 { 00330 PIX *pixd; 00331 00332 PROCNAME("pixCreateTemplate"); 00333 00334 if (!pixs) 00335 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00336 00337 if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL) 00338 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00339 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h); 00340 return pixd; 00341 } 00342 00343 00344 /*! 00345 * pixCreateTemplateNoInit() 00346 * 00347 * Input: pixs 00348 * Return: pixd, or null on error 00349 * 00350 * Notes: 00351 * (1) Makes a Pix of the same size as the input Pix, with 00352 * the data array allocated but not initialized to 0. 00353 * (2) Copies the other fields, including colormap if it exists. 00354 */ 00355 PIX * 00356 pixCreateTemplateNoInit(PIX *pixs) 00357 { 00358 l_int32 w, h, d; 00359 PIX *pixd; 00360 00361 PROCNAME("pixCreateTemplateNoInit"); 00362 00363 if (!pixs) 00364 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00365 00366 pixGetDimensions(pixs, &w, &h, &d); 00367 if ((pixd = pixCreateNoInit(w, h, d)) == NULL) 00368 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00369 pixCopyResolution(pixd, pixs); 00370 pixCopyColormap(pixd, pixs); 00371 pixCopyText(pixd, pixs); 00372 pixCopyInputFormat(pixd, pixs); 00373 00374 return pixd; 00375 } 00376 00377 00378 /*! 00379 * pixCreateHeader() 00380 * 00381 * Input: width, height, depth 00382 * Return: pixd (with no data allocated), or null on error 00383 */ 00384 PIX * 00385 pixCreateHeader(l_int32 width, 00386 l_int32 height, 00387 l_int32 depth) 00388 { 00389 l_int32 wpl; 00390 PIX *pixd; 00391 00392 PROCNAME("pixCreateHeader"); 00393 00394 if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) 00395 && (depth != 16) && (depth != 24) && (depth != 32)) 00396 return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}", 00397 procName, NULL); 00398 if (width <= 0) 00399 return (PIX *)ERROR_PTR("width must be > 0", procName, NULL); 00400 if (height <= 0) 00401 return (PIX *)ERROR_PTR("height must be > 0", procName, NULL); 00402 00403 if ((pixd = (PIX *)CALLOC(1, sizeof(PIX))) == NULL) 00404 return (PIX *)ERROR_PTR("CALLOC fail for pixd", procName, NULL); 00405 pixSetWidth(pixd, width); 00406 pixSetHeight(pixd, height); 00407 pixSetDepth(pixd, depth); 00408 wpl = (width * depth + 31) / 32; 00409 pixSetWpl(pixd, wpl); 00410 00411 pixd->refcount = 1; 00412 pixd->informat = IFF_UNKNOWN; 00413 return pixd; 00414 } 00415 00416 00417 /*! 00418 * pixClone() 00419 * 00420 * Input: pix 00421 * Return: same pix (ptr), or null on error 00422 * 00423 * Notes: 00424 * (1) A "clone" is simply a handle (ptr) to an existing pix. 00425 * It is implemented because (a) images can be large and 00426 * hence expensive to copy, and (b) extra handles to a data 00427 * structure need to be made with a simple policy to avoid 00428 * both double frees and memory leaks. Pix are reference 00429 * counted. The side effect of pixClone() is an increase 00430 * by 1 in the ref count. 00431 * (2) The protocol to be used is: 00432 * (a) Whenever you want a new handle to an existing image, 00433 * call pixClone(), which just bumps a ref count. 00434 * (b) Always call pixDestroy() on all handles. This 00435 * decrements the ref count, nulls the handle, and 00436 * only destroys the pix when pixDestroy() has been 00437 * called on all handles. 00438 */ 00439 PIX * 00440 pixClone(PIX *pixs) 00441 { 00442 PROCNAME("pixClone"); 00443 00444 if (!pixs) 00445 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00446 pixChangeRefcount(pixs, 1); 00447 00448 return pixs; 00449 } 00450 00451 00452 /*--------------------------------------------------------------------* 00453 * Pix Destruction * 00454 *--------------------------------------------------------------------*/ 00455 /*! 00456 * pixDestroy() 00457 * 00458 * Input: &pix <will be nulled> 00459 * Return: void 00460 * 00461 * Notes: 00462 * (1) Decrements the ref count and, if 0, destroys the pix. 00463 * (2) Always nulls the input ptr. 00464 */ 00465 void 00466 pixDestroy(PIX **ppix) 00467 { 00468 PIX *pix; 00469 00470 PROCNAME("pixDestroy"); 00471 00472 if (!ppix) { 00473 L_WARNING("ptr address is null!", procName); 00474 return; 00475 } 00476 00477 if ((pix = *ppix) == NULL) 00478 return; 00479 00480 pixFree(pix); 00481 *ppix = NULL; 00482 return; 00483 } 00484 00485 00486 /*! 00487 * pixFree() 00488 * 00489 * Input: pix 00490 * Return: void 00491 * 00492 * Notes: 00493 * (1) Decrements the ref count and, if 0, destroys the pix. 00494 */ 00495 static void 00496 pixFree(PIX *pix) 00497 { 00498 l_uint32 *data; 00499 char *text; 00500 00501 if (!pix) return; 00502 00503 pixChangeRefcount(pix, -1); 00504 if (pixGetRefcount(pix) <= 0) { 00505 if ((data = pixGetData(pix)) != NULL) 00506 pix_free(data); 00507 if ((text = pixGetText(pix)) != NULL) 00508 FREE(text); 00509 pixDestroyColormap(pix); 00510 FREE(pix); 00511 } 00512 return; 00513 } 00514 00515 00516 /*-------------------------------------------------------------------------* 00517 * Pix Copy * 00518 *-------------------------------------------------------------------------*/ 00519 /*! 00520 * pixCopy() 00521 * 00522 * Input: pixd (<optional>; can be null, or equal to pixs, 00523 * or different from pixs) 00524 * pixs 00525 * Return: pixd, or null on error 00526 * 00527 * Notes: 00528 * (1) There are three cases: 00529 * (a) pixd == null (makes a new pix; refcount = 1) 00530 * (b) pixd == pixs (no-op) 00531 * (c) pixd != pixs (data copy; no change in refcount) 00532 * If the refcount of pixd > 1, case (c) will side-effect 00533 * these handles. 00534 * (2) The general pattern of use is: 00535 * pixd = pixCopy(pixd, pixs); 00536 * This will work for all three cases. 00537 * For clarity when the case is known, you can use: 00538 * (a) pixd = pixCopy(NULL, pixs); 00539 * (c) pixCopy(pixd, pixs); 00540 * (3) For case (c), we check if pixs and pixd are the same 00541 * size (w,h,d). If so, the data is copied directly. 00542 * Otherwise, the data is reallocated to the correct size 00543 * and the copy proceeds. The refcount of pixd is unchanged. 00544 * (4) This operation, like all others that may involve a pre-existing 00545 * pixd, will side-effect any existing clones of pixd. 00546 */ 00547 PIX * 00548 pixCopy(PIX *pixd, /* can be null */ 00549 PIX *pixs) 00550 { 00551 l_int32 bytes; 00552 l_uint32 *datas, *datad; 00553 00554 PROCNAME("pixCopy"); 00555 00556 if (!pixs) 00557 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00558 if (pixs == pixd) 00559 return pixd; 00560 00561 /* Total bytes in image data */ 00562 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); 00563 00564 /* If we're making a new pix ... */ 00565 if (!pixd) { 00566 if ((pixd = pixCreateTemplate(pixs)) == NULL) 00567 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00568 datas = pixGetData(pixs); 00569 datad = pixGetData(pixd); 00570 memcpy((char *)datad, (char *)datas, bytes); 00571 return pixd; 00572 } 00573 00574 /* Reallocate image data if sizes are different */ 00575 if (pixResizeImageData(pixd, pixs) == 1) 00576 return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL); 00577 00578 /* Copy non-image data fields */ 00579 pixCopyColormap(pixd, pixs); 00580 pixCopyResolution(pixd, pixs); 00581 pixCopyInputFormat(pixd, pixs); 00582 pixCopyText(pixd, pixs); 00583 00584 /* Copy image data */ 00585 datas = pixGetData(pixs); 00586 datad = pixGetData(pixd); 00587 memcpy((char*)datad, (char*)datas, bytes); 00588 return pixd; 00589 } 00590 00591 00592 /*! 00593 * pixResizeImageData() 00594 * 00595 * Input: pixd (gets new uninitialized buffer for image data) 00596 * pixs (determines the size of the buffer; not changed) 00597 * Return: 0 if OK, 1 on error 00598 * 00599 * Notes: 00600 * (1) This removes any existing image data from pixd and 00601 * allocates an uninitialized buffer that will hold the 00602 * amount of image data that is in pixs. 00603 */ 00604 l_int32 00605 pixResizeImageData(PIX *pixd, 00606 PIX *pixs) 00607 { 00608 l_int32 w, h, d, wpl, bytes; 00609 l_uint32 *data; 00610 00611 PROCNAME("pixResizeImageData"); 00612 00613 if (!pixs) 00614 return ERROR_INT("pixs not defined", procName, 1); 00615 if (!pixd) 00616 return ERROR_INT("pixd not defined", procName, 1); 00617 00618 if (pixSizesEqual(pixs, pixd)) /* nothing to do */ 00619 return 0; 00620 00621 pixGetDimensions(pixs, &w, &h, &d); 00622 wpl = pixGetWpl(pixs); 00623 pixSetWidth(pixd, w); 00624 pixSetHeight(pixd, h); 00625 pixSetDepth(pixd, d); 00626 pixSetWpl(pixd, wpl); 00627 bytes = 4 * wpl * h; 00628 pixFreeData(pixd); /* free any existing image data */ 00629 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL) 00630 return ERROR_INT("pix_malloc fail for data", procName, 1); 00631 pixSetData(pixd, data); 00632 return 0; 00633 } 00634 00635 00636 /*! 00637 * pixCopyColormap() 00638 * 00639 * Input: src and dest Pix 00640 * Return: 0 if OK, 1 on error 00641 * 00642 * Notes: 00643 * (1) This always destroys any colormap in pixd (except if 00644 * the operation is a no-op. 00645 */ 00646 l_int32 00647 pixCopyColormap(PIX *pixd, 00648 PIX *pixs) 00649 { 00650 PIXCMAP *cmaps, *cmapd; 00651 00652 PROCNAME("pixCopyColormap"); 00653 00654 if (!pixs) 00655 return ERROR_INT("pixs not defined", procName, 1); 00656 if (!pixd) 00657 return ERROR_INT("pixd not defined", procName, 1); 00658 if (pixs == pixd) 00659 return 0; /* no-op */ 00660 00661 pixDestroyColormap(pixd); 00662 if ((cmaps = pixGetColormap(pixs)) == NULL) /* not an error */ 00663 return 0; 00664 00665 if ((cmapd = pixcmapCopy(cmaps)) == NULL) 00666 return ERROR_INT("cmapd not made", procName, 1); 00667 pixSetColormap(pixd, cmapd); 00668 00669 return 0; 00670 } 00671 00672 00673 /*! 00674 * pixSizesEqual() 00675 * 00676 * Input: two pix 00677 * Return: 1 if the two pix have same {h, w, d}; 0 otherwise. 00678 */ 00679 l_int32 00680 pixSizesEqual(PIX *pix1, 00681 PIX *pix2) 00682 { 00683 PROCNAME("pixSizesEqual"); 00684 00685 if (!pix1 || !pix2) 00686 return ERROR_INT("pix1 and pix2 not both defined", procName, 0); 00687 00688 if (pix1 == pix2) 00689 return 1; 00690 00691 if ((pixGetWidth(pix1) != pixGetWidth(pix2)) || 00692 (pixGetHeight(pix1) != pixGetHeight(pix2)) || 00693 (pixGetDepth(pix1) != pixGetDepth(pix2))) 00694 return 0; 00695 else 00696 return 1; 00697 } 00698 00699 00700 /*! 00701 * pixTransferAllData() 00702 * 00703 * Input: pixd (must be different from pixs) 00704 * &pixs (will be nulled if refcount goes to 0) 00705 * copytext (1 to copy the text field; 0 to skip) 00706 * copyformat (1 to copy the informat field; 0 to skip) 00707 * Return: 0 if OK, 1 on error 00708 * 00709 * Notes: 00710 * (1) This does a complete data transfer from pixs to pixd, 00711 * followed by the destruction of pixs (refcount permitting). 00712 * (2) If the refcount of pixs is 1, pixs is destroyed. Otherwise, 00713 * the data in pixs is copied (rather than transferred) to pixd. 00714 * (3) This operation, like all others with a pre-existing pixd, 00715 * will side-effect any existing clones of pixd. The pixd 00716 * refcount does not change. 00717 * (4) When might you use this? Suppose you have an in-place Pix 00718 * function (returning void) with the typical signature: 00719 * void function-inplace(PIX *pix, ...) 00720 * where "..." are non-pointer input parameters, and suppose 00721 * further that you sometimes want to return an arbitrary Pix 00722 * in place of the input Pix. There are two ways you can do this: 00723 * (a) The straightforward way is to change the function 00724 * signature to take the address of the Pix ptr: 00725 * void function-inplace(PIX **ppix, ...) { 00726 * PIX *pixt = function-makenew(*ppix); 00727 * pixDestroy(ppix); 00728 * *ppix = pixt; 00729 * return; 00730 * } 00731 * Here, the input and returned pix are different, as viewed 00732 * by the calling function, and the inplace function is 00733 * expected to destroy the input pix to avoid a memory leak. 00734 * (b) Keep the signature the same and use pixTransferAllData() 00735 * to return the new Pix in the input Pix struct: 00736 * void function-inplace(PIX *pix, ...) { 00737 * PIX *pixt = function-makenew(pix); 00738 * pixTransferAllData(pix, &pixt, 0, 0); 00739 * // pixDestroy() is called on pixt 00740 * return; 00741 * } 00742 * Here, the input and returned pix are the same, as viewed 00743 * by the calling function, and the inplace function must 00744 * never destroy the input pix, because the calling function 00745 * maintains an unchanged handle to it. 00746 */ 00747 l_int32 00748 pixTransferAllData(PIX *pixd, 00749 PIX **ppixs, 00750 l_int32 copytext, 00751 l_int32 copyformat) 00752 { 00753 l_int32 nbytes; 00754 PIX *pixs; 00755 00756 PROCNAME("pixTransferAllData"); 00757 00758 if (!ppixs) 00759 return ERROR_INT("&pixs not defined", procName, 1); 00760 if ((pixs = *ppixs) == NULL) 00761 return ERROR_INT("pixs not defined", procName, 1); 00762 if (!pixd) 00763 return ERROR_INT("pixd not defined", procName, 1); 00764 if (pixs == pixd) /* no-op */ 00765 return ERROR_INT("pixd == pixs", procName, 1); 00766 00767 if (pixGetRefcount(pixs) == 1) { /* transfer the data, cmap, text */ 00768 pixFreeData(pixd); /* dealloc any existing data */ 00769 pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */ 00770 pixs->data = NULL; /* pixs no longer owns data */ 00771 pixSetColormap(pixd, pixGetColormap(pixs)); /* frees old; sets new */ 00772 pixs->colormap = NULL; /* pixs no longer owns colormap */ 00773 if (copytext) { 00774 pixSetText(pixd, pixGetText(pixs)); 00775 pixSetText(pixs, NULL); 00776 } 00777 } else { /* preserve pixs by making a copy of the data, cmap, text */ 00778 pixResizeImageData(pixd, pixs); 00779 nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); 00780 memcpy((char *)pixGetData(pixd), (char *)pixGetData(pixs), nbytes); 00781 pixCopyColormap(pixd, pixs); 00782 if (copytext) 00783 pixCopyText(pixd, pixs); 00784 } 00785 00786 pixCopyResolution(pixd, pixs); 00787 pixCopyDimensions(pixd, pixs); 00788 if (copyformat) 00789 pixCopyInputFormat(pixd, pixs); 00790 00791 /* This will destroy pixs if data was transferred; 00792 * otherwise, it just decrements its refcount. */ 00793 pixDestroy(ppixs); 00794 return 0; 00795 } 00796 00797 00798 00799 /*--------------------------------------------------------------------* 00800 * Accessors * 00801 *--------------------------------------------------------------------*/ 00802 l_int32 00803 pixGetWidth(PIX *pix) 00804 { 00805 PROCNAME("pixGetWidth"); 00806 00807 if (!pix) 00808 return ERROR_INT("pix not defined", procName, UNDEF); 00809 00810 return pix->w; 00811 } 00812 00813 00814 l_int32 00815 pixSetWidth(PIX *pix, 00816 l_int32 width) 00817 { 00818 PROCNAME("pixSetWidth"); 00819 00820 if (!pix) 00821 return ERROR_INT("pix not defined", procName, 1); 00822 if (width < 0) { 00823 pix->w = 0; 00824 return ERROR_INT("width must be >= 0", procName, 1); 00825 } 00826 00827 pix->w = width; 00828 return 0; 00829 } 00830 00831 00832 l_int32 00833 pixGetHeight(PIX *pix) 00834 { 00835 PROCNAME("pixGetHeight"); 00836 00837 if (!pix) 00838 return ERROR_INT("pix not defined", procName, UNDEF); 00839 00840 return pix->h; 00841 } 00842 00843 00844 l_int32 00845 pixSetHeight(PIX *pix, 00846 l_int32 height) 00847 { 00848 PROCNAME("pixSetHeight"); 00849 00850 if (!pix) 00851 return ERROR_INT("pix not defined", procName, 1); 00852 if (height < 0) { 00853 pix->h = 0; 00854 return ERROR_INT("h must be >= 0", procName, 1); 00855 } 00856 00857 pix->h = height; 00858 return 0; 00859 } 00860 00861 00862 l_int32 00863 pixGetDepth(PIX *pix) 00864 { 00865 PROCNAME("pixGetDepth"); 00866 00867 if (!pix) 00868 return ERROR_INT("pix not defined", procName, UNDEF); 00869 00870 return pix->d; 00871 } 00872 00873 00874 l_int32 00875 pixSetDepth(PIX *pix, 00876 l_int32 depth) 00877 { 00878 PROCNAME("pixSetDepth"); 00879 00880 if (!pix) 00881 return ERROR_INT("pix not defined", procName, 1); 00882 if (depth < 1) 00883 return ERROR_INT("d must be >= 1", procName, 1); 00884 00885 pix->d = depth; 00886 return 0; 00887 } 00888 00889 00890 /*! 00891 * pixGetDimensions() 00892 * 00893 * Input: pix 00894 * &w, &h, &d (<optional return>; each can be null) 00895 * Return: 0 if OK, 1 on error 00896 */ 00897 l_int32 00898 pixGetDimensions(PIX *pix, 00899 l_int32 *pw, 00900 l_int32 *ph, 00901 l_int32 *pd) 00902 { 00903 PROCNAME("pixGetDimensions"); 00904 00905 if (pw) *pw = 0; 00906 if (ph) *ph = 0; 00907 if (pd) *pd = 0; 00908 if (!pix) 00909 return ERROR_INT("pix not defined", procName, 1); 00910 if (pw) *pw = pix->w; 00911 if (ph) *ph = pix->h; 00912 if (pd) *pd = pix->d; 00913 return 0; 00914 } 00915 00916 00917 /*! 00918 * pixSetDimensions() 00919 * 00920 * Input: pix 00921 * w, h, d (use 0 to skip the setting for any of these) 00922 * Return: 0 if OK, 1 on error 00923 */ 00924 l_int32 00925 pixSetDimensions(PIX *pix, 00926 l_int32 w, 00927 l_int32 h, 00928 l_int32 d) 00929 { 00930 PROCNAME("pixSetDimensions"); 00931 00932 if (!pix) 00933 return ERROR_INT("pix not defined", procName, 1); 00934 if (w > 0) pixSetWidth(pix, w); 00935 if (h > 0) pixSetHeight(pix, h); 00936 if (d > 0) pixSetDepth(pix, d); 00937 return 0; 00938 } 00939 00940 00941 /*! 00942 * pixCopyDimensions() 00943 * 00944 * Input: pixd 00945 * pixd 00946 * Return: 0 if OK, 1 on error 00947 */ 00948 l_int32 00949 pixCopyDimensions(PIX *pixd, 00950 PIX *pixs) 00951 { 00952 PROCNAME("pixCopyDimensions"); 00953 00954 if (!pixd) 00955 return ERROR_INT("pixd not defined", procName, 1); 00956 if (!pixs) 00957 return ERROR_INT("pixs not defined", procName, 1); 00958 if (pixs == pixd) 00959 return 0; /* no-op */ 00960 00961 pixSetWidth(pixd, pixGetWidth(pixs)); 00962 pixSetHeight(pixd, pixGetHeight(pixs)); 00963 pixSetDepth(pixd, pixGetDepth(pixs)); 00964 pixSetWpl(pixd, pixGetWpl(pixs)); 00965 return 0; 00966 } 00967 00968 00969 l_int32 00970 pixGetWpl(PIX *pix) 00971 { 00972 PROCNAME("pixGetWpl"); 00973 00974 if (!pix) 00975 return ERROR_INT("pix not defined", procName, UNDEF); 00976 return pix->wpl; 00977 } 00978 00979 00980 l_int32 00981 pixSetWpl(PIX *pix, 00982 l_int32 wpl) 00983 { 00984 PROCNAME("pixSetWpl"); 00985 00986 if (!pix) 00987 return ERROR_INT("pix not defined", procName, 1); 00988 00989 pix->wpl = wpl; 00990 return 0; 00991 } 00992 00993 00994 l_int32 00995 pixGetRefcount(PIX *pix) 00996 { 00997 PROCNAME("pixGetRefcount"); 00998 00999 if (!pix) 01000 return ERROR_INT("pix not defined", procName, UNDEF); 01001 return pix->refcount; 01002 } 01003 01004 01005 l_int32 01006 pixChangeRefcount(PIX *pix, 01007 l_int32 delta) 01008 { 01009 PROCNAME("pixChangeRefcount"); 01010 01011 if (!pix) 01012 return ERROR_INT("pix not defined", procName, 1); 01013 01014 pix->refcount += delta; 01015 return 0; 01016 } 01017 01018 01019 l_int32 01020 pixGetXRes(PIX *pix) 01021 { 01022 PROCNAME("pixGetXRes"); 01023 01024 if (!pix) 01025 return ERROR_INT("pix not defined", procName, 0); 01026 return pix->xres; 01027 } 01028 01029 01030 l_int32 01031 pixSetXRes(PIX *pix, 01032 l_int32 res) 01033 { 01034 PROCNAME("pixSetXRes"); 01035 01036 if (!pix) 01037 return ERROR_INT("pix not defined", procName, 1); 01038 01039 pix->xres = res; 01040 return 0; 01041 } 01042 01043 01044 l_int32 01045 pixGetYRes(PIX *pix) 01046 { 01047 PROCNAME("pixGetYRes"); 01048 01049 if (!pix) 01050 return ERROR_INT("pix not defined", procName, 0); 01051 return pix->yres; 01052 } 01053 01054 01055 l_int32 01056 pixSetYRes(PIX *pix, 01057 l_int32 res) 01058 { 01059 PROCNAME("pixSetYRes"); 01060 01061 if (!pix) 01062 return ERROR_INT("pix not defined", procName, 1); 01063 01064 pix->yres = res; 01065 return 0; 01066 } 01067 01068 01069 /*! 01070 * pixGetResolution() 01071 * 01072 * Input: pix 01073 * &xres, &yres (<optional return>; each can be null) 01074 * Return: 0 if OK, 1 on error 01075 */ 01076 l_int32 01077 pixGetResolution(PIX *pix, 01078 l_int32 *pxres, 01079 l_int32 *pyres) 01080 { 01081 PROCNAME("pixGetResolution"); 01082 01083 if (!pix) 01084 return ERROR_INT("pix not defined", procName, 1); 01085 if (pxres) *pxres = pix->xres; 01086 if (pyres) *pyres = pix->yres; 01087 return 0; 01088 } 01089 01090 01091 /*! 01092 * pixSetResolution() 01093 * 01094 * Input: pix 01095 * xres, yres (use 0 to skip the setting for either of these) 01096 * Return: 0 if OK, 1 on error 01097 */ 01098 l_int32 01099 pixSetResolution(PIX *pix, 01100 l_int32 xres, 01101 l_int32 yres) 01102 { 01103 PROCNAME("pixSetResolution"); 01104 01105 if (!pix) 01106 return ERROR_INT("pix not defined", procName, 1); 01107 if (xres > 0) pix->xres = xres; 01108 if (yres > 0) pix->yres = yres; 01109 return 0; 01110 } 01111 01112 01113 l_int32 01114 pixCopyResolution(PIX *pixd, 01115 PIX *pixs) 01116 { 01117 PROCNAME("pixCopyResolution"); 01118 01119 if (!pixs) 01120 return ERROR_INT("pixs not defined", procName, 1); 01121 if (!pixd) 01122 return ERROR_INT("pixd not defined", procName, 1); 01123 if (pixs == pixd) 01124 return 0; /* no-op */ 01125 01126 pixSetXRes(pixd, pixGetXRes(pixs)); 01127 pixSetYRes(pixd, pixGetYRes(pixs)); 01128 return 0; 01129 } 01130 01131 01132 l_int32 01133 pixScaleResolution(PIX *pix, 01134 l_float32 xscale, 01135 l_float32 yscale) 01136 { 01137 PROCNAME("pixScaleResolution"); 01138 01139 if (!pix) 01140 return ERROR_INT("pix not defined", procName, 1); 01141 01142 if (pix->xres != 0 && pix->yres != 0) { 01143 pix->xres = (l_uint32)(xscale * (l_float32)(pix->xres) + 0.5); 01144 pix->yres = (l_uint32)(yscale * (l_float32)(pix->yres) + 0.5); 01145 } 01146 return 0; 01147 } 01148 01149 01150 l_int32 01151 pixGetInputFormat(PIX *pix) 01152 { 01153 PROCNAME("pixGetInputFormat"); 01154 01155 if (!pix) 01156 return ERROR_INT("pix not defined", procName, UNDEF); 01157 return pix->informat; 01158 } 01159 01160 01161 l_int32 01162 pixSetInputFormat(PIX *pix, 01163 l_int32 informat) 01164 { 01165 PROCNAME("pixSetInputFormat"); 01166 01167 if (!pix) 01168 return ERROR_INT("pix not defined", procName, 1); 01169 01170 pix->informat = informat; 01171 return 0; 01172 } 01173 01174 01175 l_int32 01176 pixCopyInputFormat(PIX *pixd, 01177 PIX *pixs) 01178 { 01179 PROCNAME("pixCopyInputFormat"); 01180 01181 if (!pixs) 01182 return ERROR_INT("pixs not defined", procName, 1); 01183 if (!pixd) 01184 return ERROR_INT("pixd not defined", procName, 1); 01185 if (pixs == pixd) 01186 return 0; /* no-op */ 01187 01188 pixSetInputFormat(pixd, pixGetInputFormat(pixs)); 01189 return 0; 01190 } 01191 01192 01193 /*! 01194 * pixGetText() 01195 * 01196 * Input: pix 01197 * Return: ptr to existing text string 01198 * 01199 * Notes: 01200 * (1) The text string belongs to the pix. The caller must 01201 * NOT free it! 01202 */ 01203 char * 01204 pixGetText(PIX *pix) 01205 { 01206 PROCNAME("pixGetText"); 01207 01208 if (!pix) 01209 return (char *)ERROR_PTR("pix not defined", procName, NULL); 01210 return pix->text; 01211 } 01212 01213 01214 /*! 01215 * pixSetText() 01216 * 01217 * Input: pix 01218 * textstring (can be null) 01219 * Return: 0 if OK, 1 on error 01220 * 01221 * Notes: 01222 * (1) This removes any existing textstring and puts a copy of 01223 * the input textstring there. 01224 */ 01225 l_int32 01226 pixSetText(PIX *pix, 01227 const char *textstring) 01228 { 01229 PROCNAME("pixSetText"); 01230 01231 if (!pix) 01232 return ERROR_INT("pix not defined", procName, 1); 01233 01234 stringReplace(&pix->text, textstring); 01235 return 0; 01236 } 01237 01238 01239 /*! 01240 * pixAddText() 01241 * 01242 * Input: pix 01243 * textstring 01244 * Return: 0 if OK, 1 on error 01245 * 01246 * Notes: 01247 * (1) This adds the new textstring to any existing text. 01248 * (2) Either or both the existing text and the new text 01249 * string can be null. 01250 */ 01251 l_int32 01252 pixAddText(PIX *pix, 01253 const char *textstring) 01254 { 01255 char *newstring; 01256 01257 PROCNAME("pixAddText"); 01258 01259 if (!pix) 01260 return ERROR_INT("pix not defined", procName, 1); 01261 01262 newstring = stringJoin(pixGetText(pix), textstring); 01263 stringReplace(&pix->text, newstring); 01264 FREE(newstring); 01265 return 0; 01266 } 01267 01268 01269 l_int32 01270 pixCopyText(PIX *pixd, 01271 PIX *pixs) 01272 { 01273 PROCNAME("pixCopyText"); 01274 01275 if (!pixs) 01276 return ERROR_INT("pixs not defined", procName, 1); 01277 if (!pixd) 01278 return ERROR_INT("pixd not defined", procName, 1); 01279 if (pixs == pixd) 01280 return 0; /* no-op */ 01281 01282 pixSetText(pixd, pixGetText(pixs)); 01283 return 0; 01284 } 01285 01286 01287 PIXCMAP * 01288 pixGetColormap(PIX *pix) 01289 { 01290 PROCNAME("pixGetColormap"); 01291 01292 if (!pix) 01293 return (PIXCMAP *)ERROR_PTR("pix not defined", procName, NULL); 01294 return pix->colormap; 01295 } 01296 01297 01298 /*! 01299 * pixSetColormap() 01300 * 01301 * Input: pix 01302 * colormap (to be assigned) 01303 * Return: 0 if OK, 1 on error. 01304 * 01305 * Notes: 01306 * (1) Unlike with the pix data field, pixSetColormap() destroys 01307 * any existing colormap before assigning the new one. 01308 * Because colormaps are not ref counted, it is important that 01309 * the new colormap does not belong to any other pix. 01310 */ 01311 l_int32 01312 pixSetColormap(PIX *pix, 01313 PIXCMAP *colormap) 01314 { 01315 PROCNAME("pixSetColormap"); 01316 01317 if (!pix) 01318 return ERROR_INT("pix not defined", procName, 1); 01319 01320 pixDestroyColormap(pix); 01321 pix->colormap = colormap; 01322 return 0; 01323 } 01324 01325 01326 /*! 01327 * pixDestroyColormap() 01328 * 01329 * Input: pix 01330 * Return: 0 if OK, 1 on error 01331 */ 01332 l_int32 01333 pixDestroyColormap(PIX *pix) 01334 { 01335 PIXCMAP *cmap; 01336 01337 PROCNAME("pixDestroyColormap"); 01338 01339 if (!pix) 01340 return ERROR_INT("pix not defined", procName, 1); 01341 01342 if ((cmap = pix->colormap) != NULL) { 01343 pixcmapDestroy(&cmap); 01344 pix->colormap = NULL; 01345 } 01346 return 0; 01347 } 01348 01349 01350 /*! 01351 * pixGetData() 01352 * 01353 * Notes: 01354 * (1) This gives a new handle for the data. The data is still 01355 * owned by the pix, so do not call FREE() on it. 01356 */ 01357 l_uint32 * 01358 pixGetData(PIX *pix) 01359 { 01360 PROCNAME("pixGetData"); 01361 01362 if (!pix) 01363 return (l_uint32 *)ERROR_PTR("pix not defined", procName, NULL); 01364 return pix->data; 01365 } 01366 01367 01368 /*! 01369 * pixSetData() 01370 * 01371 * Notes: 01372 * (1) This does not free any existing data. To free existing 01373 * data, use pixFreeData() before pixSetData(). 01374 */ 01375 l_int32 01376 pixSetData(PIX *pix, 01377 l_uint32 *data) 01378 { 01379 PROCNAME("pixSetData"); 01380 01381 if (!pix) 01382 return ERROR_INT("pix not defined", procName, 1); 01383 01384 pix->data = data; 01385 return 0; 01386 } 01387 01388 01389 /*! 01390 * pixExtractData() 01391 * 01392 * Notes: 01393 * (1) This extracts the pix image data for use in another context. 01394 * The caller still needs to use pixDestroy() on the input pix. 01395 * (2) If refcount == 1, the data is extracted and the 01396 * pix->data ptr is set to NULL. 01397 * (3) If refcount > 1, this simply returns a copy of the data, 01398 * using the pix allocator, and leaving the input pix unchanged. 01399 */ 01400 l_uint32 * 01401 pixExtractData(PIX *pixs) 01402 { 01403 l_int32 count, bytes; 01404 l_uint32 *data, *datas; 01405 01406 PROCNAME("pixExtractData"); 01407 01408 if (!pixs) 01409 return (l_uint32 *)ERROR_PTR("pixs not defined", procName, NULL); 01410 01411 count = pixGetRefcount(pixs); 01412 if (count == 1) { /* extract */ 01413 data = pixGetData(pixs); 01414 pixSetData(pixs, NULL); 01415 } 01416 else { /* refcount > 1; copy */ 01417 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs); 01418 datas = pixGetData(pixs); 01419 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL) 01420 return (l_uint32 *)ERROR_PTR("data not made", procName, NULL); 01421 memcpy((char *)data, (char *)datas, bytes); 01422 } 01423 01424 return data; 01425 } 01426 01427 01428 /*! 01429 * pixFreeData() 01430 * 01431 * Notes: 01432 * (1) This frees the data and sets the pix data ptr to null. 01433 * It should be used before pixSetData() in the situation where 01434 * you want to free any existing data before doing 01435 * a subsequent assignment with pixSetData(). 01436 */ 01437 l_int32 01438 pixFreeData(PIX *pix) 01439 { 01440 l_uint32 *data; 01441 01442 PROCNAME("pixFreeData"); 01443 01444 if (!pix) 01445 return ERROR_INT("pix not defined", procName, 1); 01446 01447 if ((data = pixGetData(pix)) != NULL) { 01448 pix_free(data); 01449 pix->data = NULL; 01450 } 01451 return 0; 01452 } 01453 01454 01455 /*--------------------------------------------------------------------* 01456 * Pix line ptrs * 01457 *--------------------------------------------------------------------*/ 01458 /*! 01459 * pixGetLinePtrs() 01460 * 01461 * Input: pix 01462 * &size (<optional return> array size, which is the pix height) 01463 * Return: array of line ptrs, or null on error 01464 * 01465 * Notes: 01466 * (1) This is intended to be used for fast random pixel access. 01467 * For example, for an 8 bpp image, 01468 * val = GET_DATA_BYTE(lines8[i], j); 01469 * is equivalent to, but much faster than, 01470 * pixGetPixel(pix, j, i, &val); 01471 * (2) How much faster? For 1 bpp, it's from 6 to 10x faster. 01472 * For 8 bpp, it's an amazing 30x faster. So if you are 01473 * doing random access over a substantial part of the image, 01474 * use this line ptr array. 01475 * (3) When random access is used in conjunction with a stack, 01476 * queue or heap, the overall computation time depends on 01477 * the operations performed on each struct that is popped 01478 * or pushed, and whether we are using a priority queue (O(logn)) 01479 * or a queue or stack (O(1)). For example, for maze search, 01480 * the overall ratio of time for line ptrs vs. pixGet/Set* is 01481 * Maze type Type Time ratio 01482 * binary queue 0.4 01483 * gray heap (priority queue) 0.6 01484 * (4) Because this returns a void** and the accessors take void*, 01485 * the compiler cannot check the pointer types. It is 01486 * strongly recommended that you adopt a naming scheme for 01487 * the returned ptr arrays that indicates the pixel depth. 01488 * (This follows the original intent of Simonyi's "Hungarian" 01489 * application notation, where naming is used proactively 01490 * to make errors visibly obvious.) By doing this, you can 01491 * tell by inspection if the correct accessor is used. 01492 * For example, for an 8 bpp pixg: 01493 * void **lineg8 = pixGetLinePtrs(pixg, NULL); 01494 * val = GET_DATA_BYTE(lineg8[i], j); // fast access; BYTE, 8 01495 * ... 01496 * FREE(lineg8); // don't forget this 01497 * (5) These are convenient for accessing bytes sequentially in an 01498 * 8 bpp grayscale image. People who write image processing code 01499 * on 8 bpp images are accustomed to grabbing pixels directly out 01500 * of the raster array. Note that for little endians, you first 01501 * need to reverse the byte order in each 32-bit word. 01502 * Here's a typical usage pattern: 01503 * pixEndianByteSwap(pix); // always safe; no-op on big-endians 01504 * l_uint8 **lineptrs = (l_uint8 **)pixGetLinePtrs(pix, NULL); 01505 * pixGetDimensions(pix, &w, &h, NULL); 01506 * for (i = 0; i < h; i++) { 01507 * l_uint8 *line = lineptrs[i]; 01508 * for (j = 0; j < w; j++) { 01509 * val = line[j]; 01510 * ... 01511 * } 01512 * } 01513 * pixEndianByteSwap(pix); // restore big-endian order 01514 * FREE(lineptrs); 01515 * This can be done even more simply as follows: 01516 * l_uint8 **lineptrs = pixSetupByteProcessing(pix, &w, &h); 01517 * for (i = 0; i < h; i++) { 01518 * l_uint8 *line = lineptrs[i]; 01519 * for (j = 0; j < w; j++) { 01520 * val = line[j]; 01521 * ... 01522 * } 01523 * } 01524 * pixCleanupByteProcessing(pix, lineptrs); 01525 */ 01526 void ** 01527 pixGetLinePtrs(PIX *pix, 01528 l_int32 *psize) 01529 { 01530 l_int32 i, h, wpl; 01531 l_uint32 *data; 01532 void **lines; 01533 01534 PROCNAME("pixGetLinePtrs"); 01535 01536 if (!pix) 01537 return (void **)ERROR_PTR("pix not defined", procName, NULL); 01538 01539 h = pixGetHeight(pix); 01540 if (psize) *psize = h; 01541 if ((lines = (void **)CALLOC(h, sizeof(void *))) == NULL) 01542 return (void **)ERROR_PTR("lines not made", procName, NULL); 01543 wpl = pixGetWpl(pix); 01544 data = pixGetData(pix); 01545 for (i = 0; i < h; i++) 01546 lines[i] = (void *)(data + i * wpl); 01547 01548 return lines; 01549 } 01550 01551 01552 /*--------------------------------------------------------------------* 01553 * Print output for debugging * 01554 *--------------------------------------------------------------------*/ 01555 extern const char *ImageFileFormatExtensions[]; 01556 01557 /*! 01558 * pixPrintStreamInfo() 01559 * 01560 * Input: fp (file stream) 01561 * pix 01562 * text (<optional> identifying string; can be null) 01563 * Return: 0 if OK, 1 on error 01564 */ 01565 l_int32 01566 pixPrintStreamInfo(FILE *fp, 01567 PIX *pix, 01568 const char *text) 01569 { 01570 l_int32 informat; 01571 PIXCMAP *cmap; 01572 01573 PROCNAME("pixPrintStreamInfo"); 01574 01575 if (!fp) 01576 return ERROR_INT("fp not defined", procName, 1); 01577 if (!pix) 01578 return ERROR_INT("pix not defined", procName, 1); 01579 01580 if (text) 01581 fprintf(fp, " Pix Info for %s:\n", text); 01582 fprintf(fp, " width = %d, height = %d, depth = %d\n", 01583 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix)); 01584 fprintf(fp, " wpl = %d, data = %p, refcount = %d\n", 01585 pixGetWpl(pix), pixGetData(pix), pixGetRefcount(pix)); 01586 if ((cmap = pixGetColormap(pix)) != NULL) 01587 pixcmapWriteStream(fp, cmap); 01588 else 01589 fprintf(fp, " no colormap\n"); 01590 informat = pixGetInputFormat(pix); 01591 fprintf(fp, " input format: %d (%s)\n", informat, 01592 ImageFileFormatExtensions[informat]); 01593 01594 return 0; 01595 }