Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/rop.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 { | |
| 214 l_int32 dpw, dph, dpd, spw, sph, spd; | |
| 215 | |
| 216 if (!pixd) | |
| 217 return ERROR_INT("pixd not defined", __func__, 1); | |
| 218 | |
| 219 if (op == PIX_DST) /* no-op */ | |
| 220 return 0; | |
| 221 | |
| 222 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 if (op == PIX_CLR || op == PIX_SET || op == PIX_NOT(PIX_DST)) { | |
| 232 rasteropUniLow(pixGetData(pixd), dpw, dph, dpd, pixGetWpl(pixd), | |
| 233 dx, dy, dw, dh, op); | |
| 234 return 0; | |
| 235 } | |
| 236 | |
| 237 /* Two-image rasterop; the depths must match */ | |
| 238 if (!pixs) | |
| 239 return ERROR_INT("pixs not defined", __func__, 1); | |
| 240 pixGetDimensions(pixs, &spw, &sph, &spd); | |
| 241 if (dpd != spd) | |
| 242 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 rasteropLow(pixGetData(pixd), dpw, dph, dpd, pixGetWpl(pixd), | |
| 251 dx, dy, dw, dh, op, | |
| 252 pixGetData(pixs), spw, sph, pixGetWpl(pixs), sx, sy); | |
| 253 return 0; | |
| 254 } | |
| 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 { | |
| 287 l_int32 w, h, d, index, op; | |
| 288 PIX *pixt; | |
| 289 PIXCMAP *cmap; | |
| 290 | |
| 291 if (!pixd) | |
| 292 return ERROR_INT("pixd not defined", __func__, 1); | |
| 293 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) | |
| 294 return ERROR_INT("invalid value for incolor", __func__, 1); | |
| 295 if (bw <= 0) | |
| 296 return ERROR_INT("bw must be > 0", __func__, 1); | |
| 297 | |
| 298 if (vshift == 0) | |
| 299 return 0; | |
| 300 | |
| 301 pixGetDimensions(pixd, &w, &h, &d); | |
| 302 rasteropVipLow(pixGetData(pixd), w, h, d, pixGetWpl(pixd), bx, bw, vshift); | |
| 303 | |
| 304 cmap = pixGetColormap(pixd); | |
| 305 if (!cmap) { | |
| 306 if ((d == 1 && incolor == L_BRING_IN_BLACK) || | |
| 307 (d > 1 && incolor == L_BRING_IN_WHITE)) | |
| 308 op = PIX_SET; | |
| 309 else | |
| 310 op = PIX_CLR; | |
| 311 | |
| 312 /* Set the pixels brought in at top or bottom */ | |
| 313 if (vshift > 0) | |
| 314 pixRasterop(pixd, bx, 0, bw, vshift, op, NULL, 0, 0); | |
| 315 else /* vshift < 0 */ | |
| 316 pixRasterop(pixd, bx, h + vshift, bw, -vshift, op, NULL, 0, 0); | |
| 317 return 0; | |
| 318 } | |
| 319 | |
| 320 /* Get the nearest index and fill with that */ | |
| 321 if (incolor == L_BRING_IN_BLACK) | |
| 322 pixcmapGetRankIntensity(cmap, 0.0, &index); | |
| 323 else /* white */ | |
| 324 pixcmapGetRankIntensity(cmap, 1.0, &index); | |
| 325 pixt = pixCreate(bw, L_ABS(vshift), d); | |
| 326 pixSetAllArbitrary(pixt, index); | |
| 327 if (vshift > 0) | |
| 328 pixRasterop(pixd, bx, 0, bw, vshift, PIX_SRC, pixt, 0, 0); | |
| 329 else /* vshift < 0 */ | |
| 330 pixRasterop(pixd, bx, h + vshift, bw, -vshift, PIX_SRC, pixt, 0, 0); | |
| 331 pixDestroy(&pixt); | |
| 332 return 0; | |
| 333 } | |
| 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 { | |
| 363 l_int32 w, h, d, index, op; | |
| 364 PIX *pixt; | |
| 365 PIXCMAP *cmap; | |
| 366 | |
| 367 if (!pixd) | |
| 368 return ERROR_INT("pixd not defined", __func__, 1); | |
| 369 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) | |
| 370 return ERROR_INT("invalid value for incolor", __func__, 1); | |
| 371 if (bh <= 0) | |
| 372 return ERROR_INT("bh must be > 0", __func__, 1); | |
| 373 | |
| 374 if (hshift == 0) | |
| 375 return 0; | |
| 376 | |
| 377 pixGetDimensions(pixd, &w, &h, &d); | |
| 378 rasteropHipLow(pixGetData(pixd), h, d, pixGetWpl(pixd), by, bh, hshift); | |
| 379 | |
| 380 cmap = pixGetColormap(pixd); | |
| 381 if (!cmap) { | |
| 382 if ((d == 1 && incolor == L_BRING_IN_BLACK) || | |
| 383 (d > 1 && incolor == L_BRING_IN_WHITE)) | |
| 384 op = PIX_SET; | |
| 385 else | |
| 386 op = PIX_CLR; | |
| 387 | |
| 388 /* Set the pixels brought in at left or right */ | |
| 389 if (hshift > 0) | |
| 390 pixRasterop(pixd, 0, by, hshift, bh, op, NULL, 0, 0); | |
| 391 else /* hshift < 0 */ | |
| 392 pixRasterop(pixd, w + hshift, by, -hshift, bh, op, NULL, 0, 0); | |
| 393 return 0; | |
| 394 } | |
| 395 | |
| 396 /* Get the nearest index and fill with that */ | |
| 397 if (incolor == L_BRING_IN_BLACK) | |
| 398 pixcmapGetRankIntensity(cmap, 0.0, &index); | |
| 399 else /* white */ | |
| 400 pixcmapGetRankIntensity(cmap, 1.0, &index); | |
| 401 pixt = pixCreate(L_ABS(hshift), bh, d); | |
| 402 pixSetAllArbitrary(pixt, index); | |
| 403 if (hshift > 0) | |
| 404 pixRasterop(pixd, 0, by, hshift, bh, PIX_SRC, pixt, 0, 0); | |
| 405 else /* hshift < 0 */ | |
| 406 pixRasterop(pixd, w + hshift, by, -hshift, bh, PIX_SRC, pixt, 0, 0); | |
| 407 pixDestroy(&pixt); | |
| 408 return 0; | |
| 409 } | |
| 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 { | |
| 445 if (!pixs) | |
| 446 return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL); | |
| 447 | |
| 448 /* Prepare pixd for in-place operation */ | |
| 449 if ((pixd = pixCopy(pixd, pixs)) == NULL) | |
| 450 return (PIX *)ERROR_PTR("pixd not made", __func__, NULL); | |
| 451 | |
| 452 pixRasteropIP(pixd, hshift, vshift, incolor); | |
| 453 return pixd; | |
| 454 } | |
| 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 { | |
| 472 l_int32 w, h; | |
| 473 | |
| 474 if (!pixd) | |
| 475 return ERROR_INT("pixd not defined", __func__, 1); | |
| 476 | |
| 477 pixGetDimensions(pixd, &w, &h, NULL); | |
| 478 pixRasteropHip(pixd, 0, h, hshift, incolor); | |
| 479 pixRasteropVip(pixd, 0, w, vshift, incolor); | |
| 480 | |
| 481 return 0; | |
| 482 } | |
| 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 { | |
| 510 if (!pixd) | |
| 511 return ERROR_INT("pixd not defined", __func__, 1); | |
| 512 if (!pixs) | |
| 513 return ERROR_INT("pixs not defined", __func__, 1); | |
| 514 | |
| 515 pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd), op, | |
| 516 pixs, 0, 0); | |
| 517 return 0; | |
| 518 } | |
| 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 { | |
| 548 if (pixw < 1 || pixh < 1 || w < 1 || h < 1) | |
| 549 return ERROR_INT("dimension is <= 0", __func__, 1); | |
| 550 | |
| 551 if (x + w <= 0 || y + h <= 0) | |
| 552 return ERROR_INT("box to left or above pix", __func__, 1); | |
| 553 | |
| 554 if (x >= pixw || y >= pixh) | |
| 555 return ERROR_INT("box to right or below pix", __func__, 1); | |
| 556 | |
| 557 return 0; | |
| 558 } |
