Coverage Report

Created: 2024-06-18 06:05

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