1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16 /*
17 * pix1.c
18 *
19 * The pixN.c {N = 1,2,3,4} files are sorted by the type of operation.
20 * The primary functions in these files are:
21 *
22 * pix1.c: constructors, destructors and field accessors
23 * pix2.c: pixel poking of image, pad and border pixels
24 * pix3.c: masking and logical ops, counting, mirrored tiling
25 * pix4.c: histograms, fg/bg estimation, rectangle extraction
26 *
27 *
28 * This file has the basic constructors, destructors and field accessors
29 *
30 * Pix memory management (allows custom allocator and deallocator)
31 * static void *pix_malloc()
32 * static void pix_free()
33 * void setPixMemoryManager()
34 *
35 * Pix creation
36 * PIX *pixCreate()
37 * PIX *pixCreateNoInit()
38 * PIX *pixCreateTemplate()
39 * PIX *pixCreateTemplateNoInit()
40 * PIX *pixCreateHeader()
41 * PIX *pixClone()
42 *
43 * Pix destruction
44 * void pixDestroy()
45 * static void pixFree()
46 *
47 * Pix copy
48 * PIX *pixCopy()
49 * l_int32 pixResizeImageData()
50 * l_int32 pixCopyColormap()
51 * l_int32 pixSizesEqual()
52 * l_int32 pixTransferAllData()
53 *
54 * Pix accessors
55 * l_int32 pixGetWidth()
56 * l_int32 pixSetWidth()
57 * l_int32 pixGetHeight()
58 * l_int32 pixSetHeight()
59 * l_int32 pixGetDepth()
60 * l_int32 pixSetDepth()
61 * l_int32 pixGetDimensions()
62 * l_int32 pixSetDimensions()
63 * l_int32 pixCopyDimensions()
64 * l_int32 pixGetWpl()
65 * l_int32 pixSetWpl()
66 * l_int32 pixGetRefcount()
67 * l_int32 pixChangeRefcount()
68 * l_uint32 pixGetXRes()
69 * l_int32 pixSetXRes()
70 * l_uint32 pixGetYRes()
71 * l_int32 pixSetYRes()
72 * l_int32 pixGetResolution()
73 * l_int32 pixSetResolution()
74 * l_int32 pixCopyResolution()
75 * l_int32 pixScaleResolution()
76 * l_int32 pixGetInputFormat()
77 * l_int32 pixSetInputFormat()
78 * l_int32 pixCopyInputFormat()
79 * char *pixGetText()
80 * l_int32 pixSetText()
81 * l_int32 pixAddText()
82 * l_int32 pixCopyText()
83 * PIXCMAP *pixGetColormap()
84 * l_int32 pixSetColormap()
85 * l_int32 pixDestroyColormap()
86 * l_uint32 *pixGetData()
87 * l_int32 pixSetData()
88 * l_uint32 *pixExtractData()
89 * l_int32 pixFreeData()
90 *
91 * Pix line ptrs
92 * void **pixGetLinePtrs()
93 *
94 * Pix debug
95 * l_int32 pixPrintStreamInfo()
96 *
97 *
98 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
99 * Important notes on direct management of pix image data
100 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
101 *
102 * Custom allocator and deallocator
103 * --------------------------------
104 *
105 * At the lowest level, you can specify the function that does the
106 * allocation and deallocation of the data field in the pix.
107 * By default, this is malloc and free. However, by calling
108 * setPixMemoryManager(), custom functions can be substituted.
109 * When using this, keep two things in mind:
110 *
111 * (1) Call setPixMemoryManager() before any pix have been allocated
112 * (2) Destroy all pix as usual, in order to prevent leaks.
113 *
114 * In pixalloc.c, we provide an example custom allocator and deallocator.
115 * To use it, you must call pmsCreate() before any pix have been allocated
116 * and pmsDestroy() at the end after all pix have been destroyed.
117 *
118 *
119 * Direct manipulation of the pix data field
120 * -----------------------------------------
121 *
122 * Memory management of the (image) data field in the pix is
123 * handled differently from that in the colormap or text fields.
124 * For colormap and text, the functions pixSetColormap() and
125 * pixSetText() remove the existing heap data and insert the
126 * new data. For the image data, pixSetData() just reassigns the
127 * data field; any existing data will be lost if there isn't
128 * another handle for it.
129 *
130 * Why is pixSetData() limited in this way? Because the image
131 * data can be very large, we need flexible ways to handle it,
132 * particularly when you want to re-use the data in a different
133 * context without making a copy. Here are some different
134 * things you might want to do:
135 *
136 * (1) Use pixCopy(pixd, pixs) where pixd is not the same size
137 * as pixs. This will remove the data in pixd, allocate a
138 * new data field in pixd, and copy the data from pixs, leaving
139 * pixs unchanged.
140 *
141 * (2) Use pixTransferAllData(pixd, &pixs, ...) to transfer the
142 * data from pixs to pixd without making a copy of it. If
143 * pixs is not cloned, this will do the transfer and destroy pixs.
144 * But if the refcount of pixs is greater than 1, it just copies
145 * the data and decrements the ref count.
146 *
147 * (3) Use pixExtractData() to extract the image data from the pix
148 * without copying if possible. This could be used, for example,
149 * to convert from a pix to some other data structure with minimal
150 * heap allocation. After the data is extracated, the pixels can
151 * be munged and used in another context. However, the danger
152 * here is that the pix might have a refcount > 1, in which case
153 * a copy of the data must be made and the input pix left unchanged.
154 * If there are no clones, the image data can be extracted without
155 * a copy, and the data ptr in the pix must be nulled before
156 * destroying it because the pix will no longer 'own' the data.
157 *
158 * We have provided accessors and functions here that should be
159 * sufficient so that you can do anything you want without
160 * explicitly referencing any of the pix member fields.
161 *
162 * However, to avoid memory smashes and leaks when doing special operations
163 * on the pix data field, look carefully at the behavior of the image
164 * data accessors and keep in mind that when you invoke pixDestroy(),
165 * the pix considers itself the owner of all its heap data.
166 */
167
168 #include <stdio.h>
169 #include <stdlib.h>
170 #include <string.h>
171 #include "allheaders.h"
172
173 static void pixFree(PIX *pix);
174
175
176 /*-------------------------------------------------------------------------*
177 * Pix Memory Management *
178 * *
179 * These functions give you the freedom to specify at compile or run *
180 * time the allocator and deallocator to be used for pix. It has no *
181 * effect on memory management for other data structs, which are *
182 * controlled by the #defines in environ.h. Likewise, the #defines *
183 * in environ.h have no effect on the pix memory management. *
184 * The default functions are malloc and free. Use setPixMemoryManager() *
185 * to specify other functions to use. *
186 *-------------------------------------------------------------------------*/
187 struct PixMemoryManager
188 {
189 void *(*allocator)(size_t);
190 void (*deallocator)(void *);
191 };
192
193 static struct PixMemoryManager pix_mem_manager = {
194 &malloc,
195 &free
196 };
197
198 static void *
pix_malloc(size_t size)199 pix_malloc(size_t size)
200 {
201 #ifndef COMPILER_MSVC
202 return (*pix_mem_manager.allocator)(size);
203 #else /* COMPILER_MSVC */
204 /* Under MSVC++, pix_mem_manager is initialized after a call
205 * to pix_malloc. Just ignore the custom allocator feature. */
206 return malloc(size);
207 #endif /* COMPILER_MSVC */
208 }
209
210 static void
pix_free(void * ptr)211 pix_free(void *ptr)
212 {
213 #ifndef COMPILER_MSVC
214 return (*pix_mem_manager.deallocator)(ptr);
215 #else /* COMPILER_MSVC */
216 /* Under MSVC++, pix_mem_manager is initialized after a call
217 * to pix_malloc. Just ignore the custom allocator feature. */
218 return free(ptr);
219 #endif /* COMPILER_MSVC */
220 }
221
222 /*!
223 * setPixMemoryManager()
224 *
225 * Input: allocator (<optional>; use null to skip)
226 * deallocator (<optional>; use null to skip)
227 * Return: void
228 *
229 * Notes:
230 * (1) Use this to change the alloc and/or dealloc functions;
231 * e.g., setPixMemoryManager(my_malloc, my_free).
232 */
233 #ifndef COMPILER_MSVC
234 void
setPixMemoryManager(void * (allocator (size_t)),void (deallocator (void *)))235 setPixMemoryManager(void *(allocator(size_t)),
236 void (deallocator(void *)))
237 {
238 if (allocator) pix_mem_manager.allocator = allocator;
239 if (deallocator) pix_mem_manager.deallocator = deallocator;
240 return;
241 }
242 #else /* COMPILER_MSVC */
243 /* MSVC++ wants type (*fun)(types...) syntax */
244 void
setPixMemoryManager(void * ((* allocator)(size_t)),void ((* deallocator)(void *)))245 setPixMemoryManager(void *((*allocator)(size_t)),
246 void ((*deallocator)(void *)))
247 {
248 if (allocator) pix_mem_manager.allocator = allocator;
249 if (deallocator) pix_mem_manager.deallocator = deallocator;
250 return;
251 }
252 #endif /* COMPILER_MSVC */
253
254
255 /*--------------------------------------------------------------------*
256 * Pix Creation *
257 *--------------------------------------------------------------------*/
258 /*!
259 * pixCreate()
260 *
261 * Input: width, height, depth
262 * Return: pixd (with data allocated and initialized to 0),
263 * or null on error
264 */
265 PIX *
pixCreate(l_int32 width,l_int32 height,l_int32 depth)266 pixCreate(l_int32 width,
267 l_int32 height,
268 l_int32 depth)
269 {
270 PIX *pixd;
271
272 PROCNAME("pixCreate");
273
274 if ((pixd = pixCreateNoInit(width, height, depth)) == NULL)
275 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
276 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h);
277 return pixd;
278 }
279
280
281 /*!
282 * pixCreateNoInit()
283 *
284 * Input: width, height, depth
285 * Return: pixd (with data allocated but not initialized),
286 * or null on error
287 *
288 * Notes:
289 * (1) Must set pad bits to avoid reading unitialized data, because
290 * some optimized routines (e.g., pixConnComp()) read from pad bits.
291 */
292 PIX *
pixCreateNoInit(l_int32 width,l_int32 height,l_int32 depth)293 pixCreateNoInit(l_int32 width,
294 l_int32 height,
295 l_int32 depth)
296 {
297 l_int32 wpl;
298 PIX *pixd;
299 l_uint32 *data;
300
301 PROCNAME("pixCreateNoInit");
302 pixd = pixCreateHeader(width, height, depth);
303 if (!pixd) return NULL;
304 wpl = pixGetWpl(pixd);
305 if ((data = (l_uint32 *)pix_malloc(4 * wpl * height)) == NULL)
306 return (PIX *)ERROR_PTR("pix_malloc fail for data", procName, NULL);
307 pixSetData(pixd, data);
308 pixSetPadBits(pixd, 0);
309 return pixd;
310 }
311
312
313 /*!
314 * pixCreateTemplate()
315 *
316 * Input: pixs
317 * Return: pixd, or null on error
318 *
319 * Notes:
320 * (1) Makes a Pix of the same size as the input Pix, with the
321 * data array allocated and initialized to 0.
322 * (2) Copies the other fields, including colormap if it exists.
323 */
324 PIX *
pixCreateTemplate(PIX * pixs)325 pixCreateTemplate(PIX *pixs)
326 {
327 PIX *pixd;
328
329 PROCNAME("pixCreateTemplate");
330
331 if (!pixs)
332 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
333
334 if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
335 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
336 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h);
337 return pixd;
338 }
339
340
341 /*!
342 * pixCreateTemplateNoInit()
343 *
344 * Input: pixs
345 * Return: pixd, or null on error
346 *
347 * Notes:
348 * (1) Makes a Pix of the same size as the input Pix, with
349 * the data array allocated but not initialized to 0.
350 * (2) Copies the other fields, including colormap if it exists.
351 */
352 PIX *
pixCreateTemplateNoInit(PIX * pixs)353 pixCreateTemplateNoInit(PIX *pixs)
354 {
355 l_int32 w, h, d;
356 PIX *pixd;
357
358 PROCNAME("pixCreateTemplateNoInit");
359
360 if (!pixs)
361 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
362
363 pixGetDimensions(pixs, &w, &h, &d);
364 if ((pixd = pixCreateNoInit(w, h, d)) == NULL)
365 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
366 pixCopyResolution(pixd, pixs);
367 pixCopyColormap(pixd, pixs);
368 pixCopyText(pixd, pixs);
369 pixCopyInputFormat(pixd, pixs);
370
371 return pixd;
372 }
373
374
375 /*!
376 * pixCreateHeader()
377 *
378 * Input: width, height, depth
379 * Return: pixd (with no data allocated), or null on error
380 */
381 PIX *
pixCreateHeader(l_int32 width,l_int32 height,l_int32 depth)382 pixCreateHeader(l_int32 width,
383 l_int32 height,
384 l_int32 depth)
385 {
386 l_int32 wpl;
387 PIX *pixd;
388
389 PROCNAME("pixCreateHeader");
390
391 if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8)
392 && (depth != 16) && (depth != 24) && (depth != 32))
393 return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}",
394 procName, NULL);
395 if (width <= 0)
396 return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
397 if (height <= 0)
398 return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
399
400 if ((pixd = (PIX *)CALLOC(1, sizeof(PIX))) == NULL)
401 return (PIX *)ERROR_PTR("CALLOC fail for pixd", procName, NULL);
402 pixSetWidth(pixd, width);
403 pixSetHeight(pixd, height);
404 pixSetDepth(pixd, depth);
405 wpl = (width * depth + 31) / 32;
406 pixSetWpl(pixd, wpl);
407
408 pixd->refcount = 1;
409 pixd->informat = IFF_UNKNOWN;
410
411 return pixd;
412 }
413
414
415 /*!
416 * pixClone()
417 *
418 * Input: pix
419 * Return: same pix (ptr), or null on error
420 *
421 * Notes:
422 * (1) A "clone" is simply a handle (ptr) to an existing pix.
423 * It is implemented because (a) images can be large and
424 * hence expensive to copy, and (b) extra handles to a data
425 * structure need to be made with a simple policy to avoid
426 * both double frees and memory leaks. Pix are reference
427 * counted. The side effect of pixClone() is an increase
428 * by 1 in the ref count.
429 * (2) The protocol to be used is:
430 * (a) Whenever you want a new handle to an existing image,
431 * call pixClone(), which just bumps a ref count.
432 * (b) Always call pixDestroy() on all handles. This
433 * decrements the ref count, nulls the handle, and
434 * only destroys the pix when pixDestroy() has been
435 * called on all handles.
436 */
437 PIX *
pixClone(PIX * pixs)438 pixClone(PIX *pixs)
439 {
440 PROCNAME("pixClone");
441
442 if (!pixs)
443 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
444 pixChangeRefcount(pixs, 1);
445
446 return pixs;
447 }
448
449
450 /*--------------------------------------------------------------------*
451 * Pix Destruction *
452 *--------------------------------------------------------------------*/
453 /*!
454 * pixDestroy()
455 *
456 * Input: &pix <will be nulled>
457 * Return: void
458 *
459 * Notes:
460 * (1) Decrements the ref count and, if 0, destroys the pix.
461 * (2) Always nulls the input ptr.
462 */
463 void
pixDestroy(PIX ** ppix)464 pixDestroy(PIX **ppix)
465 {
466 PIX *pix;
467
468 PROCNAME("pixDestroy");
469
470 if (!ppix) {
471 L_WARNING("ptr address is null!", procName);
472 return;
473 }
474
475 if ((pix = *ppix) == NULL)
476 return;
477
478 pixFree(pix);
479 *ppix = NULL;
480 return;
481 }
482
483
484 /*!
485 * pixFree()
486 *
487 * Input: pix
488 * Return: void
489 *
490 * Notes:
491 * (1) Decrements the ref count and, if 0, destroys the pix.
492 */
493 static void
pixFree(PIX * pix)494 pixFree(PIX *pix)
495 {
496 l_uint32 *data;
497 char *text;
498
499 if (!pix) return;
500
501 pixChangeRefcount(pix, -1);
502 if (pixGetRefcount(pix) <= 0) {
503 if ((data = pixGetData(pix)) != NULL)
504 pix_free(data);
505 if ((text = pixGetText(pix)) != NULL)
506 FREE(text);
507 pixDestroyColormap(pix);
508 FREE(pix);
509 }
510 return;
511 }
512
513
514 /*-------------------------------------------------------------------------*
515 * Pix Copy *
516 *-------------------------------------------------------------------------*/
517 /*!
518 * pixCopy()
519 *
520 * Input: pixd (<optional>; can be null, or equal to pixs,
521 * or different from pixs)
522 * pixs
523 * Return: pixd, or null on error
524 *
525 * Notes:
526 * (1) There are three cases:
527 * (a) pixd == null (makes a new pix; refcount = 1)
528 * (b) pixd == pixs (no-op)
529 * (c) pixd != pixs (data copy; no change in refcount)
530 * If the refcount of pixd > 1, case (c) will side-effect
531 * these handles.
532 * (2) The general pattern of use is:
533 * pixd = pixCopy(pixd, pixs);
534 * This will work for all three cases.
535 * For clarity when the case is known, you can use:
536 * (a) pixd = pixCopy(NULL, pixs);
537 * (c) pixCopy(pixd, pixs);
538 * (3) For case (c), we check if pixs and pixd are the same
539 * size (w,h,d). If so, the data is copied directly.
540 * Otherwise, the data is reallocated to the correct size
541 * and the copy proceeds. The refcount of pixd is unchanged.
542 * (4) This operation, like all others that may involve a pre-existing
543 * pixd, will side-effect any existing clones of pixd.
544 */
545 PIX *
pixCopy(PIX * pixd,PIX * pixs)546 pixCopy(PIX *pixd, /* can be null */
547 PIX *pixs)
548 {
549 l_int32 bytes;
550 l_uint32 *datas, *datad;
551
552 PROCNAME("pixCopy");
553
554 if (!pixs)
555 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
556 if (pixs == pixd)
557 return pixd;
558
559 /* Total bytes in image data */
560 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
561
562 /* If we're making a new pix ... */
563 if (!pixd) {
564 if ((pixd = pixCreateTemplate(pixs)) == NULL)
565 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
566 datas = pixGetData(pixs);
567 datad = pixGetData(pixd);
568 memcpy((char *)datad, (char *)datas, bytes);
569 return pixd;
570 }
571
572 /* Reallocate image data if sizes are different */
573 if (pixResizeImageData(pixd, pixs) == 1)
574 return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL);
575
576 /* Copy non-image data fields */
577 pixCopyColormap(pixd, pixs);
578 pixCopyResolution(pixd, pixs);
579 pixCopyInputFormat(pixd, pixs);
580 pixCopyText(pixd, pixs);
581
582 /* Copy image data */
583 datas = pixGetData(pixs);
584 datad = pixGetData(pixd);
585 memcpy((char*)datad, (char*)datas, bytes);
586 return pixd;
587 }
588
589
590 /*!
591 * pixResizeImageData()
592 *
593 * Input: pixd (gets new uninitialized buffer for image data)
594 * pixs (determines the size of the buffer; not changed)
595 * Return: 0 if OK, 1 on error
596 *
597 * Notes:
598 * (1) This removes any existing image data from pixd and
599 * allocates an uninitialized buffer that will hold the
600 * amount of image data that is in pixs.
601 */
602 l_int32
pixResizeImageData(PIX * pixd,PIX * pixs)603 pixResizeImageData(PIX *pixd,
604 PIX *pixs)
605 {
606 l_int32 w, h, d, wpl, bytes;
607 l_uint32 *data;
608
609 PROCNAME("pixResizeImageData");
610
611 if (!pixs)
612 return ERROR_INT("pixs not defined", procName, 1);
613 if (!pixd)
614 return ERROR_INT("pixd not defined", procName, 1);
615
616 if (pixSizesEqual(pixs, pixd)) /* nothing to do */
617 return 0;
618
619 pixGetDimensions(pixs, &w, &h, &d);
620 wpl = pixGetWpl(pixs);
621 pixSetWidth(pixd, w);
622 pixSetHeight(pixd, h);
623 pixSetDepth(pixd, d);
624 pixSetWpl(pixd, wpl);
625 bytes = 4 * wpl * h;
626 pixFreeData(pixd); /* free any existing image data */
627 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL)
628 return ERROR_INT("pix_malloc fail for data", procName, 1);
629 pixSetData(pixd, data);
630 return 0;
631 }
632
633
634 /*!
635 * pixCopyColormap()
636 *
637 * Input: src and dest Pix
638 * Return: 0 if OK, 1 on error
639 *
640 * Notes:
641 * (1) This always destroys any colormap in pixd (except if
642 * the operation is a no-op.
643 */
644 l_int32
pixCopyColormap(PIX * pixd,PIX * pixs)645 pixCopyColormap(PIX *pixd,
646 PIX *pixs)
647 {
648 PIXCMAP *cmaps, *cmapd;
649
650 PROCNAME("pixCopyColormap");
651
652 if (!pixs)
653 return ERROR_INT("pixs not defined", procName, 1);
654 if (!pixd)
655 return ERROR_INT("pixd not defined", procName, 1);
656 if (pixs == pixd)
657 return 0; /* no-op */
658
659 pixDestroyColormap(pixd);
660 if ((cmaps = pixGetColormap(pixs)) == NULL) /* not an error */
661 return 0;
662
663 if ((cmapd = pixcmapCopy(cmaps)) == NULL)
664 return ERROR_INT("cmapd not made", procName, 1);
665 pixSetColormap(pixd, cmapd);
666
667 return 0;
668 }
669
670
671 /*!
672 * pixSizesEqual()
673 *
674 * Input: two pix
675 * Return: 1 if the two pix have same {h, w, d}; 0 otherwise.
676 */
677 l_int32
pixSizesEqual(PIX * pix1,PIX * pix2)678 pixSizesEqual(PIX *pix1,
679 PIX *pix2)
680 {
681 PROCNAME("pixSizesEqual");
682
683 if (!pix1 || !pix2)
684 return ERROR_INT("pix1 and pix2 not both defined", procName, 0);
685
686 if (pix1 == pix2)
687 return 1;
688
689 if ((pixGetWidth(pix1) != pixGetWidth(pix2)) ||
690 (pixGetHeight(pix1) != pixGetHeight(pix2)) ||
691 (pixGetDepth(pix1) != pixGetDepth(pix2)))
692 return 0;
693 else
694 return 1;
695 }
696
697
698 /*!
699 * pixTransferAllData()
700 *
701 * Input: pixd (must be different from pixs)
702 * &pixs (will be nulled if refcount goes to 0)
703 * copytext (1 to copy the text field; 0 to skip)
704 * copyformat (1 to copy the informat field; 0 to skip)
705 * Return: 0 if OK, 1 on error
706 *
707 * Notes:
708 * (1) This does a complete data transfer from pixs to pixd,
709 * followed by the destruction of pixs (refcount permitting).
710 * (2) If the refcount of pixs is 1, pixs is destroyed. Otherwise,
711 * the data in pixs is copied (rather than transferred) to pixd.
712 * (3) This operation, like all others with a pre-existing pixd,
713 * will side-effect any existing clones of pixd. The pixd
714 * refcount does not change.
715 * (4) When might you use this? Suppose you have an in-place Pix
716 * function (returning void) with the typical signature:
717 * void function-inplace(PIX *pix, ...)
718 * where "..." are non-pointer input parameters, and suppose
719 * further that you sometimes want to return an arbitrary Pix
720 * in place of the input Pix. There are two ways you can do this:
721 * (a) The straightforward way is to change the function
722 * signature to take the address of the Pix ptr:
723 * void function-inplace(PIX **ppix, ...) {
724 * PIX *pixt = function-makenew(*ppix);
725 * pixDestroy(ppix);
726 * *ppix = pixt;
727 * return;
728 * }
729 * Here, the input and returned pix are different, as viewed
730 * by the calling function, and the inplace function is
731 * expected to destroy the input pix to avoid a memory leak.
732 * (b) Keep the signature the same and use pixTransferAllData()
733 * to return the new Pix in the input Pix struct:
734 * void function-inplace(PIX *pix, ...) {
735 * PIX *pixt = function-makenew(pix);
736 * pixTransferAllData(pix, &pixt); // pixt is destroyed
737 * return;
738 * }
739 * Here, the input and returned pix are the same, as viewed
740 * by the calling function, and the inplace function must
741 * never destroy the input pix, because the calling function
742 * maintains an unchanged handle to it.
743 */
744 l_int32
pixTransferAllData(PIX * pixd,PIX ** ppixs,l_int32 copytext,l_int32 copyformat)745 pixTransferAllData(PIX *pixd,
746 PIX **ppixs,
747 l_int32 copytext,
748 l_int32 copyformat)
749 {
750 l_int32 nbytes;
751 PIX *pixs;
752
753 PROCNAME("pixTransferAllData");
754
755 if (!ppixs)
756 return ERROR_INT("&pixs not defined", procName, 1);
757 if ((pixs = *ppixs) == NULL)
758 return ERROR_INT("pixs not defined", procName, 1);
759 if (!pixd)
760 return ERROR_INT("pixd not defined", procName, 1);
761 if (pixs == pixd) /* no-op */
762 return ERROR_INT("pixd == pixs", procName, 1);
763
764 if (pixGetRefcount(pixs) == 1) { /* transfer the data, cmap, text */
765 pixFreeData(pixd); /* dealloc any existing data */
766 pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */
767 pixs->data = NULL; /* pixs no longer owns data */
768 pixSetColormap(pixd, pixGetColormap(pixs)); /* frees old; sets new */
769 pixs->colormap = NULL; /* pixs no longer owns colormap */
770 if (copytext) {
771 pixSetText(pixd, pixGetText(pixs));
772 pixSetText(pixs, NULL);
773 }
774 } else { /* preserve pixs by making a copy of the data, cmap, text */
775 pixResizeImageData(pixd, pixs);
776 nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
777 memcpy((char *)pixGetData(pixd), (char *)pixGetData(pixs), nbytes);
778 pixCopyColormap(pixd, pixs);
779 if (copytext)
780 pixCopyText(pixd, pixs);
781 }
782
783 pixCopyResolution(pixd, pixs);
784 pixCopyDimensions(pixd, pixs);
785 if (copyformat)
786 pixCopyInputFormat(pixd, pixs);
787
788 /* This will destroy pixs if data was transferred;
789 * otherwise, it just decrements its refcount. */
790 pixDestroy(ppixs);
791 return 0;
792 }
793
794
795
796 /*--------------------------------------------------------------------*
797 * Accessors *
798 *--------------------------------------------------------------------*/
799 l_int32
pixGetWidth(PIX * pix)800 pixGetWidth(PIX *pix)
801 {
802 PROCNAME("pixGetWidth");
803
804 if (!pix)
805 return ERROR_INT("pix not defined", procName, UNDEF);
806
807 return pix->w;
808 }
809
810
811 l_int32
pixSetWidth(PIX * pix,l_int32 width)812 pixSetWidth(PIX *pix,
813 l_int32 width)
814 {
815 PROCNAME("pixSetWidth");
816
817 if (!pix)
818 return ERROR_INT("pix not defined", procName, 1);
819 if (width < 0) {
820 pix->w = 0;
821 return ERROR_INT("width must be >= 0", procName, 1);
822 }
823
824 pix->w = width;
825 return 0;
826 }
827
828
829 l_int32
pixGetHeight(PIX * pix)830 pixGetHeight(PIX *pix)
831 {
832 PROCNAME("pixGetHeight");
833
834 if (!pix)
835 return ERROR_INT("pix not defined", procName, UNDEF);
836
837 return pix->h;
838 }
839
840
841 l_int32
pixSetHeight(PIX * pix,l_int32 height)842 pixSetHeight(PIX *pix,
843 l_int32 height)
844 {
845 PROCNAME("pixSetHeight");
846
847 if (!pix)
848 return ERROR_INT("pix not defined", procName, 1);
849 if (height < 0) {
850 pix->h = 0;
851 return ERROR_INT("h must be >= 0", procName, 1);
852 }
853
854 pix->h = height;
855 return 0;
856 }
857
858
859 l_int32
pixGetDepth(PIX * pix)860 pixGetDepth(PIX *pix)
861 {
862 PROCNAME("pixGetDepth");
863
864 if (!pix)
865 return ERROR_INT("pix not defined", procName, UNDEF);
866
867 return pix->d;
868 }
869
870
871 l_int32
pixSetDepth(PIX * pix,l_int32 depth)872 pixSetDepth(PIX *pix,
873 l_int32 depth)
874 {
875 PROCNAME("pixSetDepth");
876
877 if (!pix)
878 return ERROR_INT("pix not defined", procName, 1);
879 if (depth < 1)
880 return ERROR_INT("d must be >= 1", procName, 1);
881
882 pix->d = depth;
883 return 0;
884 }
885
886
887 /*!
888 * pixGetDimensions()
889 *
890 * Input: pix
891 * &w, &h, &d (<optional return>; each can be null)
892 * Return: 0 if OK, 1 on error
893 */
894 l_int32
pixGetDimensions(PIX * pix,l_int32 * pw,l_int32 * ph,l_int32 * pd)895 pixGetDimensions(PIX *pix,
896 l_int32 *pw,
897 l_int32 *ph,
898 l_int32 *pd)
899 {
900 PROCNAME("pixGetDimensions");
901
902 if (!pix)
903 return ERROR_INT("pix not defined", procName, 1);
904 if (pw) *pw = pix->w;
905 if (ph) *ph = pix->h;
906 if (pd) *pd = pix->d;
907 return 0;
908 }
909
910
911 /*!
912 * pixSetDimensions()
913 *
914 * Input: pix
915 * w, h, d (use 0 to skip the setting for any of these)
916 * Return: 0 if OK, 1 on error
917 */
918 l_int32
pixSetDimensions(PIX * pix,l_int32 w,l_int32 h,l_int32 d)919 pixSetDimensions(PIX *pix,
920 l_int32 w,
921 l_int32 h,
922 l_int32 d)
923 {
924 PROCNAME("pixSetDimensions");
925
926 if (!pix)
927 return ERROR_INT("pix not defined", procName, 1);
928 if (w > 0) pixSetWidth(pix, w);
929 if (h > 0) pixSetHeight(pix, h);
930 if (d > 0) pixSetDepth(pix, d);
931 return 0;
932 }
933
934
935 /*!
936 * pixCopyDimensions()
937 *
938 * Input: pixd
939 * pixd
940 * Return: 0 if OK, 1 on error
941 */
942 l_int32
pixCopyDimensions(PIX * pixd,PIX * pixs)943 pixCopyDimensions(PIX *pixd,
944 PIX *pixs)
945 {
946 PROCNAME("pixCopyDimensions");
947
948 if (!pixd)
949 return ERROR_INT("pixd not defined", procName, 1);
950 if (!pixs)
951 return ERROR_INT("pixs not defined", procName, 1);
952 if (pixs == pixd)
953 return 0; /* no-op */
954
955 pixSetWidth(pixd, pixGetWidth(pixs));
956 pixSetHeight(pixd, pixGetHeight(pixs));
957 pixSetDepth(pixd, pixGetDepth(pixs));
958 pixSetWpl(pixd, pixGetWpl(pixs));
959 return 0;
960 }
961
962
963 l_int32
pixGetWpl(PIX * pix)964 pixGetWpl(PIX *pix)
965 {
966 PROCNAME("pixGetWpl");
967
968 if (!pix)
969 return ERROR_INT("pix not defined", procName, UNDEF);
970 return pix->wpl;
971 }
972
973
974 l_int32
pixSetWpl(PIX * pix,l_int32 wpl)975 pixSetWpl(PIX *pix,
976 l_int32 wpl)
977 {
978 PROCNAME("pixSetWpl");
979
980 if (!pix)
981 return ERROR_INT("pix not defined", procName, 1);
982
983 pix->wpl = wpl;
984 return 0;
985 }
986
987
988 l_int32
pixGetRefcount(PIX * pix)989 pixGetRefcount(PIX *pix)
990 {
991 PROCNAME("pixGetRefcount");
992
993 if (!pix)
994 return ERROR_INT("pix not defined", procName, UNDEF);
995 return pix->refcount;
996 }
997
998
999 l_int32
pixChangeRefcount(PIX * pix,l_int32 delta)1000 pixChangeRefcount(PIX *pix,
1001 l_int32 delta)
1002 {
1003 PROCNAME("pixChangeRefcount");
1004
1005 if (!pix)
1006 return ERROR_INT("pix not defined", procName, 1);
1007
1008 pix->refcount += delta;
1009 return 0;
1010 }
1011
1012
1013 l_uint32
pixGetXRes(PIX * pix)1014 pixGetXRes(PIX *pix)
1015 {
1016 PROCNAME("pixGetXRes");
1017
1018 if (!pix)
1019 return ERROR_INT("pix not defined", procName, 0);
1020 return pix->xres;
1021 }
1022
1023
1024 l_int32
pixSetXRes(PIX * pix,l_uint32 res)1025 pixSetXRes(PIX *pix,
1026 l_uint32 res)
1027 {
1028 PROCNAME("pixSetXRes");
1029
1030 if (!pix)
1031 return ERROR_INT("pix not defined", procName, 1);
1032
1033 pix->xres = res;
1034 return 0;
1035 }
1036
1037
1038 l_uint32
pixGetYRes(PIX * pix)1039 pixGetYRes(PIX *pix)
1040 {
1041 PROCNAME("pixGetYRes");
1042
1043 if (!pix)
1044 return ERROR_INT("pix not defined", procName, 0);
1045 return pix->yres;
1046 }
1047
1048
1049 l_int32
pixSetYRes(PIX * pix,l_uint32 res)1050 pixSetYRes(PIX *pix,
1051 l_uint32 res)
1052 {
1053 PROCNAME("pixSetYRes");
1054
1055 if (!pix)
1056 return ERROR_INT("pix not defined", procName, 1);
1057
1058 pix->yres = res;
1059 return 0;
1060 }
1061
1062
1063 /*!
1064 * pixGetResolution()
1065 *
1066 * Input: pix
1067 * &xres, &yres (<optional return>; each can be null)
1068 * Return: 0 if OK, 1 on error
1069 */
1070 l_int32
pixGetResolution(PIX * pix,l_uint32 * pxres,l_uint32 * pyres)1071 pixGetResolution(PIX *pix,
1072 l_uint32 *pxres,
1073 l_uint32 *pyres)
1074 {
1075 PROCNAME("pixGetResolution");
1076
1077 if (!pix)
1078 return ERROR_INT("pix not defined", procName, 1);
1079 if (pxres) *pxres = pix->xres;
1080 if (pyres) *pyres = pix->yres;
1081 return 0;
1082 }
1083
1084
1085 /*!
1086 * pixSetResolution()
1087 *
1088 * Input: pix
1089 * xres, yres (use 0 to skip the setting for either of these)
1090 * Return: 0 if OK, 1 on error
1091 */
1092 l_int32
pixSetResolution(PIX * pix,l_uint32 xres,l_uint32 yres)1093 pixSetResolution(PIX *pix,
1094 l_uint32 xres,
1095 l_uint32 yres)
1096 {
1097 PROCNAME("pixSetResolution");
1098
1099 if (!pix)
1100 return ERROR_INT("pix not defined", procName, 1);
1101 if (xres > 0) pix->xres = xres;
1102 if (yres > 0) pix->yres = yres;
1103 return 0;
1104 }
1105
1106
1107 l_int32
pixCopyResolution(PIX * pixd,PIX * pixs)1108 pixCopyResolution(PIX *pixd,
1109 PIX *pixs)
1110 {
1111 PROCNAME("pixCopyResolution");
1112
1113 if (!pixs)
1114 return ERROR_INT("pixs not defined", procName, 1);
1115 if (!pixd)
1116 return ERROR_INT("pixd not defined", procName, 1);
1117 if (pixs == pixd)
1118 return 0; /* no-op */
1119
1120 pixSetXRes(pixd, pixGetXRes(pixs));
1121 pixSetYRes(pixd, pixGetYRes(pixs));
1122 return 0;
1123 }
1124
1125
1126 l_int32
pixScaleResolution(PIX * pix,l_float32 xscale,l_float32 yscale)1127 pixScaleResolution(PIX *pix,
1128 l_float32 xscale,
1129 l_float32 yscale)
1130 {
1131 PROCNAME("pixScaleResolution");
1132
1133 if (!pix)
1134 return ERROR_INT("pix not defined", procName, 1);
1135
1136 if (pix->xres != 0 && pix->yres != 0) {
1137 pix->xres = (l_uint32)(xscale * (l_float32)(pix->xres) + 0.5);
1138 pix->yres = (l_uint32)(yscale * (l_float32)(pix->yres) + 0.5);
1139 }
1140 return 0;
1141 }
1142
1143
1144 l_int32
pixGetInputFormat(PIX * pix)1145 pixGetInputFormat(PIX *pix)
1146 {
1147 PROCNAME("pixGetInputFormat");
1148
1149 if (!pix)
1150 return ERROR_INT("pix not defined", procName, UNDEF);
1151 return pix->informat;
1152 }
1153
1154
1155 l_int32
pixSetInputFormat(PIX * pix,l_int32 informat)1156 pixSetInputFormat(PIX *pix,
1157 l_int32 informat)
1158 {
1159 PROCNAME("pixSetInputFormat");
1160
1161 if (!pix)
1162 return ERROR_INT("pix not defined", procName, 1);
1163
1164 pix->informat = informat;
1165 return 0;
1166 }
1167
1168
1169 l_int32
pixCopyInputFormat(PIX * pixd,PIX * pixs)1170 pixCopyInputFormat(PIX *pixd,
1171 PIX *pixs)
1172 {
1173 PROCNAME("pixCopyInputFormat");
1174
1175 if (!pixs)
1176 return ERROR_INT("pixs not defined", procName, 1);
1177 if (!pixd)
1178 return ERROR_INT("pixd not defined", procName, 1);
1179 if (pixs == pixd)
1180 return 0; /* no-op */
1181
1182 pixSetInputFormat(pixd, pixGetInputFormat(pixs));
1183 return 0;
1184 }
1185
1186
1187 /*!
1188 * pixGetText()
1189 *
1190 * Input: pix
1191 * Return: ptr to existing text string
1192 *
1193 * Notes:
1194 * (1) The text string belongs to the pix. The caller must
1195 * NOT free it!
1196 */
1197 char *
pixGetText(PIX * pix)1198 pixGetText(PIX *pix)
1199 {
1200 PROCNAME("pixGetText");
1201
1202 if (!pix)
1203 return (char *)ERROR_PTR("pix not defined", procName, NULL);
1204 return pix->text;
1205 }
1206
1207
1208 /*!
1209 * pixSetText()
1210 *
1211 * Input: pix
1212 * textstring (can be null)
1213 * Return: 0 if OK, 1 on error
1214 *
1215 * Notes:
1216 * (1) This removes any existing textstring and puts a copy of
1217 * the input textstring there.
1218 */
1219 l_int32
pixSetText(PIX * pix,const char * textstring)1220 pixSetText(PIX *pix,
1221 const char *textstring)
1222 {
1223 PROCNAME("pixSetText");
1224
1225 if (!pix)
1226 return ERROR_INT("pix not defined", procName, 1);
1227
1228 stringReplace(&pix->text, textstring);
1229 return 0;
1230 }
1231
1232
1233 /*!
1234 * pixAddText()
1235 *
1236 * Input: pix
1237 * textstring
1238 * Return: 0 if OK, 1 on error
1239 *
1240 * Notes:
1241 * (1) This adds the new textstring to any existing text.
1242 * (2) Either or both the existing text and the new text
1243 * string can be null.
1244 */
1245 l_int32
pixAddText(PIX * pix,const char * textstring)1246 pixAddText(PIX *pix,
1247 const char *textstring)
1248 {
1249 char *newstring;
1250
1251 PROCNAME("pixAddText");
1252
1253 if (!pix)
1254 return ERROR_INT("pix not defined", procName, 1);
1255
1256 newstring = stringJoin(pixGetText(pix), textstring);
1257 stringReplace(&pix->text, newstring);
1258 FREE(newstring);
1259 return 0;
1260 }
1261
1262
1263 l_int32
pixCopyText(PIX * pixd,PIX * pixs)1264 pixCopyText(PIX *pixd,
1265 PIX *pixs)
1266 {
1267 PROCNAME("pixCopyText");
1268
1269 if (!pixs)
1270 return ERROR_INT("pixs not defined", procName, 1);
1271 if (!pixd)
1272 return ERROR_INT("pixd not defined", procName, 1);
1273 if (pixs == pixd)
1274 return 0; /* no-op */
1275
1276 pixSetText(pixd, pixGetText(pixs));
1277 return 0;
1278 }
1279
1280
1281 PIXCMAP *
pixGetColormap(PIX * pix)1282 pixGetColormap(PIX *pix)
1283 {
1284 PROCNAME("pixGetColormap");
1285
1286 if (!pix)
1287 return (PIXCMAP *)ERROR_PTR("pix not defined", procName, NULL);
1288 return pix->colormap;
1289 }
1290
1291
1292 /*!
1293 * pixSetColormap()
1294 *
1295 * Input: pix
1296 * colormap (to be assigned)
1297 * Return: 0 if OK, 1 on error.
1298 *
1299 * Notes:
1300 * (1) Unlike with the pix data field, pixSetColormap() destroys
1301 * any existing colormap before assigning the new one.
1302 * Because colormaps are not ref counted, it is important that
1303 * the new colormap does not belong to any other pix.
1304 */
1305 l_int32
pixSetColormap(PIX * pix,PIXCMAP * colormap)1306 pixSetColormap(PIX *pix,
1307 PIXCMAP *colormap)
1308 {
1309 PROCNAME("pixSetColormap");
1310
1311 if (!pix)
1312 return ERROR_INT("pix not defined", procName, 1);
1313
1314 pixDestroyColormap(pix);
1315 pix->colormap = colormap;
1316 return 0;
1317 }
1318
1319
1320 /*!
1321 * pixDestroyColormap()
1322 *
1323 * Input: pix
1324 * Return: 0 if OK, 1 on error
1325 */
1326 l_int32
pixDestroyColormap(PIX * pix)1327 pixDestroyColormap(PIX *pix)
1328 {
1329 PIXCMAP *cmap;
1330
1331 PROCNAME("pixDestroyColormap");
1332
1333 if (!pix)
1334 return ERROR_INT("pix not defined", procName, 1);
1335
1336 if ((cmap = pix->colormap) != NULL) {
1337 pixcmapDestroy(&cmap);
1338 pix->colormap = NULL;
1339 }
1340 return 0;
1341 }
1342
1343
1344 /*!
1345 * pixGetData()
1346 *
1347 * Notes:
1348 * (1) This gives a new handle for the data. The data is still
1349 * owned by the pix, so do not call FREE() on it.
1350 */
1351 l_uint32 *
pixGetData(PIX * pix)1352 pixGetData(PIX *pix)
1353 {
1354 PROCNAME("pixGetData");
1355
1356 if (!pix)
1357 return (l_uint32 *)ERROR_PTR("pix not defined", procName, NULL);
1358 return pix->data;
1359 }
1360
1361
1362 /*!
1363 * pixSetData()
1364 *
1365 * Notes:
1366 * (1) This does not free any existing data. To free existing
1367 * data, use pixFreeData() before pixSetData().
1368 */
1369 l_int32
pixSetData(PIX * pix,l_uint32 * data)1370 pixSetData(PIX *pix,
1371 l_uint32 *data)
1372 {
1373 PROCNAME("pixSetData");
1374
1375 if (!pix)
1376 return ERROR_INT("pix not defined", procName, 1);
1377
1378 pix->data = data;
1379 return 0;
1380 }
1381
1382
1383 /*!
1384 * pixExtractData()
1385 *
1386 * Notes:
1387 * (1) This extracts the pix image data for use in another context.
1388 * The caller still needs to use pixDestroy() on the input pix.
1389 * (2) If refcount == 1, the data is extracted and the
1390 * pix->data ptr is set to NULL.
1391 * (3) If refcount > 1, this simply returns a copy of the data,
1392 * using the pix allocator, and leaving the input pix unchanged.
1393 */
1394 l_uint32 *
pixExtractData(PIX * pixs)1395 pixExtractData(PIX *pixs)
1396 {
1397 l_int32 count, bytes;
1398 l_uint32 *data, *datas;
1399
1400 PROCNAME("pixExtractData");
1401
1402 if (!pixs)
1403 return (l_uint32 *)ERROR_PTR("pixs not defined", procName, NULL);
1404
1405 count = pixGetRefcount(pixs);
1406 if (count == 1) { /* extract */
1407 data = pixGetData(pixs);
1408 pixSetData(pixs, NULL);
1409 }
1410 else { /* refcount > 1; copy */
1411 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
1412 datas = pixGetData(pixs);
1413 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL)
1414 return (l_uint32 *)ERROR_PTR("data not made", procName, NULL);
1415 memcpy((char *)data, (char *)datas, bytes);
1416 }
1417
1418 return data;
1419 }
1420
1421
1422 /*!
1423 * pixFreeData()
1424 *
1425 * Notes:
1426 * (1) This frees the data and sets the pix data ptr to null.
1427 * It should be used before pixSetData() in the situation where
1428 * you want to free any existing data before doing
1429 * a subsequent assignment with pixSetData().
1430 */
1431 l_int32
pixFreeData(PIX * pix)1432 pixFreeData(PIX *pix)
1433 {
1434 l_uint32 *data;
1435
1436 PROCNAME("pixFreeData");
1437
1438 if (!pix)
1439 return ERROR_INT("pix not defined", procName, 1);
1440
1441 if ((data = pixGetData(pix)) != NULL) {
1442 pix_free(data);
1443 pix->data = NULL;
1444 }
1445 return 0;
1446 }
1447
1448
1449 /*--------------------------------------------------------------------*
1450 * Pix line ptrs *
1451 *--------------------------------------------------------------------*/
1452 /*!
1453 * pixGetLinePtrs()
1454 *
1455 * Input: pix
1456 * &size (<optional return> array size, which is the pix height)
1457 * Return: array of line ptrs, or null on error
1458 *
1459 * Notes:
1460 * (1) This is intended to be used for fast random pixel access.
1461 * For example, for an 8 bpp image,
1462 * val = GET_DATA_BYTE(lines8[i], j);
1463 * is equivalent to, but much faster than,
1464 * pixGetPixel(pix, j, i, &val);
1465 * (2) How much faster? For 1 bpp, it's from 6 to 10x faster.
1466 * For 8 bpp, it's an amazing 30x faster. So if you are
1467 * doing random access over a substantial part of the image,
1468 * use this line ptr array.
1469 * (3) When random access is used in conjunction with a stack,
1470 * queue or heap, the overall computation time depends on
1471 * the operations performed on each struct that is popped
1472 * or pushed, and whether we are using a priority queue (O(logn))
1473 * or a queue or stack (O(1)). For example, for maze search,
1474 * the overall ratio of time for line ptrs vs. pixGet/Set* is
1475 * Maze type Type Time ratio
1476 * binary queue 0.4
1477 * gray heap (priority queue) 0.6
1478 * (4) Because this returns a void** and the accessors take void*,
1479 * the compiler cannot check the pointer types. It is
1480 * strongly recommended that you adopt a naming scheme for
1481 * the returned ptr arrays that indicates the pixel depth.
1482 * (This follows the original intent of Simonyi's "Hungarian"
1483 * application notation, where naming is used proactively
1484 * to make errors visibly obvious.) By doing this, you can
1485 * tell by inspection if the correct accessor is used.
1486 * For example, for an 8 bpp pixg:
1487 * void **lineg8 = pixGetLinePtrs(pixg, NULL);
1488 * val = GET_DATA_BYTE(lineg8[i], j); // fast access; BYTE, 8
1489 * ...
1490 * FREE(lineg8); // don't forget this
1491 */
1492 void **
pixGetLinePtrs(PIX * pix,l_int32 * psize)1493 pixGetLinePtrs(PIX *pix,
1494 l_int32 *psize)
1495 {
1496 l_int32 i, h, wpl;
1497 l_uint32 *data;
1498 void **lines;
1499
1500 PROCNAME("pixGetLinePtrs");
1501
1502 if (!pix)
1503 return (void **)ERROR_PTR("pix not defined", procName, NULL);
1504
1505 h = pixGetHeight(pix);
1506 if ((lines = (void **)CALLOC(h, sizeof(void *))) == NULL)
1507 return (void **)ERROR_PTR("lines not made", procName, NULL);
1508 wpl = pixGetWpl(pix);
1509 data = pixGetData(pix);
1510 for (i = 0; i < h; i++)
1511 lines[i] = (void *)(data + i * wpl);
1512
1513 return lines;
1514 }
1515
1516
1517 /*--------------------------------------------------------------------*
1518 * Print output for debugging *
1519 *--------------------------------------------------------------------*/
1520 /*!
1521 * pixPrintStreamInfo()
1522 *
1523 * Input: fp (file stream)
1524 * pix
1525 * text (<optional> identifying string; can be null)
1526 * Return: 0 if OK, 1 on error
1527 */
1528 l_int32
pixPrintStreamInfo(FILE * fp,PIX * pix,const char * text)1529 pixPrintStreamInfo(FILE *fp,
1530 PIX *pix,
1531 const char *text)
1532 {
1533 PIXCMAP *cmap;
1534
1535 PROCNAME("pixPrintStreamInfo");
1536
1537 if (!fp)
1538 return ERROR_INT("fp not defined", procName, 1);
1539 if (!pix)
1540 return ERROR_INT("pix not defined", procName, 1);
1541
1542 if (text)
1543 fprintf(fp, " Pix Info for %s:\n", text);
1544 fprintf(fp, " width = %d, height = %d, depth = %d\n",
1545 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix));
1546 fprintf(fp, " wpl = %d, data = %p, refcount = %d\n",
1547 pixGetWpl(pix), pixGetData(pix), pixGetRefcount(pix));
1548 if ((cmap = pixGetColormap(pix)) != NULL)
1549 pixcmapWriteStream(fp, cmap);
1550 else
1551 fprintf(fp, " no colormap\n");
1552
1553 return 0;
1554 }
1555