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 | } |