Coverage Report

Created: 2024-06-18 06:05

/src/leptonica/src/rop.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 rop.c
29
 * <pre>
30
 *      General rasterop
31
 *           l_int32    pixRasterop()
32
 *
33
 *      In-place full band translation
34
 *           l_int32    pixRasteropVip()
35
 *           l_int32    pixRasteropHip()
36
 *
37
 *      Full image translation (general and in-place)
38
 *           l_int32    pixTranslate()
39
 *           l_int32    pixRasteropIP()
40
 *
41
 *      Full image rasterop with no translation
42
 *           l_int32    pixRasteropFullImage()
43
 *
44
 *      Checking for invalid crop box
45
 *           static l_int32   checkRasteropCrop()
46
 * </pre>
47
 */
48
49
#ifdef HAVE_CONFIG_H
50
#include <config_auto.h>
51
#endif  /* HAVE_CONFIG_H */
52
53
#include <string.h>
54
#include "allheaders.h"
55
56
static l_int32 checkRasteropCrop(l_int32 pixw, l_int32 pixh, l_int32 dx,
57
                                 l_int32 dy, l_int32 dw, l_int32 dh);
58
59
60
/*--------------------------------------------------------------------*
61
 *                General rasterop (basic pix interface)              *
62
 *--------------------------------------------------------------------*/
63
/*!
64
 * \brief   pixRasterop()
65
 *
66
 * \param[in]    pixd   dest pix
67
 * \param[in]    dx     x val of UL corner of dest rectangle
68
 * \param[in]    dy     y val of UL corner of dest rectangle
69
 * \param[in]    dw     width of dest rectangle
70
 * \param[in]    dh     height of dest rectangle
71
 * \param[in]    op     op code
72
 * \param[in]    pixs   src pix
73
 * \param[in]    sx     x val of UL corner of src rectangle
74
 * \param[in]    sy     y val of UL corner of src rectangle
75
 * \return  0 if OK; 1 on error.
76
 *
77
 * <pre>
78
 * Notes:
79
 *      (1) This has the standard set of 9 args for rasterop.
80
 *          This function is your friend; it is worth memorizing!
81
 *      (2) If the operation involves only dest, this calls
82
 *          rasteropUniLow().  Otherwise, checks depth of the
83
 *          src and dest, and if they match, calls rasteropLow().
84
 *      (3) For the two-image operation, where both pixs and pixd
85
 *          are defined, they are typically different images.  However
86
 *          there are cases, such as pixSetMirroredBorder(), where
87
 *          in-place operations can be done, blitting pixels from
88
 *          one part of pixd to another.  Consequently, we permit
89
 *          such operations.  If you use them, be sure that there
90
 *          is no overlap between the source and destination rectangles
91
 *          in pixd (!)
92
 *
93
 *  Background:
94
 *  -----------
95
 *
96
 *  There are 18 operations, described by the op codes in pix.h.
97
 *
98
 *  One, PIX_DST, is a no-op.
99
 *
100
 *  Three, PIX_CLR, PIX_SET, and PIX_NOT(PIX_DST) operate only on the dest.
101
 *  These are handled by the low-level rasteropUniLow().
102
 *
103
 *  The other 14 involve both the src and the dest, and depend on
104
 *  the bit values of either just the src or the bit values of both
105
 *  src and dest.  They are handled by rasteropLow():
106
 *
107
 *          PIX_SRC                             s
108
 *          PIX_NOT(PIX_SRC)                   ~s
109
 *          PIX_SRC | PIX_DST                   s | d
110
 *          PIX_SRC & PIX_DST                   s & d
111
 *          PIX_SRC ^ PIX_DST                   s ^ d
112
 *          PIX_NOT(PIX_SRC) | PIX_DST         ~s | d
113
 *          PIX_NOT(PIX_SRC) & PIX_DST         ~s & d
114
 *          PIX_NOT(PIX_SRC) ^ PIX_DST         ~s ^ d
115
 *          PIX_SRC | PIX_NOT(PIX_DST)          s | ~d
116
 *          PIX_SRC & PIX_NOT(PIX_DST)          s & ~d
117
 *          PIX_SRC ^ PIX_NOT(PIX_DST)          s ^ ~d
118
 *          PIX_NOT(PIX_SRC | PIX_DST)         ~(s | d)
119
 *          PIX_NOT(PIX_SRC & PIX_DST)         ~(s & d)
120
 *          PIX_NOT(PIX_SRC ^ PIX_DST)         ~(s ^ d)
121
 *
122
 *  Each of these is implemented with one of three low-level
123
 *  functions, depending on the alignment of the left edge
124
 *  of the src and dest rectangles:
125
 *      * a fastest implementation if both left edges are
126
 *        (32-bit) word aligned
127
 *      * a very slightly slower implementation if both left
128
 *        edges have the same relative (32-bit) word alignment
129
 *      * the general routine that is invoked when
130
 *        both left edges have different word alignment
131
 *
132
 *  Of the 14 binary rasterops above, only 12 are unique
133
 *  logical combinations (out of a possible 16) of src
134
 *  and dst bits:
135
 *
136
 *        (sd)         (11)   (10)   (01)   (00)
137
 *   -----------------------------------------------
138
 *         s            1      1      0      0
139
 *        ~s            0      1      0      1
140
 *       s | d          1      1      1      0
141
 *       s & d          1      0      0      0
142
 *       s ^ d          0      1      1      0
143
 *      ~s | d          1      0      1      1
144
 *      ~s & d          0      0      1      0
145
 *      ~s ^ d          1      0      0      1
146
 *       s | ~d         1      1      0      1
147
 *       s & ~d         0      1      0      0
148
 *       s ^ ~d         1      0      0      1
149
 *      ~(s | d)        0      0      0      1
150
 *      ~(s & d)        0      1      1      1
151
 *      ~(s ^ d)        1      0      0      1
152
 *
153
 *  Note that the following three operations are equivalent:
154
 *      ~(s ^ d)
155
 *      ~s ^ d
156
 *      s ^ ~d
157
 *  and in the implementation, we call them out with the first form;
158
 *  namely, ~(s ^ d).
159
 *
160
 *  Of the 16 possible binary combinations of src and dest bits,
161
 *  the remaining 4 unique ones are independent of the src bit.
162
 *  They depend on either just the dest bit or on neither
163
 *  the src nor dest bits:
164
 *
165
 *         d            1      0      1      0    (indep. of s)
166
 *        ~d            0      1      0      1    (indep. of s)
167
 *        CLR           0      0      0      0    (indep. of both s & d)
168
 *        SET           1      1      1      1    (indep. of both s & d)
169
 *
170
 *  As mentioned above, three of these are implemented by
171
 *  rasteropUniLow(), and one is a no-op.
172
 *
173
 *  How can these operation codes be represented by bits
174
 *  in such a way that when the basic operations are performed
175
 *  on the bits the results are unique for unique
176
 *  operations, and mimic the logic table given above?
177
 *
178
 *  The answer is to choose a particular order of the pairings:
179
 *         (sd)         (11)   (10)   (01)   (00)
180
 *  (which happens to be the same as in the above table)
181
 *  and to translate the result into 4-bit representations
182
 *  of s and d.  For example, the Sun rasterop choice
183
 *  (omitting the extra bit for clipping) is
184
 *
185
 *      PIX_SRC      0xc
186
 *      PIX_DST      0xa
187
 *
188
 *  This corresponds to our pairing order given above:
189
 *         (sd)         (11)   (10)   (01)   (00)
190
 *  where for s = 1 we get the bit pattern
191
 *       PIX_SRC:        1      1      0      0     (0xc)
192
 *  and for d = 1 we get the pattern
193
 *       PIX_DST:         1      0      1      0    (0xa)
194
 *
195
 *  OK, that's the pairing order that Sun chose.  How many different
196
 *  ways can we assign bit patterns to PIX_SRC and PIX_DST to get
197
 *  the boolean ops to work out?  Any of the 4 pairs can be put
198
 *  in the first position, any of the remaining 3 pairs can go
199
 *  in the second; and one of the remaining 2 pairs can go the the third.
200
 *  There is a total of 4*3*2 = 24 ways these pairs can be permuted.
201
 * </pre>
202
 */
203
l_ok
204
pixRasterop(PIX     *pixd,
205
            l_int32  dx,
206
            l_int32  dy,
207
            l_int32  dw,
208
            l_int32  dh,
209
            l_int32  op,
210
            PIX     *pixs,
211
            l_int32  sx,
212
            l_int32  sy)
213
2.72k
{
214
2.72k
l_int32  dpw, dph, dpd, spw, sph, spd;
215
216
2.72k
    if (!pixd)
217
0
        return ERROR_INT("pixd not defined", __func__, 1);
218
219
2.72k
    if (op == PIX_DST)   /* no-op */
220
0
        return 0;
221
222
2.72k
    pixGetDimensions(pixd, &dpw, &dph, &dpd);
223
#if 0
224
    if (checkRasteropCrop(dpw, dph, dx, dy, dw, dh)) {
225
        L_WARNING("dest crop box out of bounds\n", __func__);
226
        return 1;
227
    }
228
#endif
229
230
        /* Check if operation is only on dest */
231
2.72k
    if (op == PIX_CLR || op == PIX_SET || op == PIX_NOT(PIX_DST)) {
232
2.17k
        rasteropUniLow(pixGetData(pixd), dpw, dph, dpd, pixGetWpl(pixd),
233
2.17k
                       dx, dy, dw, dh, op);
234
2.17k
        return 0;
235
2.17k
    }
236
237
        /* Two-image rasterop; the depths must match */
238
544
    if (!pixs)
239
0
        return ERROR_INT("pixs not defined", __func__, 1);
240
544
    pixGetDimensions(pixs, &spw, &sph, &spd);
241
544
    if (dpd != spd)
242
0
        return ERROR_INT("depths of pixs and pixd differ", __func__, 1);
243
#if 0
244
    if (checkRasteropCrop(spw, sph, sx, sy, dw, dh)) {
245
        L_WARNING("source crop box out of bounds\n", __func__);
246
        return 1;
247
    }
248
#endif
249
250
544
    rasteropLow(pixGetData(pixd), dpw, dph, dpd, pixGetWpl(pixd),
251
544
                dx, dy, dw, dh, op,
252
544
                pixGetData(pixs), spw, sph, pixGetWpl(pixs), sx, sy);
253
544
    return 0;
254
544
}
255
256
257
/*--------------------------------------------------------------------*
258
 *                    In-place full band translation                  *
259
 *--------------------------------------------------------------------*/
260
/*!
261
 * \brief   pixRasteropVip()
262
 *
263
 * \param[in]    pixd     in-place
264
 * \param[in]    bx       left edge of vertical band
265
 * \param[in]    bw       width of vertical band
266
 * \param[in]    vshift   vertical shift of band; vshift > 0 is down
267
 * \param[in]    incolor  L_BRING_IN_WHITE, L_BRING_IN_BLACK
268
 * \return  0 if OK; 1 on error
269
 *
270
 * <pre>
271
 * Notes:
272
 *      (1) This rasterop translates a vertical band of the
273
 *          image either up or down, bringing in either white
274
 *          or black pixels from outside the image.
275
 *      (2) The vertical band extends the full height of pixd.
276
 *      (3) If a colormap exists, the nearest color to white or black
277
 *          is brought in.
278
 * </pre>
279
 */
280
l_ok
281
pixRasteropVip(PIX     *pixd,
282
               l_int32  bx,
283
               l_int32  bw,
284
               l_int32  vshift,
285
               l_int32  incolor)
286
0
{
287
0
l_int32   w, h, d, index, op;
288
0
PIX      *pixt;
289
0
PIXCMAP  *cmap;
290
291
0
    if (!pixd)
292
0
        return ERROR_INT("pixd not defined", __func__, 1);
293
0
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
294
0
        return ERROR_INT("invalid value for incolor", __func__, 1);
295
0
    if (bw <= 0)
296
0
        return ERROR_INT("bw must be > 0", __func__, 1);
297
298
0
    if (vshift == 0)
299
0
        return 0;
300
301
0
    pixGetDimensions(pixd, &w, &h, &d);
302
0
    rasteropVipLow(pixGetData(pixd), w, h, d, pixGetWpl(pixd), bx, bw, vshift);
303
304
0
    cmap = pixGetColormap(pixd);
305
0
    if (!cmap) {
306
0
        if ((d == 1 && incolor == L_BRING_IN_BLACK) ||
307
0
            (d > 1 && incolor == L_BRING_IN_WHITE))
308
0
            op = PIX_SET;
309
0
        else
310
0
            op = PIX_CLR;
311
312
            /* Set the pixels brought in at top or bottom */
313
0
        if (vshift > 0)
314
0
            pixRasterop(pixd, bx, 0, bw, vshift, op, NULL, 0, 0);
315
0
        else  /* vshift < 0 */
316
0
            pixRasterop(pixd, bx, h + vshift, bw, -vshift, op, NULL, 0, 0);
317
0
        return 0;
318
0
    }
319
320
        /* Get the nearest index and fill with that */
321
0
    if (incolor == L_BRING_IN_BLACK)
322
0
        pixcmapGetRankIntensity(cmap, 0.0, &index);
323
0
    else  /* white */
324
0
        pixcmapGetRankIntensity(cmap, 1.0, &index);
325
0
    pixt = pixCreate(bw, L_ABS(vshift), d);
326
0
    pixSetAllArbitrary(pixt, index);
327
0
    if (vshift > 0)
328
0
        pixRasterop(pixd, bx, 0, bw, vshift, PIX_SRC, pixt, 0, 0);
329
0
    else  /* vshift < 0 */
330
0
        pixRasterop(pixd, bx, h + vshift, bw, -vshift, PIX_SRC, pixt, 0, 0);
331
0
    pixDestroy(&pixt);
332
0
    return 0;
333
0
}
334
335
336
/*!
337
 * \brief   pixRasteropHip()
338
 *
339
 * \param[in]    pixd     in-place operation
340
 * \param[in]    by       top of horizontal band
341
 * \param[in]    bh       height of horizontal band
342
 * \param[in]    hshift   horizontal shift of band; hshift > 0 is to right
343
 * \param[in]    incolor  L_BRING_IN_WHITE, L_BRING_IN_BLACK
344
 * \return  0 if OK; 1 on error
345
 *
346
 * <pre>
347
 * Notes:
348
 *      (1) This rasterop translates a horizontal band of the
349
 *          image either left or right, bringing in either white
350
 *          or black pixels from outside the image.
351
 *      (2) The horizontal band extends the full width of pixd.
352
 *      (3) If a colormap exists, the nearest color to white or black
353
 *          is brought in.
354
 * </pre>
355
 */
356
l_ok
357
pixRasteropHip(PIX     *pixd,
358
               l_int32  by,
359
               l_int32  bh,
360
               l_int32  hshift,
361
               l_int32  incolor)
362
0
{
363
0
l_int32   w, h, d, index, op;
364
0
PIX      *pixt;
365
0
PIXCMAP  *cmap;
366
367
0
    if (!pixd)
368
0
        return ERROR_INT("pixd not defined", __func__, 1);
369
0
    if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK)
370
0
        return ERROR_INT("invalid value for incolor", __func__, 1);
371
0
    if (bh <= 0)
372
0
        return ERROR_INT("bh must be > 0", __func__, 1);
373
374
0
    if (hshift == 0)
375
0
        return 0;
376
377
0
    pixGetDimensions(pixd, &w, &h, &d);
378
0
    rasteropHipLow(pixGetData(pixd), h, d, pixGetWpl(pixd), by, bh, hshift);
379
380
0
    cmap = pixGetColormap(pixd);
381
0
    if (!cmap) {
382
0
        if ((d == 1 && incolor == L_BRING_IN_BLACK) ||
383
0
            (d > 1 && incolor == L_BRING_IN_WHITE))
384
0
            op = PIX_SET;
385
0
        else
386
0
            op = PIX_CLR;
387
388
            /* Set the pixels brought in at left or right */
389
0
        if (hshift > 0)
390
0
            pixRasterop(pixd, 0, by, hshift, bh, op, NULL, 0, 0);
391
0
        else  /* hshift < 0 */
392
0
            pixRasterop(pixd, w + hshift, by, -hshift, bh, op, NULL, 0, 0);
393
0
        return 0;
394
0
    }
395
396
        /* Get the nearest index and fill with that */
397
0
    if (incolor == L_BRING_IN_BLACK)
398
0
        pixcmapGetRankIntensity(cmap, 0.0, &index);
399
0
    else  /* white */
400
0
        pixcmapGetRankIntensity(cmap, 1.0, &index);
401
0
    pixt = pixCreate(L_ABS(hshift), bh, d);
402
0
    pixSetAllArbitrary(pixt, index);
403
0
    if (hshift > 0)
404
0
        pixRasterop(pixd, 0, by, hshift, bh, PIX_SRC, pixt, 0, 0);
405
0
    else  /* hshift < 0 */
406
0
        pixRasterop(pixd, w + hshift, by, -hshift, bh, PIX_SRC, pixt, 0, 0);
407
0
    pixDestroy(&pixt);
408
0
    return 0;
409
0
}
410
411
412
/*--------------------------------------------------------------------*
413
 *             Full image translation (general and in-place)          *
414
 *--------------------------------------------------------------------*/
415
/*!
416
 * \brief   pixTranslate()
417
 *
418
 * \param[in]    pixd    [optional] destination: this can be null,
419
 *                        equal to pixs, or different from pixs
420
 * \param[in]    pixs
421
 * \param[in]    hshift   horizontal shift; hshift > 0 is to right
422
 * \param[in]    vshift   vertical shift; vshift > 0 is down
423
 * \param[in]    incolor  L_BRING_IN_WHITE, L_BRING_IN_BLACK
424
 * \return  pixd, or NULL on error.
425
 *
426
 * <pre>
427
 * Notes:
428
 *      (1) The general pattern is:
429
 *            pixd = pixTranslate(pixd, pixs, ...);
430
 *          For clarity, when you know the case, use one of these:
431
 *            pixd = pixTranslate(NULL, pixs, ...);  // new
432
 *            pixTranslate(pixs, pixs, ...);         // in-place
433
 *            pixTranslate(pixd, pixs, ...);         // to existing pixd
434
 *      (2) If an existing pixd is not the same size as pixs, the
435
 *          image data will be reallocated.
436
 * </pre>
437
 */
438
PIX *
439
pixTranslate(PIX     *pixd,
440
             PIX     *pixs,
441
             l_int32  hshift,
442
             l_int32  vshift,
443
             l_int32  incolor)
444
0
{
445
0
    if (!pixs)
446
0
        return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
447
448
        /* Prepare pixd for in-place operation */
449
0
    if ((pixd = pixCopy(pixd, pixs)) == NULL)
450
0
        return (PIX *)ERROR_PTR("pixd not made", __func__, NULL);
451
452
0
    pixRasteropIP(pixd, hshift, vshift, incolor);
453
0
    return pixd;
454
0
}
455
456
457
/*!
458
 * \brief   pixRasteropIP()
459
 *
460
 * \param[in]    pixd     in-place translation
461
 * \param[in]    hshift   horizontal shift; hshift > 0 is to right
462
 * \param[in]    vshift   vertical shift; vshift > 0 is down
463
 * \param[in]    incolor  L_BRING_IN_WHITE, L_BRING_IN_BLACK
464
 * \return  0 if OK; 1 on error
465
 */
466
l_ok
467
pixRasteropIP(PIX     *pixd,
468
              l_int32  hshift,
469
              l_int32  vshift,
470
              l_int32  incolor)
471
0
{
472
0
l_int32  w, h;
473
474
0
    if (!pixd)
475
0
        return ERROR_INT("pixd not defined", __func__, 1);
476
477
0
    pixGetDimensions(pixd, &w, &h, NULL);
478
0
    pixRasteropHip(pixd, 0, h, hshift, incolor);
479
0
    pixRasteropVip(pixd, 0, w, vshift, incolor);
480
481
0
    return 0;
482
0
}
483
484
485
/*--------------------------------------------------------------------*
486
 *                 Full image rasterop with no shifts                 *
487
 *--------------------------------------------------------------------*/
488
/*!
489
 * \brief   pixRasteropFullImage()
490
 *
491
 * \param[in]    pixd
492
 * \param[in]    pixs
493
 * \param[in]    op     any of the op-codes
494
 * \return  0 if OK; 1 on error
495
 *
496
 * <pre>
497
 * Notes:
498
 *      ~ this is a wrapper for a common 2-image raster operation
499
 *      ~ both pixs and pixd must be defined
500
 *      ~ the operation is performed with aligned UL corners of pixs and pixd
501
 *      ~ the operation clips to the smallest pix; if the width or height
502
 *        of pixd is larger than pixs, some pixels in pixd will be unchanged
503
 * </pre>
504
 */
505
l_ok
506
pixRasteropFullImage(PIX     *pixd,
507
                     PIX     *pixs,
508
                     l_int32  op)
509
0
{
510
0
    if (!pixd)
511
0
        return ERROR_INT("pixd not defined", __func__, 1);
512
0
    if (!pixs)
513
0
        return ERROR_INT("pixs not defined", __func__, 1);
514
515
0
    pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd), op,
516
0
                pixs, 0, 0);
517
0
    return 0;
518
0
}
519
520
521
/*--------------------------------------------------------------------*
522
 *                    Checking for invalid crop box                   *
523
 *--------------------------------------------------------------------*/
524
/*!
525
 * \brief   checkRasteropCrop()
526
 *
527
 * \param[in]    pixw, pixh   pix dimensions
528
 * \param[in]    x, y, w, h   crop box parameters
529
 * \return  0 if OK, 1 if the crop box does not intersect with the pix.
530
 *
531
 * <pre>
532
 * Notes:
533
 *      (1) The widths and heights must all be positive, but %x and %y
534
 *          can take on any value.
535
 *      (2) This works for checking both the source and dest regions.
536
 *      (3) This has been used to verify rasteropLow() cropping is correct.
537
 *          It is not needed for pre-filtering in pixRasterop().
538
 * </pre>
539
 */
540
static l_int32
541
checkRasteropCrop(l_int32 pixw,
542
                  l_int32 pixh,
543
                  l_int32 x,
544
                  l_int32 y,
545
                  l_int32 w,
546
                  l_int32 h)
547
0
{
548
0
    if (pixw < 1 || pixh < 1 || w < 1 || h < 1)
549
0
        return ERROR_INT("dimension is <= 0", __func__, 1);
550
0
551
0
    if (x + w <= 0 || y + h <= 0)
552
0
        return ERROR_INT("box to left or above pix", __func__, 1);
553
0
554
0
    if (x >= pixw || y >= pixh)
555
0
        return ERROR_INT("box to right or below pix", __func__, 1);
556
0
557
0
    return 0;
558
0
}