• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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