1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27 /*!
28 * \file pix1.c
29 * <pre>
30 *
31 * The pixN.c {N = 1,2,3,4,5} files are sorted by the type of operation.
32 * The primary functions in these files are:
33 *
34 * pix1.c: constructors, destructors and field accessors
35 * pix2.c: pixel poking of image, pad and border pixels
36 * pix3.c: masking and logical ops, counting, mirrored tiling
37 * pix4.c: histograms, statistics, fg/bg estimation
38 * pix5.c: property measurements, rectangle extraction
39 *
40 *
41 * This file has the basic constructors, destructors and field accessors
42 *
43 * Pix memory management (allows custom allocator and deallocator)
44 * static void *pix_malloc()
45 * static void pix_free()
46 * void setPixMemoryManager()
47 *
48 * Pix creation
49 * PIX *pixCreate()
50 * PIX *pixCreateNoInit()
51 * PIX *pixCreateTemplate()
52 * PIX *pixCreateTemplateNoInit()
53 * PIX *pixCreateHeader()
54 * PIX *pixClone()
55 *
56 * Pix destruction
57 * void pixDestroy()
58 * static void pixFree()
59 *
60 * Pix copy
61 * PIX *pixCopy()
62 * l_int32 pixResizeImageData()
63 * l_int32 pixCopyColormap()
64 * l_int32 pixSizesEqual()
65 * l_int32 pixTransferAllData()
66 * l_int32 pixSwapAndDestroy()
67 *
68 * Pix accessors
69 * l_int32 pixGetWidth()
70 * l_int32 pixSetWidth()
71 * l_int32 pixGetHeight()
72 * l_int32 pixSetHeight()
73 * l_int32 pixGetDepth()
74 * l_int32 pixSetDepth()
75 * l_int32 pixGetDimensions()
76 * l_int32 pixSetDimensions()
77 * l_int32 pixCopyDimensions()
78 * l_int32 pixGetSpp()
79 * l_int32 pixSetSpp()
80 * l_int32 pixCopySpp()
81 * l_int32 pixGetWpl()
82 * l_int32 pixSetWpl()
83 * l_int32 pixGetRefcount()
84 * l_int32 pixChangeRefcount()
85 * l_uint32 pixGetXRes()
86 * l_int32 pixSetXRes()
87 * l_uint32 pixGetYRes()
88 * l_int32 pixSetYRes()
89 * l_int32 pixGetResolution()
90 * l_int32 pixSetResolution()
91 * l_int32 pixCopyResolution()
92 * l_int32 pixScaleResolution()
93 * l_int32 pixGetInputFormat()
94 * l_int32 pixSetInputFormat()
95 * l_int32 pixCopyInputFormat()
96 * l_int32 pixSetSpecial()
97 * char *pixGetText()
98 * l_int32 pixSetText()
99 * l_int32 pixAddText()
100 * l_int32 pixCopyText()
101 * PIXCMAP *pixGetColormap()
102 * l_int32 pixSetColormap()
103 * l_int32 pixDestroyColormap()
104 * l_uint32 *pixGetData()
105 * l_int32 pixSetData()
106 * l_uint32 *pixExtractData()
107 * l_int32 pixFreeData()
108 *
109 * Pix line ptrs
110 * void **pixGetLinePtrs()
111 *
112 * Pix debug
113 * l_int32 pixPrintStreamInfo()
114 *
115 *
116 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
117 * Important notes on direct management of pix image data
118 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119 *
120 * Custom allocator and deallocator
121 * --------------------------------
122 *
123 * At the lowest level, you can specify the function that does the
124 * allocation and deallocation of the data field in the pix.
125 * By default, this is malloc and free. However, by calling
126 * setPixMemoryManager(), custom functions can be substituted.
127 * When using this, keep two things in mind:
128 *
129 * (1) Call setPixMemoryManager() before any pix have been allocated
130 * (2) Destroy all pix as usual, in order to prevent leaks.
131 *
132 * In pixalloc.c, we provide an example custom allocator and deallocator.
133 * To use it, you must call pmsCreate() before any pix have been allocated
134 * and pmsDestroy() at the end after all pix have been destroyed.
135 *
136 *
137 * Direct manipulation of the pix data field
138 * -----------------------------------------
139 *
140 * Memory management of the (image) data field in the pix is
141 * handled differently from that in the colormap or text fields.
142 * For colormap and text, the functions pixSetColormap() and
143 * pixSetText() remove the existing heap data and insert the
144 * new data. For the image data, pixSetData() just reassigns the
145 * data field; any existing data will be lost if there isn't
146 * another handle for it.
147 *
148 * Why is pixSetData() limited in this way? Because the image
149 * data can be very large, we need flexible ways to handle it,
150 * particularly when you want to re-use the data in a different
151 * context without making a copy. Here are some different
152 * things you might want to do:
153 *
154 * (1) Use pixCopy(pixd, pixs) where pixd is not the same size
155 * as pixs. This will remove the data in pixd, allocate a
156 * new data field in pixd, and copy the data from pixs, leaving
157 * pixs unchanged.
158 *
159 * (2) Use pixTransferAllData(pixd, &pixs, ...) to transfer the
160 * data from pixs to pixd without making a copy of it. If
161 * pixs is not cloned, this will do the transfer and destroy pixs.
162 * But if the refcount of pixs is greater than 1, it just copies
163 * the data and decrements the ref count.
164 *
165 * (3) Use pixSwapAndDestroy(pixd, &pixs) to replace pixs by an
166 * existing pixd. This is similar to pixTransferAllData(), but
167 * simpler, in that it never makes any copies and if pixs is
168 * cloned, the other references are not changed by this operation.
169 *
170 * (4) Use pixExtractData() to extract the image data from the pix
171 * without copying if possible. This could be used, for example,
172 * to convert from a pix to some other data structure with minimal
173 * heap allocation. After the data is extracated, the pixels can
174 * be munged and used in another context. However, the danger
175 * here is that the pix might have a refcount > 1, in which case
176 * a copy of the data must be made and the input pix left unchanged.
177 * If there are no clones, the image data can be extracted without
178 * a copy, and the data ptr in the pix must be nulled before
179 * destroying it because the pix will no longer 'own' the data.
180 *
181 * We have provided accessors and functions here that should be
182 * sufficient so that you can do anything you want without
183 * explicitly referencing any of the pix member fields.
184 *
185 * However, to avoid memory smashes and leaks when doing special operations
186 * on the pix data field, look carefully at the behavior of the image
187 * data accessors and keep in mind that when you invoke pixDestroy(),
188 * the pix considers itself the owner of all its heap data.
189 * </pre>
190 */
191
192 #include <string.h>
193 #include "allheaders.h"
194
195 static void pixFree(PIX *pix);
196
197
198 /*-------------------------------------------------------------------------*
199 * Pix Memory Management *
200 * *
201 * These functions give you the freedom to specify at compile or run *
202 * time the allocator and deallocator to be used for pix. It has no *
203 * effect on memory management for other data structs, which are *
204 * controlled by the #defines in environ.h. Likewise, the #defines *
205 * in environ.h have no effect on the pix memory management. *
206 * The default functions are malloc and free. Use setPixMemoryManager() *
207 * to specify other functions to use. *
208 *-------------------------------------------------------------------------*/
209
210 /*! Pix memory manager */
211 /*
212 * <pre>
213 * Notes:
214 * (1) The allocator and deallocator function types,
215 * alloc_fn and dealloc_fn, are defined in pix.h.
216 * </pre>
217 */
218 struct PixMemoryManager
219 {
220 alloc_fn allocator;
221 dealloc_fn deallocator;
222 };
223
224 /*! Default Pix memory manager */
225 static struct PixMemoryManager pix_mem_manager = {
226 &malloc,
227 &free
228 };
229
230 static void *
pix_malloc(size_t size)231 pix_malloc(size_t size)
232 {
233 #ifndef _MSC_VER
234 return (*pix_mem_manager.allocator)(size);
235 #else /* _MSC_VER */
236 /* Under MSVC++, pix_mem_manager is initialized after a call
237 * to pix_malloc. Just ignore the custom allocator feature. */
238 return malloc(size);
239 #endif /* _MSC_VER */
240 }
241
242 static void
pix_free(void * ptr)243 pix_free(void *ptr)
244 {
245 #ifndef _MSC_VER
246 (*pix_mem_manager.deallocator)(ptr);
247 return;
248 #else /* _MSC_VER */
249 /* Under MSVC++, pix_mem_manager is initialized after a call
250 * to pix_malloc. Just ignore the custom allocator feature. */
251 free(ptr);
252 return;
253 #endif /* _MSC_VER */
254 }
255
256 /*!
257 * \brief setPixMemoryManager()
258 *
259 * \param[in] allocator [optional]; use NULL to skip
260 * \param[in] deallocator [optional]; use NULL to skip
261 * \return void
262 *
263 * <pre>
264 * Notes:
265 * (1) Use this to change the alloc and/or dealloc functions;
266 * e.g., setPixMemoryManager(my_malloc, my_free).
267 * (2) The C99 standard (section 6.7.5.3, par. 8) says:
268 * A declaration of a parameter as "function returning type"
269 * shall be adjusted to "pointer to function returning type"
270 * so that it can be in either of these two forms:
271 * (a) type (function-ptr(type, ...))
272 * (b) type ((*function-ptr)(type, ...))
273 * because form (a) is implictly converted to form (b), as in the
274 * definition of struct PixMemoryManager above. So, for example,
275 * we should be able to declare either of these:
276 * (a) void *(allocator(size_t))
277 * (b) void *((*allocator)(size_t))
278 * However, MSVC++ only accepts the second version.
279 * </pre>
280 */
281 void
setPixMemoryManager(alloc_fn allocator,dealloc_fn deallocator)282 setPixMemoryManager(alloc_fn allocator,
283 dealloc_fn deallocator)
284 {
285 if (allocator) pix_mem_manager.allocator = allocator;
286 if (deallocator) pix_mem_manager.deallocator = deallocator;
287 return;
288 }
289
290
291 /*--------------------------------------------------------------------*
292 * Pix Creation *
293 *--------------------------------------------------------------------*/
294 /*!
295 * \brief pixCreate()
296 *
297 * \param[in] width, height, depth
298 * \return pixd with data allocated and initialized to 0,
299 * or NULL on error
300 */
301 PIX *
pixCreate(l_int32 width,l_int32 height,l_int32 depth)302 pixCreate(l_int32 width,
303 l_int32 height,
304 l_int32 depth)
305 {
306 PIX *pixd;
307
308 PROCNAME("pixCreate");
309
310 if ((pixd = pixCreateNoInit(width, height, depth)) == NULL)
311 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
312 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h);
313 return pixd;
314 }
315
316
317 /*!
318 * \brief pixCreateNoInit()
319 *
320 * \param[in] width, height, depth
321 * \return pixd with data allocated but not initialized,
322 * or NULL on error
323 *
324 * <pre>
325 * Notes:
326 * (1) Must set pad bits to avoid reading unitialized data, because
327 * some optimized routines (e.g., pixConnComp()) read from pad bits.
328 * </pre>
329 */
330 PIX *
pixCreateNoInit(l_int32 width,l_int32 height,l_int32 depth)331 pixCreateNoInit(l_int32 width,
332 l_int32 height,
333 l_int32 depth)
334 {
335 l_int32 wpl;
336 PIX *pixd;
337 l_uint32 *data;
338
339 PROCNAME("pixCreateNoInit");
340 if ((pixd = pixCreateHeader(width, height, depth)) == NULL)
341 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
342 wpl = pixGetWpl(pixd);
343 if ((data = (l_uint32 *)pix_malloc(4LL * wpl * height)) == NULL) {
344 pixDestroy(&pixd);
345 return (PIX *)ERROR_PTR("pix_malloc fail for data", procName, NULL);
346 }
347 pixSetData(pixd, data);
348 pixSetPadBits(pixd, 0);
349 return pixd;
350 }
351
352
353 /*!
354 * \brief pixCreateTemplate()
355 *
356 * \param[in] pixs
357 * \return pixd, or NULL on error
358 *
359 * <pre>
360 * Notes:
361 * (1) Makes a Pix of the same size as the input Pix, with the
362 * data array allocated and initialized to 0.
363 * (2) Copies the other fields, including colormap if it exists.
364 * </pre>
365 */
366 PIX *
pixCreateTemplate(PIX * pixs)367 pixCreateTemplate(PIX *pixs)
368 {
369 PIX *pixd;
370
371 PROCNAME("pixCreateTemplate");
372
373 if (!pixs)
374 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
375
376 if ((pixd = pixCreateTemplateNoInit(pixs)) == NULL)
377 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
378 memset(pixd->data, 0, 4 * pixd->wpl * pixd->h);
379 return pixd;
380 }
381
382
383 /*!
384 * \brief pixCreateTemplateNoInit()
385 *
386 * \param[in] pixs
387 * \return pixd, or NULL on error
388 *
389 * <pre>
390 * Notes:
391 * (1) Makes a Pix of the same size as the input Pix, with
392 * the data array allocated but not initialized to 0.
393 * (2) Copies the other fields, including colormap if it exists.
394 * </pre>
395 */
396 PIX *
pixCreateTemplateNoInit(PIX * pixs)397 pixCreateTemplateNoInit(PIX *pixs)
398 {
399 l_int32 w, h, d;
400 PIX *pixd;
401
402 PROCNAME("pixCreateTemplateNoInit");
403
404 if (!pixs)
405 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
406
407 pixGetDimensions(pixs, &w, &h, &d);
408 if ((pixd = pixCreateNoInit(w, h, d)) == NULL)
409 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
410 pixCopySpp(pixd, pixs);
411 pixCopyResolution(pixd, pixs);
412 pixCopyColormap(pixd, pixs);
413 pixCopyText(pixd, pixs);
414 pixCopyInputFormat(pixd, pixs);
415 return pixd;
416 }
417
418
419 /*!
420 * \brief pixCreateHeader()
421 *
422 * \param[in] width, height, depth
423 * \return pixd with no data allocated, or NULL on error
424 *
425 * <pre>
426 * Notes:
427 * (1) It is assumed that all 32 bit pix have 3 spp. If there is
428 * a valid alpha channel, this will be set to 4 spp later.
429 * (2) If the number of bytes to be allocated is larger than the
430 * maximum value in an int32, we can get overflow, resulting
431 * in a smaller amount of memory actually being allocated.
432 * Later, an attempt to access memory that wasn't allocated will
433 * cause a crash. So to avoid crashing a program (or worse)
434 * with bad (or malicious) input, this is where we limit the
435 * requested allocation of image data in a typesafe way.
436 * </pre>
437 */
438 PIX *
pixCreateHeader(l_int32 width,l_int32 height,l_int32 depth)439 pixCreateHeader(l_int32 width,
440 l_int32 height,
441 l_int32 depth)
442 {
443 l_int32 wpl;
444 l_uint64 wpl64, bignum;
445 PIX *pixd;
446
447 PROCNAME("pixCreateHeader");
448
449 if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8)
450 && (depth != 16) && (depth != 24) && (depth != 32))
451 return (PIX *)ERROR_PTR("depth must be {1, 2, 4, 8, 16, 24, 32}",
452 procName, NULL);
453 if (width <= 0)
454 return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
455 if (height <= 0)
456 return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
457
458 /* Avoid overflow in malloc arg, malicious or otherwise */
459 wpl = 0;
460 wpl64 = ((l_uint64)width * (l_uint64)depth + 31) / 32;
461 if (wpl64 > ((1LL << 29) - 1)) {
462 L_ERROR("requested w = %d, h = %d, d = %d\n",
463 procName, width, height, depth);
464 return (PIX *)ERROR_PTR("wpl >= 2^29", procName, NULL);
465 } else {
466 wpl = (l_int32)wpl64;
467 }
468 bignum = 4L * wpl * height; /* number of bytes to be requested */
469 if (bignum > ((1LL << 31) - 1)) {
470 L_ERROR("requested w = %d, h = %d, d = %d\n",
471 procName, width, height, depth);
472 return (PIX *)ERROR_PTR("requested bytes >= 2^31", procName, NULL);
473 }
474
475 if ((pixd = (PIX *)LEPT_CALLOC(1, sizeof(PIX))) == NULL)
476 return (PIX *)ERROR_PTR("LEPT_CALLOC fail for pixd", procName, NULL);
477 pixSetWidth(pixd, width);
478 pixSetHeight(pixd, height);
479 pixSetDepth(pixd, depth);
480 pixSetWpl(pixd, wpl);
481 if (depth == 24 || depth == 32)
482 pixSetSpp(pixd, 3);
483 else
484 pixSetSpp(pixd, 1);
485
486 pixd->refcount = 1;
487 pixd->informat = IFF_UNKNOWN;
488 return pixd;
489 }
490
491
492 /*!
493 * \brief pixClone()
494 *
495 * \param[in] pixs
496 * \return same pix ptr, or NULL on error
497 *
498 * <pre>
499 * Notes:
500 * (1) A "clone" is simply a handle (ptr) to an existing pix.
501 * It is implemented because (a) images can be large and
502 * hence expensive to copy, and (b) extra handles to a data
503 * structure need to be made with a simple policy to avoid
504 * both double frees and memory leaks. Pix are reference
505 * counted. The side effect of pixClone() is an increase
506 * by 1 in the ref count.
507 * (2) The protocol to be used is:
508 * (a) Whenever you want a new handle to an existing image,
509 * call pixClone(), which just bumps a ref count.
510 * (b) Always call pixDestroy() on all handles. This
511 * decrements the ref count, nulls the handle, and
512 * only destroys the pix when pixDestroy() has been
513 * called on all handles.
514 * </pre>
515 */
516 PIX *
pixClone(PIX * pixs)517 pixClone(PIX *pixs)
518 {
519 PROCNAME("pixClone");
520
521 if (!pixs)
522 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
523 pixChangeRefcount(pixs, 1);
524
525 return pixs;
526 }
527
528
529 /*--------------------------------------------------------------------*
530 * Pix Destruction *
531 *--------------------------------------------------------------------*/
532 /*!
533 * \brief pixDestroy()
534 *
535 * \param[in,out] ppix will be nulled
536 * \return void
537 *
538 * <pre>
539 * Notes:
540 * (1) Decrements the ref count and, if 0, destroys the pix.
541 * (2) Always nulls the input ptr.
542 * </pre>
543 */
544 void
pixDestroy(PIX ** ppix)545 pixDestroy(PIX **ppix)
546 {
547 PIX *pix;
548
549 PROCNAME("pixDestroy");
550
551 if (!ppix) {
552 L_WARNING("ptr address is null!\n", procName);
553 return;
554 }
555
556 if ((pix = *ppix) == NULL)
557 return;
558 pixFree(pix);
559 *ppix = NULL;
560 return;
561 }
562
563
564 /*!
565 * \brief pixFree()
566 *
567 * \param[in] pix
568 * \return void
569 *
570 * <pre>
571 * Notes:
572 * (1) Decrements the ref count and, if 0, destroys the pix.
573 * </pre>
574 */
575 static void
pixFree(PIX * pix)576 pixFree(PIX *pix)
577 {
578 l_uint32 *data;
579 char *text;
580
581 if (!pix) return;
582
583 pixChangeRefcount(pix, -1);
584 if (pixGetRefcount(pix) <= 0) {
585 if ((data = pixGetData(pix)) != NULL)
586 pix_free(data);
587 if ((text = pixGetText(pix)) != NULL)
588 LEPT_FREE(text);
589 pixDestroyColormap(pix);
590 LEPT_FREE(pix);
591 }
592 return;
593 }
594
595
596 /*-------------------------------------------------------------------------*
597 * Pix Copy *
598 *-------------------------------------------------------------------------*/
599 /*!
600 * \brief pixCopy()
601 *
602 * \param[in] pixd [optional]; can be null, or equal to pixs,
603 * or different from pixs
604 * \param[in] pixs
605 * \return pixd, or NULL on error
606 *
607 * <pre>
608 * Notes:
609 * (1) There are three cases:
610 * (a) pixd == null (makes a new pix; refcount = 1)
611 * (b) pixd == pixs (no-op)
612 * (c) pixd != pixs (data copy; no change in refcount)
613 * If the refcount of pixd > 1, case (c) will side-effect
614 * these handles.
615 * (2) The general pattern of use is:
616 * pixd = pixCopy(pixd, pixs);
617 * This will work for all three cases.
618 * For clarity when the case is known, you can use:
619 * (a) pixd = pixCopy(NULL, pixs);
620 * (c) pixCopy(pixd, pixs);
621 * (3) For case (c), we check if pixs and pixd are the same
622 * size (w,h,d). If so, the data is copied directly.
623 * Otherwise, the data is reallocated to the correct size
624 * and the copy proceeds. The refcount of pixd is unchanged.
625 * (4) This operation, like all others that may involve a pre-existing
626 * pixd, will side-effect any existing clones of pixd.
627 * </pre>
628 */
629 PIX *
pixCopy(PIX * pixd,PIX * pixs)630 pixCopy(PIX *pixd, /* can be null */
631 PIX *pixs)
632 {
633 l_int32 bytes;
634 l_uint32 *datas, *datad;
635
636 PROCNAME("pixCopy");
637
638 if (!pixs)
639 return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
640 if (pixs == pixd)
641 return pixd;
642
643 /* Total bytes in image data */
644 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
645
646 /* If we're making a new pix ... */
647 if (!pixd) {
648 if ((pixd = pixCreateTemplate(pixs)) == NULL)
649 return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
650 datas = pixGetData(pixs);
651 datad = pixGetData(pixd);
652 memcpy((char *)datad, (char *)datas, bytes);
653 return pixd;
654 }
655
656 /* Reallocate image data if sizes are different. If this fails,
657 * pixd hasn't been changed. But we want to signal that the copy
658 * failed, so return NULL. This will cause a memory leak if the
659 * return ptr is assigned to pixd, but that is preferred to proceeding
660 * with an incorrect pixd, and in any event this use case of
661 * pixCopy() -- reallocating into an existing pix -- is infrequent. */
662 if (pixResizeImageData(pixd, pixs) == 1)
663 return (PIX *)ERROR_PTR("reallocation of data failed", procName, NULL);
664
665 /* Copy non-image data fields */
666 pixCopyColormap(pixd, pixs);
667 pixCopySpp(pixd, pixs);
668 pixCopyResolution(pixd, pixs);
669 pixCopyInputFormat(pixd, pixs);
670 pixCopyText(pixd, pixs);
671
672 /* Copy image data */
673 datas = pixGetData(pixs);
674 datad = pixGetData(pixd);
675 memcpy((char*)datad, (char*)datas, bytes);
676 return pixd;
677 }
678
679
680 /*!
681 * \brief pixResizeImageData()
682 *
683 * \param[in] pixd gets new uninitialized buffer for image data
684 * \param[in] pixs determines the size of the buffer; not changed
685 * \return 0 if OK, 1 on error
686 *
687 * <pre>
688 * Notes:
689 * (1) If the sizes of data in pixs and pixd are unequal, this
690 * frees the existing image data in pixd and allocates
691 * an uninitialized buffer that will hold the required amount
692 * of image data in pixs. The image data from pixs is not
693 * copied into the new buffer.
694 * (2) On failure to allocate, pixd is unchanged.
695 * </pre>
696 */
697 l_int32
pixResizeImageData(PIX * pixd,PIX * pixs)698 pixResizeImageData(PIX *pixd,
699 PIX *pixs)
700 {
701 l_int32 w, h, d, wpl, bytes;
702 l_uint32 *data;
703
704 PROCNAME("pixResizeImageData");
705
706 if (!pixs)
707 return ERROR_INT("pixs not defined", procName, 1);
708 if (!pixd)
709 return ERROR_INT("pixd not defined", procName, 1);
710
711 if (pixSizesEqual(pixs, pixd)) /* nothing to do */
712 return 0;
713
714 /* Make sure we can copy the data */
715 pixGetDimensions(pixs, &w, &h, &d);
716 wpl = pixGetWpl(pixs);
717 bytes = 4 * wpl * h;
718 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL)
719 return ERROR_INT("pix_malloc fail for data", procName, 1);
720
721 /* OK, do it */
722 pixSetWidth(pixd, w);
723 pixSetHeight(pixd, h);
724 pixSetDepth(pixd, d);
725 pixSetWpl(pixd, wpl);
726 pixFreeData(pixd); /* free any existing image data */
727 pixSetData(pixd, data); /* set the uninitialized memory buffer */
728 pixCopyResolution(pixd, pixs);
729 return 0;
730 }
731
732
733 /*!
734 * \brief pixCopyColormap()
735 *
736 * \param[in] pixd, pixs dest and src Pix
737 * \return 0 if OK, 1 on error
738 *
739 * <pre>
740 * Notes:
741 * (1) This always destroys any colormap in pixd (except if
742 * the operation is a no-op.
743 * </pre>
744 */
745 l_int32
pixCopyColormap(PIX * pixd,PIX * pixs)746 pixCopyColormap(PIX *pixd,
747 PIX *pixs)
748 {
749 PIXCMAP *cmaps, *cmapd;
750
751 PROCNAME("pixCopyColormap");
752
753 if (!pixs)
754 return ERROR_INT("pixs not defined", procName, 1);
755 if (!pixd)
756 return ERROR_INT("pixd not defined", procName, 1);
757 if (pixs == pixd)
758 return 0; /* no-op */
759
760 pixDestroyColormap(pixd);
761 if ((cmaps = pixGetColormap(pixs)) == NULL) /* not an error */
762 return 0;
763
764 if ((cmapd = pixcmapCopy(cmaps)) == NULL)
765 return ERROR_INT("cmapd not made", procName, 1);
766 pixSetColormap(pixd, cmapd);
767
768 return 0;
769 }
770
771
772 /*!
773 * \brief pixSizesEqual()
774 *
775 * \param[in] pix1, pix2 two pix
776 * \return 1 if the two pix have same {h, w, d}; 0 otherwise.
777 */
778 l_int32
pixSizesEqual(PIX * pix1,PIX * pix2)779 pixSizesEqual(PIX *pix1,
780 PIX *pix2)
781 {
782 PROCNAME("pixSizesEqual");
783
784 if (!pix1 || !pix2)
785 return ERROR_INT("pix1 and pix2 not both defined", procName, 0);
786
787 if (pix1 == pix2)
788 return 1;
789
790 if ((pixGetWidth(pix1) != pixGetWidth(pix2)) ||
791 (pixGetHeight(pix1) != pixGetHeight(pix2)) ||
792 (pixGetDepth(pix1) != pixGetDepth(pix2)))
793 return 0;
794 else
795 return 1;
796 }
797
798
799 /*!
800 * \brief pixTransferAllData()
801 *
802 * \param[in] pixd must be different from pixs
803 * \param[in,out] ppixs will be nulled if refcount goes to 0
804 * \param[in] copytext 1 to copy the text field; 0 to skip
805 * \param[in] copyformat 1 to copy the informat field; 0 to skip
806 * \return 0 if OK, 1 on error
807 *
808 * <pre>
809 * Notes:
810 * (1) This does a complete data transfer from pixs to pixd,
811 * followed by the destruction of pixs (refcount permitting).
812 * (2) If the refcount of pixs is 1, pixs is destroyed. Otherwise,
813 * the data in pixs is copied (rather than transferred) to pixd.
814 * (3) This operation, like all others with a pre-existing pixd,
815 * will side-effect any existing clones of pixd. The pixd
816 * refcount does not change.
817 * (4) When might you use this? Suppose you have an in-place Pix
818 * function (returning void) with the typical signature:
819 * void function-inplace(PIX *pix, ...)
820 * where "..." are non-pointer input parameters, and suppose
821 * further that you sometimes want to return an arbitrary Pix
822 * in place of the input Pix. There are two ways you can do this:
823 * (a) The straightforward way is to change the function
824 * signature to take the address of the Pix ptr:
825 * \code
826 * void function-inplace(PIX **ppix, ...) {
827 * PIX *pixt = function-makenew(*ppix);
828 * pixDestroy(ppix);
829 * *ppix = pixt;
830 * return;
831 * }
832 * \endcode
833 * Here, the input and returned pix are different, as viewed
834 * by the calling function, and the inplace function is
835 * expected to destroy the input pix to avoid a memory leak.
836 * (b) Keep the signature the same and use pixTransferAllData()
837 * to return the new Pix in the input Pix struct:
838 * \code
839 * void function-inplace(PIX *pix, ...) {
840 * PIX *pixt = function-makenew(pix);
841 * pixTransferAllData(pix, &pixt, 0, 0);
842 * // pixDestroy() is called on pixt
843 * return;
844 * }
845 * \endcode
846 * Here, the input and returned pix are the same, as viewed
847 * by the calling function, and the inplace function must
848 * never destroy the input pix, because the calling function
849 * maintains an unchanged handle to it.
850 * </pre>
851 */
852 l_int32
pixTransferAllData(PIX * pixd,PIX ** ppixs,l_int32 copytext,l_int32 copyformat)853 pixTransferAllData(PIX *pixd,
854 PIX **ppixs,
855 l_int32 copytext,
856 l_int32 copyformat)
857 {
858 l_int32 nbytes;
859 PIX *pixs;
860
861 PROCNAME("pixTransferAllData");
862
863 if (!ppixs)
864 return ERROR_INT("&pixs not defined", procName, 1);
865 if ((pixs = *ppixs) == NULL)
866 return ERROR_INT("pixs not defined", procName, 1);
867 if (!pixd)
868 return ERROR_INT("pixd not defined", procName, 1);
869 if (pixs == pixd) /* no-op */
870 return ERROR_INT("pixd == pixs", procName, 1);
871
872 if (pixGetRefcount(pixs) == 1) { /* transfer the data, cmap, text */
873 pixFreeData(pixd); /* dealloc any existing data */
874 pixSetData(pixd, pixGetData(pixs)); /* transfer new data from pixs */
875 pixs->data = NULL; /* pixs no longer owns data */
876 pixSetColormap(pixd, pixGetColormap(pixs)); /* frees old; sets new */
877 pixs->colormap = NULL; /* pixs no longer owns colormap */
878 if (copytext) {
879 pixSetText(pixd, pixGetText(pixs));
880 pixSetText(pixs, NULL);
881 }
882 } else { /* preserve pixs by making a copy of the data, cmap, text */
883 pixResizeImageData(pixd, pixs);
884 nbytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
885 memcpy((char *)pixGetData(pixd), (char *)pixGetData(pixs), nbytes);
886 pixCopyColormap(pixd, pixs);
887 if (copytext)
888 pixCopyText(pixd, pixs);
889 }
890
891 pixCopySpp(pixd, pixs);
892 pixCopyResolution(pixd, pixs);
893 pixCopyDimensions(pixd, pixs);
894 if (copyformat)
895 pixCopyInputFormat(pixd, pixs);
896
897 /* This will destroy pixs if data was transferred;
898 * otherwise, it just decrements its refcount. */
899 pixDestroy(ppixs);
900 return 0;
901 }
902
903
904 /*!
905 * \brief pixSwapAndDestroy()
906 *
907 * \param[out] ppixd [optional] input pixd can be null,
908 * and it must be different from pixs
909 * \param[in,out] ppixs will be nulled after the swap
910 * \return 0 if OK, 1 on error
911 *
912 * <pre>
913 * Notes:
914 * (1) Simple operation to change the handle name safely.
915 * After this operation, the original image in pixd has
916 * been destroyed, pixd points to what was pixs, and
917 * the input pixs ptr has been nulled.
918 * (2) This works safely whether or not pixs and pixd are cloned.
919 * If pixs is cloned, the other handles still point to
920 * the original image, with the ref count reduced by 1.
921 * (3) Usage example:
922 * \code
923 * Pix *pix1 = pixRead("...");
924 * Pix *pix2 = function(pix1, ...);
925 * pixSwapAndDestroy(&pix1, &pix2);
926 * pixDestroy(&pix1); // holds what was in pix2
927 * \endcode
928 * Example with clones ([] shows ref count of image generated
929 * by the function):
930 * \code
931 * Pix *pixs = pixRead("...");
932 * Pix *pix1 = pixClone(pixs);
933 * Pix *pix2 = function(pix1, ...); [1]
934 * Pix *pix3 = pixClone(pix2); [1] --> [2]
935 * pixSwapAndDestroy(&pix1, &pix2);
936 * pixDestroy(&pixs); // still holds read image
937 * pixDestroy(&pix1); // holds what was in pix2 [2] --> [1]
938 * pixDestroy(&pix3); // holds what was in pix2 [1] --> [0]
939 * \endcode
940 * </pre>
941 */
942 l_int32
pixSwapAndDestroy(PIX ** ppixd,PIX ** ppixs)943 pixSwapAndDestroy(PIX **ppixd,
944 PIX **ppixs)
945 {
946 PROCNAME("pixSwapAndDestroy");
947
948 if (!ppixd)
949 return ERROR_INT("&pixd not defined", procName, 1);
950 if (!ppixs)
951 return ERROR_INT("&pixs not defined", procName, 1);
952 if (*ppixs == NULL)
953 return ERROR_INT("pixs not defined", procName, 1);
954 if (ppixs == ppixd) /* no-op */
955 return ERROR_INT("&pixd == &pixs", procName, 1);
956
957 pixDestroy(ppixd);
958 *ppixd = pixClone(*ppixs);
959 pixDestroy(ppixs);
960 return 0;
961 }
962
963
964 /*--------------------------------------------------------------------*
965 * Accessors *
966 *--------------------------------------------------------------------*/
967 l_int32
pixGetWidth(PIX * pix)968 pixGetWidth(PIX *pix)
969 {
970 PROCNAME("pixGetWidth");
971
972 if (!pix)
973 return ERROR_INT("pix not defined", procName, 0);
974
975 return pix->w;
976 }
977
978
979 l_int32
pixSetWidth(PIX * pix,l_int32 width)980 pixSetWidth(PIX *pix,
981 l_int32 width)
982 {
983 PROCNAME("pixSetWidth");
984
985 if (!pix)
986 return ERROR_INT("pix not defined", procName, 1);
987 if (width < 0) {
988 pix->w = 0;
989 return ERROR_INT("width must be >= 0", procName, 1);
990 }
991
992 pix->w = width;
993 return 0;
994 }
995
996
997 l_int32
pixGetHeight(PIX * pix)998 pixGetHeight(PIX *pix)
999 {
1000 PROCNAME("pixGetHeight");
1001
1002 if (!pix)
1003 return ERROR_INT("pix not defined", procName, 0);
1004
1005 return pix->h;
1006 }
1007
1008
1009 l_int32
pixSetHeight(PIX * pix,l_int32 height)1010 pixSetHeight(PIX *pix,
1011 l_int32 height)
1012 {
1013 PROCNAME("pixSetHeight");
1014
1015 if (!pix)
1016 return ERROR_INT("pix not defined", procName, 1);
1017 if (height < 0) {
1018 pix->h = 0;
1019 return ERROR_INT("h must be >= 0", procName, 1);
1020 }
1021
1022 pix->h = height;
1023 return 0;
1024 }
1025
1026
1027 l_int32
pixGetDepth(PIX * pix)1028 pixGetDepth(PIX *pix)
1029 {
1030 PROCNAME("pixGetDepth");
1031
1032 if (!pix)
1033 return ERROR_INT("pix not defined", procName, 0);
1034
1035 return pix->d;
1036 }
1037
1038
1039 l_int32
pixSetDepth(PIX * pix,l_int32 depth)1040 pixSetDepth(PIX *pix,
1041 l_int32 depth)
1042 {
1043 PROCNAME("pixSetDepth");
1044
1045 if (!pix)
1046 return ERROR_INT("pix not defined", procName, 1);
1047 if (depth < 1)
1048 return ERROR_INT("d must be >= 1", procName, 1);
1049
1050 pix->d = depth;
1051 return 0;
1052 }
1053
1054
1055 /*!
1056 * \brief pixGetDimensions()
1057 *
1058 * \param[in] pix
1059 * \param[out] pw, ph, pd [optional] each can be null
1060 * \return 0 if OK, 1 on error
1061 */
1062 l_int32
pixGetDimensions(PIX * pix,l_int32 * pw,l_int32 * ph,l_int32 * pd)1063 pixGetDimensions(PIX *pix,
1064 l_int32 *pw,
1065 l_int32 *ph,
1066 l_int32 *pd)
1067 {
1068 PROCNAME("pixGetDimensions");
1069
1070 if (pw) *pw = 0;
1071 if (ph) *ph = 0;
1072 if (pd) *pd = 0;
1073 if (!pix)
1074 return ERROR_INT("pix not defined", procName, 1);
1075 if (pw) *pw = pix->w;
1076 if (ph) *ph = pix->h;
1077 if (pd) *pd = pix->d;
1078 return 0;
1079 }
1080
1081
1082 /*!
1083 * \brief pixSetDimensions()
1084 *
1085 * \param[in] pix
1086 * \param[in] w, h, d use 0 to skip the setting for any of these
1087 * \return 0 if OK, 1 on error
1088 */
1089 l_int32
pixSetDimensions(PIX * pix,l_int32 w,l_int32 h,l_int32 d)1090 pixSetDimensions(PIX *pix,
1091 l_int32 w,
1092 l_int32 h,
1093 l_int32 d)
1094 {
1095 PROCNAME("pixSetDimensions");
1096
1097 if (!pix)
1098 return ERROR_INT("pix not defined", procName, 1);
1099 if (w > 0) pixSetWidth(pix, w);
1100 if (h > 0) pixSetHeight(pix, h);
1101 if (d > 0) pixSetDepth(pix, d);
1102 return 0;
1103 }
1104
1105
1106 /*!
1107 * \brief pixCopyDimensions()
1108 *
1109 * \param[in] pixd
1110 * \param[in] pixd
1111 * \return 0 if OK, 1 on error
1112 */
1113 l_int32
pixCopyDimensions(PIX * pixd,PIX * pixs)1114 pixCopyDimensions(PIX *pixd,
1115 PIX *pixs)
1116 {
1117 PROCNAME("pixCopyDimensions");
1118
1119 if (!pixd)
1120 return ERROR_INT("pixd not defined", procName, 1);
1121 if (!pixs)
1122 return ERROR_INT("pixs not defined", procName, 1);
1123 if (pixs == pixd)
1124 return 0; /* no-op */
1125
1126 pixSetWidth(pixd, pixGetWidth(pixs));
1127 pixSetHeight(pixd, pixGetHeight(pixs));
1128 pixSetDepth(pixd, pixGetDepth(pixs));
1129 pixSetWpl(pixd, pixGetWpl(pixs));
1130 return 0;
1131 }
1132
1133
1134 l_int32
pixGetSpp(PIX * pix)1135 pixGetSpp(PIX *pix)
1136 {
1137 PROCNAME("pixGetSpp");
1138
1139 if (!pix)
1140 return ERROR_INT("pix not defined", procName, 0);
1141
1142 return pix->spp;
1143 }
1144
1145
1146 /*
1147 * pixSetSpp()
1148 * Input: pix
1149 * spp (1, 3 or 4)
1150 * Return: 0 if OK, 1 on error
1151 *
1152 * Notes:
1153 * (1) For a 32 bpp pix, this can be used to ignore the
1154 * alpha sample (spp == 3) or to use it (spp == 4).
1155 * For example, to write a spp == 4 image without the alpha
1156 * sample (as an rgb pix), call pixSetSpp(pix, 3) and
1157 * then write it out as a png.
1158 */
1159 l_int32
pixSetSpp(PIX * pix,l_int32 spp)1160 pixSetSpp(PIX *pix,
1161 l_int32 spp)
1162 {
1163 PROCNAME("pixSetSpp");
1164
1165 if (!pix)
1166 return ERROR_INT("pix not defined", procName, 1);
1167 if (spp < 1)
1168 return ERROR_INT("spp must be >= 1", procName, 1);
1169
1170 pix->spp = spp;
1171 return 0;
1172 }
1173
1174
1175 /*!
1176 * \brief pixCopySpp()
1177 *
1178 * \param[in] pixd
1179 * \param[in] pixs
1180 * \return 0 if OK, 1 on error
1181 */
1182 l_int32
pixCopySpp(PIX * pixd,PIX * pixs)1183 pixCopySpp(PIX *pixd,
1184 PIX *pixs)
1185 {
1186 PROCNAME("pixCopySpp");
1187
1188 if (!pixd)
1189 return ERROR_INT("pixd not defined", procName, 1);
1190 if (!pixs)
1191 return ERROR_INT("pixs not defined", procName, 1);
1192 if (pixs == pixd)
1193 return 0; /* no-op */
1194
1195 pixSetSpp(pixd, pixGetSpp(pixs));
1196 return 0;
1197 }
1198
1199
1200 l_int32
pixGetWpl(PIX * pix)1201 pixGetWpl(PIX *pix)
1202 {
1203 PROCNAME("pixGetWpl");
1204
1205 if (!pix)
1206 return ERROR_INT("pix not defined", procName, 0);
1207 return pix->wpl;
1208 }
1209
1210
1211 l_int32
pixSetWpl(PIX * pix,l_int32 wpl)1212 pixSetWpl(PIX *pix,
1213 l_int32 wpl)
1214 {
1215 PROCNAME("pixSetWpl");
1216
1217 if (!pix)
1218 return ERROR_INT("pix not defined", procName, 1);
1219
1220 pix->wpl = wpl;
1221 return 0;
1222 }
1223
1224
1225 l_int32
pixGetRefcount(PIX * pix)1226 pixGetRefcount(PIX *pix)
1227 {
1228 PROCNAME("pixGetRefcount");
1229
1230 if (!pix)
1231 return ERROR_INT("pix not defined", procName, 0);
1232 return pix->refcount;
1233 }
1234
1235
1236 l_int32
pixChangeRefcount(PIX * pix,l_int32 delta)1237 pixChangeRefcount(PIX *pix,
1238 l_int32 delta)
1239 {
1240 PROCNAME("pixChangeRefcount");
1241
1242 if (!pix)
1243 return ERROR_INT("pix not defined", procName, 1);
1244
1245 pix->refcount += delta;
1246 return 0;
1247 }
1248
1249
1250 l_int32
pixGetXRes(PIX * pix)1251 pixGetXRes(PIX *pix)
1252 {
1253 PROCNAME("pixGetXRes");
1254
1255 if (!pix)
1256 return ERROR_INT("pix not defined", procName, 0);
1257 return pix->xres;
1258 }
1259
1260
1261 l_int32
pixSetXRes(PIX * pix,l_int32 res)1262 pixSetXRes(PIX *pix,
1263 l_int32 res)
1264 {
1265 PROCNAME("pixSetXRes");
1266
1267 if (!pix)
1268 return ERROR_INT("pix not defined", procName, 1);
1269
1270 pix->xres = res;
1271 return 0;
1272 }
1273
1274
1275 l_int32
pixGetYRes(PIX * pix)1276 pixGetYRes(PIX *pix)
1277 {
1278 PROCNAME("pixGetYRes");
1279
1280 if (!pix)
1281 return ERROR_INT("pix not defined", procName, 0);
1282 return pix->yres;
1283 }
1284
1285
1286 l_int32
pixSetYRes(PIX * pix,l_int32 res)1287 pixSetYRes(PIX *pix,
1288 l_int32 res)
1289 {
1290 PROCNAME("pixSetYRes");
1291
1292 if (!pix)
1293 return ERROR_INT("pix not defined", procName, 1);
1294
1295 pix->yres = res;
1296 return 0;
1297 }
1298
1299
1300 /*!
1301 * \brief pixGetResolution()
1302 *
1303 * \param[in] pix
1304 * \param[out] pxres, pyres [optional] each can be null
1305 * \return 0 if OK, 1 on error
1306 */
1307 l_int32
pixGetResolution(PIX * pix,l_int32 * pxres,l_int32 * pyres)1308 pixGetResolution(PIX *pix,
1309 l_int32 *pxres,
1310 l_int32 *pyres)
1311 {
1312 PROCNAME("pixGetResolution");
1313
1314 if (pxres) *pxres = 0;
1315 if (pyres) *pyres = 0;
1316 if (!pxres && !pyres)
1317 return ERROR_INT("no output requested", procName, 1);
1318 if (!pix)
1319 return ERROR_INT("pix not defined", procName, 1);
1320 if (pxres) *pxres = pix->xres;
1321 if (pyres) *pyres = pix->yres;
1322 return 0;
1323 }
1324
1325
1326 /*!
1327 * \brief pixSetResolution()
1328 *
1329 * \param[in] pix
1330 * \param[in] xres, yres use 0 to skip the setting for either of these
1331 * \return 0 if OK, 1 on error
1332 */
1333 l_int32
pixSetResolution(PIX * pix,l_int32 xres,l_int32 yres)1334 pixSetResolution(PIX *pix,
1335 l_int32 xres,
1336 l_int32 yres)
1337 {
1338 PROCNAME("pixSetResolution");
1339
1340 if (!pix)
1341 return ERROR_INT("pix not defined", procName, 1);
1342 if (xres > 0) pix->xres = xres;
1343 if (yres > 0) pix->yres = yres;
1344 return 0;
1345 }
1346
1347
1348 l_int32
pixCopyResolution(PIX * pixd,PIX * pixs)1349 pixCopyResolution(PIX *pixd,
1350 PIX *pixs)
1351 {
1352 PROCNAME("pixCopyResolution");
1353
1354 if (!pixs)
1355 return ERROR_INT("pixs not defined", procName, 1);
1356 if (!pixd)
1357 return ERROR_INT("pixd not defined", procName, 1);
1358 if (pixs == pixd)
1359 return 0; /* no-op */
1360
1361 pixSetXRes(pixd, pixGetXRes(pixs));
1362 pixSetYRes(pixd, pixGetYRes(pixs));
1363 return 0;
1364 }
1365
1366
1367 l_int32
pixScaleResolution(PIX * pix,l_float32 xscale,l_float32 yscale)1368 pixScaleResolution(PIX *pix,
1369 l_float32 xscale,
1370 l_float32 yscale)
1371 {
1372 PROCNAME("pixScaleResolution");
1373
1374 if (!pix)
1375 return ERROR_INT("pix not defined", procName, 1);
1376
1377 if (pix->xres != 0 && pix->yres != 0) {
1378 pix->xres = (l_uint32)(xscale * (l_float32)(pix->xres) + 0.5);
1379 pix->yres = (l_uint32)(yscale * (l_float32)(pix->yres) + 0.5);
1380 }
1381 return 0;
1382 }
1383
1384
1385 l_int32
pixGetInputFormat(PIX * pix)1386 pixGetInputFormat(PIX *pix)
1387 {
1388 PROCNAME("pixGetInputFormat");
1389
1390 if (!pix)
1391 return ERROR_INT("pix not defined", procName, 0);
1392 return pix->informat;
1393 }
1394
1395
1396 l_int32
pixSetInputFormat(PIX * pix,l_int32 informat)1397 pixSetInputFormat(PIX *pix,
1398 l_int32 informat)
1399 {
1400 PROCNAME("pixSetInputFormat");
1401
1402 if (!pix)
1403 return ERROR_INT("pix not defined", procName, 1);
1404 pix->informat = informat;
1405 return 0;
1406 }
1407
1408
1409 l_int32
pixCopyInputFormat(PIX * pixd,PIX * pixs)1410 pixCopyInputFormat(PIX *pixd,
1411 PIX *pixs)
1412 {
1413 PROCNAME("pixCopyInputFormat");
1414
1415 if (!pixs)
1416 return ERROR_INT("pixs not defined", procName, 1);
1417 if (!pixd)
1418 return ERROR_INT("pixd not defined", procName, 1);
1419 if (pixs == pixd)
1420 return 0; /* no-op */
1421
1422 pixSetInputFormat(pixd, pixGetInputFormat(pixs));
1423 return 0;
1424 }
1425
1426
1427 l_int32
pixSetSpecial(PIX * pix,l_int32 special)1428 pixSetSpecial(PIX *pix,
1429 l_int32 special)
1430 {
1431 PROCNAME("pixSetSpecial");
1432
1433 if (!pix)
1434 return ERROR_INT("pix not defined", procName, 1);
1435 pix->special = special;
1436 return 0;
1437 }
1438
1439
1440 /*!
1441 * \brief pixGetText()
1442 *
1443 * \param[in] pix
1444 * \return ptr to existing text string
1445 *
1446 * <pre>
1447 * Notes:
1448 * (1) The text string belongs to the pix. The caller must
1449 * NOT free it!
1450 * </pre>
1451 */
1452 char *
pixGetText(PIX * pix)1453 pixGetText(PIX *pix)
1454 {
1455 PROCNAME("pixGetText");
1456
1457 if (!pix)
1458 return (char *)ERROR_PTR("pix not defined", procName, NULL);
1459 return pix->text;
1460 }
1461
1462
1463 /*!
1464 * \brief pixSetText()
1465 *
1466 * \param[in] pix
1467 * \param[in] textstring can be null
1468 * \return 0 if OK, 1 on error
1469 *
1470 * <pre>
1471 * Notes:
1472 * (1) This removes any existing textstring and puts a copy of
1473 * the input textstring there.
1474 * </pre>
1475 */
1476 l_int32
pixSetText(PIX * pix,const char * textstring)1477 pixSetText(PIX *pix,
1478 const char *textstring)
1479 {
1480 PROCNAME("pixSetText");
1481
1482 if (!pix)
1483 return ERROR_INT("pix not defined", procName, 1);
1484
1485 stringReplace(&pix->text, textstring);
1486 return 0;
1487 }
1488
1489
1490 /*!
1491 * \brief pixAddText()
1492 *
1493 * \param[in] pix
1494 * \param[in] textstring
1495 * \return 0 if OK, 1 on error
1496 *
1497 * <pre>
1498 * Notes:
1499 * (1) This adds the new textstring to any existing text.
1500 * (2) Either or both the existing text and the new text
1501 * string can be null.
1502 * </pre>
1503 */
1504 l_int32
pixAddText(PIX * pix,const char * textstring)1505 pixAddText(PIX *pix,
1506 const char *textstring)
1507 {
1508 char *newstring;
1509
1510 PROCNAME("pixAddText");
1511
1512 if (!pix)
1513 return ERROR_INT("pix not defined", procName, 1);
1514
1515 newstring = stringJoin(pixGetText(pix), textstring);
1516 stringReplace(&pix->text, newstring);
1517 LEPT_FREE(newstring);
1518 return 0;
1519 }
1520
1521
1522 l_int32
pixCopyText(PIX * pixd,PIX * pixs)1523 pixCopyText(PIX *pixd,
1524 PIX *pixs)
1525 {
1526 PROCNAME("pixCopyText");
1527
1528 if (!pixs)
1529 return ERROR_INT("pixs not defined", procName, 1);
1530 if (!pixd)
1531 return ERROR_INT("pixd not defined", procName, 1);
1532 if (pixs == pixd)
1533 return 0; /* no-op */
1534
1535 pixSetText(pixd, pixGetText(pixs));
1536 return 0;
1537 }
1538
1539
1540 PIXCMAP *
pixGetColormap(PIX * pix)1541 pixGetColormap(PIX *pix)
1542 {
1543 PROCNAME("pixGetColormap");
1544
1545 if (!pix)
1546 return (PIXCMAP *)ERROR_PTR("pix not defined", procName, NULL);
1547 return pix->colormap;
1548 }
1549
1550
1551 /*!
1552 * \brief pixSetColormap()
1553 *
1554 * \param[in] pix
1555 * \param[in] colormap to be assigned
1556 * \return 0 if OK, 1 on error.
1557 *
1558 * <pre>
1559 * Notes:
1560 * (1) Unlike with the pix data field, pixSetColormap() destroys
1561 * any existing colormap before assigning the new one.
1562 * Because colormaps are not ref counted, it is important that
1563 * the new colormap does not belong to any other pix.
1564 * </pre>
1565 */
1566 l_int32
pixSetColormap(PIX * pix,PIXCMAP * colormap)1567 pixSetColormap(PIX *pix,
1568 PIXCMAP *colormap)
1569 {
1570 PROCNAME("pixSetColormap");
1571
1572 if (!pix)
1573 return ERROR_INT("pix not defined", procName, 1);
1574
1575 pixDestroyColormap(pix);
1576 pix->colormap = colormap;
1577 return 0;
1578 }
1579
1580
1581 /*!
1582 * \brief pixDestroyColormap()
1583 *
1584 * \param[in] pix
1585 * \return 0 if OK, 1 on error
1586 */
1587 l_int32
pixDestroyColormap(PIX * pix)1588 pixDestroyColormap(PIX *pix)
1589 {
1590 PIXCMAP *cmap;
1591
1592 PROCNAME("pixDestroyColormap");
1593
1594 if (!pix)
1595 return ERROR_INT("pix not defined", procName, 1);
1596
1597 if ((cmap = pix->colormap) != NULL) {
1598 pixcmapDestroy(&cmap);
1599 pix->colormap = NULL;
1600 }
1601 return 0;
1602 }
1603
1604
1605 /*!
1606 * \brief pixGetData()
1607 *
1608 * Notes:
1609 * (1) This gives a new handle for the data. The data is still
1610 * owned by the pix, so do not call LEPT_FREE() on it.
1611 */
1612 l_uint32 *
pixGetData(PIX * pix)1613 pixGetData(PIX *pix)
1614 {
1615 PROCNAME("pixGetData");
1616
1617 if (!pix)
1618 return (l_uint32 *)ERROR_PTR("pix not defined", procName, NULL);
1619 return pix->data;
1620 }
1621
1622
1623 /*!
1624 * \brief pixSetData()
1625 *
1626 * Notes:
1627 * (1) This does not free any existing data. To free existing
1628 * data, use pixFreeData() before pixSetData().
1629 */
1630 l_int32
pixSetData(PIX * pix,l_uint32 * data)1631 pixSetData(PIX *pix,
1632 l_uint32 *data)
1633 {
1634 PROCNAME("pixSetData");
1635
1636 if (!pix)
1637 return ERROR_INT("pix not defined", procName, 1);
1638
1639 pix->data = data;
1640 return 0;
1641 }
1642
1643
1644 /*!
1645 * \brief pixExtractData()
1646 *
1647 * Notes:
1648 * (1) This extracts the pix image data for use in another context.
1649 * The caller still needs to use pixDestroy() on the input pix.
1650 * (2) If refcount == 1, the data is extracted and the
1651 * pix->data ptr is set to NULL.
1652 * (3) If refcount > 1, this simply returns a copy of the data,
1653 * using the pix allocator, and leaving the input pix unchanged.
1654 */
1655 l_uint32 *
pixExtractData(PIX * pixs)1656 pixExtractData(PIX *pixs)
1657 {
1658 l_int32 count, bytes;
1659 l_uint32 *data, *datas;
1660
1661 PROCNAME("pixExtractData");
1662
1663 if (!pixs)
1664 return (l_uint32 *)ERROR_PTR("pixs not defined", procName, NULL);
1665
1666 count = pixGetRefcount(pixs);
1667 if (count == 1) { /* extract */
1668 data = pixGetData(pixs);
1669 pixSetData(pixs, NULL);
1670 } else { /* refcount > 1; copy */
1671 bytes = 4 * pixGetWpl(pixs) * pixGetHeight(pixs);
1672 datas = pixGetData(pixs);
1673 if ((data = (l_uint32 *)pix_malloc(bytes)) == NULL)
1674 return (l_uint32 *)ERROR_PTR("data not made", procName, NULL);
1675 memcpy((char *)data, (char *)datas, bytes);
1676 }
1677
1678 return data;
1679 }
1680
1681
1682 /*!
1683 * \brief pixFreeData()
1684 *
1685 * Notes:
1686 * (1) This frees the data and sets the pix data ptr to null.
1687 * It should be used before pixSetData() in the situation where
1688 * you want to free any existing data before doing
1689 * a subsequent assignment with pixSetData().
1690 */
1691 l_int32
pixFreeData(PIX * pix)1692 pixFreeData(PIX *pix)
1693 {
1694 l_uint32 *data;
1695
1696 PROCNAME("pixFreeData");
1697
1698 if (!pix)
1699 return ERROR_INT("pix not defined", procName, 1);
1700
1701 if ((data = pixGetData(pix)) != NULL) {
1702 pix_free(data);
1703 pix->data = NULL;
1704 }
1705 return 0;
1706 }
1707
1708
1709 /*--------------------------------------------------------------------*
1710 * Pix line ptrs *
1711 *--------------------------------------------------------------------*/
1712 /*!
1713 * \brief pixGetLinePtrs()
1714 *
1715 * \param[in] pix
1716 * \param[out] psize [optional] array size, which is the pix height
1717 * \return array of line ptrs, or NULL on error
1718 *
1719 * <pre>
1720 * Notes:
1721 * (1) This is intended to be used for fast random pixel access.
1722 * For example, for an 8 bpp image,
1723 * val = GET_DATA_BYTE(lines8[i], j);
1724 * is equivalent to, but much faster than,
1725 * pixGetPixel(pix, j, i, &val);
1726 * (2) How much faster? For 1 bpp, it's from 6 to 10x faster.
1727 * For 8 bpp, it's an amazing 30x faster. So if you are
1728 * doing random access over a substantial part of the image,
1729 * use this line ptr array.
1730 * (3) When random access is used in conjunction with a stack,
1731 * queue or heap, the overall computation time depends on
1732 * the operations performed on each struct that is popped
1733 * or pushed, and whether we are using a priority queue (O(logn))
1734 * or a queue or stack (O(1)). For example, for maze search,
1735 * the overall ratio of time for line ptrs vs. pixGet/Set* is
1736 * Maze type Type Time ratio
1737 * binary queue 0.4
1738 * gray heap (priority queue) 0.6
1739 * (4) Because this returns a void** and the accessors take void*,
1740 * the compiler cannot check the pointer types. It is
1741 * strongly recommended that you adopt a naming scheme for
1742 * the returned ptr arrays that indicates the pixel depth.
1743 * (This follows the original intent of Simonyi's "Hungarian"
1744 * application notation, where naming is used proactively
1745 * to make errors visibly obvious.) By doing this, you can
1746 * tell by inspection if the correct accessor is used.
1747 * For example, for an 8 bpp pixg:
1748 * void **lineg8 = pixGetLinePtrs(pixg, NULL);
1749 * val = GET_DATA_BYTE(lineg8[i], j); // fast access; BYTE, 8
1750 * ...
1751 * LEPT_FREE(lineg8); // don't forget this
1752 * (5) These are convenient for accessing bytes sequentially in an
1753 * 8 bpp grayscale image. People who write image processing code
1754 * on 8 bpp images are accustomed to grabbing pixels directly out
1755 * of the raster array. Note that for little endians, you first
1756 * need to reverse the byte order in each 32-bit word.
1757 * Here's a typical usage pattern:
1758 * pixEndianByteSwap(pix); // always safe; no-op on big-endians
1759 * l_uint8 **lineptrs = (l_uint8 **)pixGetLinePtrs(pix, NULL);
1760 * pixGetDimensions(pix, &w, &h, NULL);
1761 * for (i = 0; i < h; i++) {
1762 * l_uint8 *line = lineptrs[i];
1763 * for (j = 0; j < w; j++) {
1764 * val = line[j];
1765 * ...
1766 * }
1767 * }
1768 * pixEndianByteSwap(pix); // restore big-endian order
1769 * LEPT_FREE(lineptrs);
1770 * This can be done even more simply as follows:
1771 * l_uint8 **lineptrs = pixSetupByteProcessing(pix, &w, &h);
1772 * for (i = 0; i < h; i++) {
1773 * l_uint8 *line = lineptrs[i];
1774 * for (j = 0; j < w; j++) {
1775 * val = line[j];
1776 * ...
1777 * }
1778 * }
1779 * pixCleanupByteProcessing(pix, lineptrs);
1780 * </pre>
1781 */
1782 void **
pixGetLinePtrs(PIX * pix,l_int32 * psize)1783 pixGetLinePtrs(PIX *pix,
1784 l_int32 *psize)
1785 {
1786 l_int32 i, h, wpl;
1787 l_uint32 *data;
1788 void **lines;
1789
1790 PROCNAME("pixGetLinePtrs");
1791
1792 if (psize) *psize = 0;
1793 if (!pix)
1794 return (void **)ERROR_PTR("pix not defined", procName, NULL);
1795
1796 h = pixGetHeight(pix);
1797 if (psize) *psize = h;
1798 if ((lines = (void **)LEPT_CALLOC(h, sizeof(void *))) == NULL)
1799 return (void **)ERROR_PTR("lines not made", procName, NULL);
1800 wpl = pixGetWpl(pix);
1801 data = pixGetData(pix);
1802 for (i = 0; i < h; i++)
1803 lines[i] = (void *)(data + i * wpl);
1804
1805 return lines;
1806 }
1807
1808
1809 /*--------------------------------------------------------------------*
1810 * Print output for debugging *
1811 *--------------------------------------------------------------------*/
1812 extern const char *ImageFileFormatExtensions[];
1813
1814 /*!
1815 * \brief pixPrintStreamInfo()
1816 *
1817 * \param[in] fp file stream
1818 * \param[in] pix
1819 * \param[in] text [optional] identifying string; can be null
1820 * \return 0 if OK, 1 on error
1821 */
1822 l_int32
pixPrintStreamInfo(FILE * fp,PIX * pix,const char * text)1823 pixPrintStreamInfo(FILE *fp,
1824 PIX *pix,
1825 const char *text)
1826 {
1827 char *textdata;
1828 l_int32 informat;
1829 PIXCMAP *cmap;
1830
1831 PROCNAME("pixPrintStreamInfo");
1832
1833 if (!fp)
1834 return ERROR_INT("fp not defined", procName, 1);
1835 if (!pix)
1836 return ERROR_INT("pix not defined", procName, 1);
1837
1838 if (text)
1839 fprintf(fp, " Pix Info for %s:\n", text);
1840 fprintf(fp, " width = %d, height = %d, depth = %d, spp = %d\n",
1841 pixGetWidth(pix), pixGetHeight(pix), pixGetDepth(pix),
1842 pixGetSpp(pix));
1843 fprintf(fp, " wpl = %d, data = %p, refcount = %d\n",
1844 pixGetWpl(pix), pixGetData(pix), pixGetRefcount(pix));
1845 fprintf(fp, " xres = %d, yres = %d\n", pixGetXRes(pix), pixGetYRes(pix));
1846 if ((cmap = pixGetColormap(pix)) != NULL)
1847 pixcmapWriteStream(fp, cmap);
1848 else
1849 fprintf(fp, " no colormap\n");
1850 informat = pixGetInputFormat(pix);
1851 fprintf(fp, " input format: %d (%s)\n", informat,
1852 ImageFileFormatExtensions[informat]);
1853 if ((textdata = pixGetText(pix)) != NULL)
1854 fprintf(fp, " text: %s\n", textdata);
1855
1856 return 0;
1857 }
1858