Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /* 00017 * rop.c 00018 * 00019 * General rasterop 00020 * l_int32 pixRasterop() 00021 * 00022 * In-place full band translation 00023 * l_int32 pixRasteropVip() 00024 * l_int32 pixRasteropHip() 00025 * 00026 * Full image translation (general and in-place) 00027 * l_int32 pixTranslate() 00028 * l_int32 pixRasteropIP() 00029 * 00030 * Full image rasterop with no translation 00031 * l_int32 pixRasteropFullImage() 00032 */ 00033 00034 00035 #include <string.h> 00036 #include "allheaders.h" 00037 00038 /*--------------------------------------------------------------------* 00039 * General rasterop (basic pix interface) * 00040 *--------------------------------------------------------------------*/ 00041 /*! 00042 * pixRasterop() 00043 * 00044 * Input: pixd (dest pix) 00045 * dx (x val of UL corner of dest rectangle) 00046 * dy (y val of UL corner of dest rectangle) 00047 * dw (width of dest rectangle) 00048 * dh (height of dest rectangle) 00049 * op (op code) 00050 * pixs (src pix) 00051 * sx (x val of UL corner of src rectangle) 00052 * sy (y val of UL corner of src rectangle) 00053 * Return: 0 if OK; 1 on error. 00054 * 00055 * Notes: 00056 * (1) This has the standard set of 9 args for rasterop. 00057 * This function is your friend; it is worth memorizing! 00058 * (2) If the operation involves only dest, this calls 00059 * rasteropUniLow(). Otherwise, checks depth of the 00060 * src and dest, and if they match, calls rasteropLow(). 00061 * (3) For the two-image operation, where both pixs and pixd 00062 * are defined, they are typically different images. However 00063 * there are cases, such as pixSetMirroredBorder(), where 00064 * in-place operations can be done, blitting pixels from 00065 * one part of pixd to another. Consequently, we permit 00066 * such operations. If you use them, be sure that there 00067 * is no overlap between the source and destination rectangles 00068 * in pixd (!) 00069 * 00070 * Background: 00071 * ----------- 00072 * 00073 * There are 18 operations, described by the op codes in pix.h. 00074 * 00075 * One, PIX_DST, is a no-op. 00076 * 00077 * Three, PIX_CLR, PIX_SET, and PIX_NOT(PIX_DST) operate only on the dest. 00078 * These are handled by the low-level rasteropUniLow(). 00079 * 00080 * The other 14 involve the both the src and the dest, and depend on 00081 * the bit values of either just the src or the bit values of both 00082 * src and dest. They are handled by rasteropLow(): 00083 * 00084 * PIX_SRC s 00085 * PIX_NOT(PIX_SRC) ~s 00086 * PIX_SRC | PIX_DST s | d 00087 * PIX_SRC & PIX_DST s & d 00088 * PIX_SRC ^ PIX_DST s ^ d 00089 * PIX_NOT(PIX_SRC) | PIX_DST ~s | d 00090 * PIX_NOT(PIX_SRC) & PIX_DST ~s & d 00091 * PIX_NOT(PIX_SRC) ^ PIX_DST ~s ^ d 00092 * PIX_SRC | PIX_NOT(PIX_DST) s | ~d 00093 * PIX_SRC & PIX_NOT(PIX_DST) s & ~d 00094 * PIX_SRC ^ PIX_NOT(PIX_DST) s ^ ~d 00095 * PIX_NOT(PIX_SRC | PIX_DST) ~(s | d) 00096 * PIX_NOT(PIX_SRC & PIX_DST) ~(s & d) 00097 * PIX_NOT(PIX_SRC ^ PIX_DST) ~(s ^ d) 00098 * 00099 * Each of these is implemented with one of three low-level 00100 * functions, depending on the alignment of the left edge 00101 * of the src and dest rectangles: 00102 * * a fastest implementation if both left edges are 00103 * (32-bit) word aligned 00104 * * a very slightly slower implementation if both left 00105 * edges have the same relative (32-bit) word alignment 00106 * * the general routine that is invoked when 00107 * both left edges have different word alignment 00108 * 00109 * Of the 14 binary rasterops above, only 12 are unique 00110 * logical combinations (out of a possible 16) of src 00111 * and dst bits: 00112 * 00113 * (sd) (11) (10) (01) (00) 00114 * ----------------------------------------------- 00115 * s 1 1 0 0 00116 * ~s 0 1 0 1 00117 * s | d 1 1 1 0 00118 * s & d 1 0 0 0 00119 * s ^ d 0 1 1 0 00120 * ~s | d 1 0 1 1 00121 * ~s & d 0 0 1 0 00122 * ~s ^ d 1 0 0 1 00123 * s | ~d 1 1 0 1 00124 * s & ~d 0 1 0 0 00125 * s ^ ~d 1 0 0 1 00126 * ~(s | d) 0 0 0 1 00127 * ~(s & d) 0 1 1 1 00128 * ~(s ^ d) 1 0 0 1 00129 * 00130 * Note that the following three operations are equivalent: 00131 * ~(s ^ d) 00132 * ~s ^ d 00133 * s ^ ~d 00134 * and in the implementation, we call them out with the first form; 00135 * namely, ~(s ^ d). 00136 * 00137 * Of the 16 possible binary combinations of src and dest bits, 00138 * the remaining 4 unique ones are independent of the src bit. 00139 * They depend on either just the dest bit or on neither 00140 * the src nor dest bits: 00141 * 00142 * d 1 0 1 0 (indep. of s) 00143 * ~d 0 1 0 1 (indep. of s) 00144 * CLR 0 0 0 0 (indep. of both s & d) 00145 * SET 1 1 1 1 (indep. of both s & d) 00146 * 00147 * As mentioned above, three of these are implemented by 00148 * rasteropUniLow(), and one is a no-op. 00149 * 00150 * How can these operation codes be represented by bits 00151 * in such a way that when the basic operations are performed 00152 * on the bits the results are unique for unique 00153 * operations, and mimic the logic table given above? 00154 * 00155 * The answer is to choose a particular order of the pairings: 00156 * (sd) (11) (10) (01) (00) 00157 * (which happens to be the same as in the above table) 00158 * and to translate the result into 4-bit representations 00159 * of s and d. For example, the Sun rasterop choice 00160 * (omitting the extra bit for clipping) is 00161 * 00162 * PIX_SRC 0xc 00163 * PIX_DST 0xa 00164 * 00165 * This corresponds to our pairing order given above: 00166 * (sd) (11) (10) (01) (00) 00167 * where for s = 1 we get the bit pattern 00168 * PIX_SRC: 1 1 0 0 (0xc) 00169 * and for d = 1 we get the pattern 00170 * PIX_DST: 1 0 1 0 (0xa) 00171 * 00172 * OK, that's the pairing order that Sun chose. How many different 00173 * ways can we assign bit patterns to PIX_SRC and PIX_DST to get 00174 * the boolean ops to work out? Any of the 4 pairs can be put 00175 * in the first position, any of the remaining 3 pairs can go 00176 * in the second; and one of the remaining 2 pairs can go the the third. 00177 * There is a total of 4*3*2 = 24 ways these pairs can be permuted. 00178 */ 00179 l_int32 00180 pixRasterop(PIX *pixd, 00181 l_int32 dx, 00182 l_int32 dy, 00183 l_int32 dw, 00184 l_int32 dh, 00185 l_int32 op, 00186 PIX *pixs, 00187 l_int32 sx, 00188 l_int32 sy) 00189 { 00190 l_int32 dd; 00191 00192 PROCNAME("pixRasterop"); 00193 00194 if (!pixd) 00195 return ERROR_INT("pixd not defined", procName, 1); 00196 00197 if (op == PIX_DST) /* no-op */ 00198 return 0; 00199 00200 /* Check if operation is only on dest */ 00201 dd = pixGetDepth(pixd); 00202 if (op == PIX_CLR || op == PIX_SET || op == PIX_NOT(PIX_DST)) { 00203 rasteropUniLow(pixGetData(pixd), 00204 pixGetWidth(pixd), pixGetHeight(pixd), dd, 00205 pixGetWpl(pixd), 00206 dx, dy, dw, dh, 00207 op); 00208 return 0; 00209 } 00210 00211 if (!pixs) 00212 return ERROR_INT("pixs not defined", procName, 1); 00213 00214 /* Check depth of src and dest; these must agree */ 00215 if (dd != pixGetDepth(pixs)) 00216 return ERROR_INT("depths of pixs and pixd differ", procName, 1); 00217 00218 rasteropLow(pixGetData(pixd), 00219 pixGetWidth(pixd), pixGetHeight(pixd), dd, 00220 pixGetWpl(pixd), 00221 dx, dy, dw, dh, 00222 op, 00223 pixGetData(pixs), 00224 pixGetWidth(pixs), pixGetHeight(pixs), 00225 pixGetWpl(pixs), 00226 sx, sy); 00227 00228 return 0; 00229 } 00230 00231 00232 /*--------------------------------------------------------------------* 00233 * In-place full band translation * 00234 *--------------------------------------------------------------------*/ 00235 /*! 00236 * pixRasteropVip() 00237 * 00238 * Input: pixd (in-place) 00239 * bx (left edge of vertical band) 00240 * bw (width of vertical band) 00241 * vshift (vertical shift of band; vshift > 0 is down) 00242 * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) 00243 * Return: 0 if OK; 1 on error 00244 * 00245 * Notes: 00246 * (1) This rasterop translates a vertical band of the 00247 * image either up or down, bringing in either white 00248 * or black pixels from outside the image. 00249 * (2) The vertical band extends the full height of pixd. 00250 * (3) If a colormap exists, the nearest color to white or black 00251 * is brought in. 00252 */ 00253 l_int32 00254 pixRasteropVip(PIX *pixd, 00255 l_int32 bx, 00256 l_int32 bw, 00257 l_int32 vshift, 00258 l_int32 incolor) 00259 { 00260 l_int32 w, h, d, index, op; 00261 PIX *pixt; 00262 PIXCMAP *cmap; 00263 00264 PROCNAME("pixRasteropVip"); 00265 00266 if (!pixd) 00267 return ERROR_INT("pixd not defined", procName, 1); 00268 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) 00269 return ERROR_INT("invalid value for incolor", procName, 1); 00270 if (bw <= 0) 00271 return ERROR_INT("width must be > 1", procName, 1); 00272 00273 if (vshift == 0) 00274 return 0; 00275 00276 pixGetDimensions(pixd, &w, &h, &d); 00277 rasteropVipLow(pixGetData(pixd), w, h, d, pixGetWpl(pixd), bx, bw, vshift); 00278 00279 cmap = pixGetColormap(pixd); 00280 if (!cmap) { 00281 if ((d == 1 && incolor == L_BRING_IN_BLACK) || 00282 (d > 1 && incolor == L_BRING_IN_WHITE)) 00283 op = PIX_SET; 00284 else 00285 op = PIX_CLR; 00286 00287 /* Set the pixels brought in at top or bottom */ 00288 if (vshift > 0) 00289 pixRasterop(pixd, bx, 0, bw, vshift, op, NULL, 0, 0); 00290 else /* vshift < 0 */ 00291 pixRasterop(pixd, bx, h + vshift, bw, -vshift, op, NULL, 0, 0); 00292 return 0; 00293 } 00294 00295 /* Get the nearest index and fill with that */ 00296 if (incolor == L_BRING_IN_BLACK) 00297 pixcmapGetRankIntensity(cmap, 0.0, &index); 00298 else /* white */ 00299 pixcmapGetRankIntensity(cmap, 1.0, &index); 00300 pixt = pixCreate(bw, L_ABS(vshift), d); 00301 pixSetAllArbitrary(pixt, index); 00302 if (vshift > 0) 00303 pixRasterop(pixd, bx, 0, bw, vshift, PIX_SRC, pixt, 0, 0); 00304 else /* vshift < 0 */ 00305 pixRasterop(pixd, bx, h + vshift, bw, -vshift, PIX_SRC, pixt, 0, 0); 00306 pixDestroy(&pixt); 00307 return 0; 00308 } 00309 00310 00311 /*! 00312 * pixRasteropHip() 00313 * 00314 * Input: pixd (in-place operation) 00315 * by (top of horizontal band) 00316 * bh (height of horizontal band) 00317 * hshift (horizontal shift of band; hshift > 0 is to right) 00318 * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) 00319 * Return: 0 if OK; 1 on error 00320 * 00321 * Notes: 00322 * (1) This rasterop translates a horizontal band of the 00323 * image either left or right, bringing in either white 00324 * or black pixels from outside the image. 00325 * (2) The horizontal band extends the full width of pixd. 00326 * (3) If a colormap exists, the nearest color to white or black 00327 * is brought in. 00328 */ 00329 l_int32 00330 pixRasteropHip(PIX *pixd, 00331 l_int32 by, 00332 l_int32 bh, 00333 l_int32 hshift, 00334 l_int32 incolor) 00335 { 00336 l_int32 w, h, d, index, op; 00337 PIX *pixt; 00338 PIXCMAP *cmap; 00339 00340 PROCNAME("pixRasteropHip"); 00341 00342 if (!pixd) 00343 return ERROR_INT("pixd not defined", procName, 1); 00344 if (incolor != L_BRING_IN_WHITE && incolor != L_BRING_IN_BLACK) 00345 return ERROR_INT("invalid value for incolor", procName, 1); 00346 if (bh <= 0) 00347 return ERROR_INT("bh must be > 0", procName, 1); 00348 00349 if (hshift == 0) 00350 return 0; 00351 00352 pixGetDimensions(pixd, &w, &h, &d); 00353 rasteropHipLow(pixGetData(pixd), h, d, pixGetWpl(pixd), by, bh, hshift); 00354 00355 cmap = pixGetColormap(pixd); 00356 if (!cmap) { 00357 if ((d == 1 && incolor == L_BRING_IN_BLACK) || 00358 (d > 1 && incolor == L_BRING_IN_WHITE)) 00359 op = PIX_SET; 00360 else 00361 op = PIX_CLR; 00362 00363 /* Set the pixels brought in at left or right */ 00364 if (hshift > 0) 00365 pixRasterop(pixd, 0, by, hshift, bh, op, NULL, 0, 0); 00366 else /* hshift < 0 */ 00367 pixRasterop(pixd, w + hshift, by, -hshift, bh, op, NULL, 0, 0); 00368 return 0; 00369 } 00370 00371 /* Get the nearest index and fill with that */ 00372 if (incolor == L_BRING_IN_BLACK) 00373 pixcmapGetRankIntensity(cmap, 0.0, &index); 00374 else /* white */ 00375 pixcmapGetRankIntensity(cmap, 1.0, &index); 00376 pixt = pixCreate(L_ABS(hshift), bh, d); 00377 pixSetAllArbitrary(pixt, index); 00378 if (hshift > 0) 00379 pixRasterop(pixd, 0, by, hshift, bh, PIX_SRC, pixt, 0, 0); 00380 else /* hshift < 0 */ 00381 pixRasterop(pixd, w + hshift, by, -hshift, bh, PIX_SRC, pixt, 0, 0); 00382 pixDestroy(&pixt); 00383 return 0; 00384 } 00385 00386 00387 /*--------------------------------------------------------------------* 00388 * Full image translation (general and in-place) * 00389 *--------------------------------------------------------------------*/ 00390 /*! 00391 * pixTranslate() 00392 * 00393 * Input: pixd (<optional> destination: this can be null, 00394 * equal to pixs, or different from pixs) 00395 * pixs 00396 * hshift (horizontal shift; hshift > 0 is to right) 00397 * vshift (vertical shift; vshift > 0 is down) 00398 * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) 00399 * Return: pixd, or null on error. 00400 * 00401 * Notes: 00402 * (1) The general pattern is: 00403 * pixd = pixTranslate(pixd, pixs, ...); 00404 * For clarity, when you know the case, use one of these: 00405 * pixd = pixTranslate(NULL, pixs, ...); // new 00406 * pixTranslate(pixs, pixs, ...); // in-place 00407 * pixTranslate(pixd, pixs, ...); // to existing pixd 00408 * (2) If an existing pixd is not the same size as pixs, the 00409 * image data will be reallocated. 00410 */ 00411 PIX * 00412 pixTranslate(PIX *pixd, 00413 PIX *pixs, 00414 l_int32 hshift, 00415 l_int32 vshift, 00416 l_int32 incolor) 00417 { 00418 PROCNAME("pixTranslate"); 00419 00420 if (!pixs) 00421 return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); 00422 00423 /* Prepare pixd for in-place operation */ 00424 if ((pixd = pixCopy(pixd, pixs)) == NULL) 00425 return (PIX *)ERROR_PTR("pixd not made", procName, NULL); 00426 00427 pixRasteropIP(pixd, hshift, vshift, incolor); 00428 return pixd; 00429 } 00430 00431 00432 /*! 00433 * pixRasteropIP() 00434 * 00435 * Input: pixd (in-place translation) 00436 * hshift (horizontal shift; hshift > 0 is to right) 00437 * vshift (vertical shift; vshift > 0 is down) 00438 * incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) 00439 * Return: 0 if OK; 1 on error 00440 */ 00441 l_int32 00442 pixRasteropIP(PIX *pixd, 00443 l_int32 hshift, 00444 l_int32 vshift, 00445 l_int32 incolor) 00446 { 00447 l_int32 w, h; 00448 00449 PROCNAME("pixRasteropIP"); 00450 00451 if (!pixd) 00452 return ERROR_INT("pixd not defined", procName, 1); 00453 00454 pixGetDimensions(pixd, &w, &h, NULL); 00455 pixRasteropHip(pixd, 0, h, hshift, incolor); 00456 pixRasteropVip(pixd, 0, w, vshift, incolor); 00457 00458 return 0; 00459 } 00460 00461 00462 /*--------------------------------------------------------------------* 00463 * Full image rasterop with no shifts * 00464 *--------------------------------------------------------------------*/ 00465 /*! 00466 * pixRasteropFullImage() 00467 * 00468 * Input: pixd 00469 * pixs 00470 * op (any of the op-codes) 00471 * Return: 0 if OK; 1 on error 00472 * 00473 * Notes: 00474 * - this is a wrapper for a common 2-image raster operation 00475 * - both pixs and pixd must be defined 00476 * - the operation is performed with aligned UL corners of pixs and pixd 00477 * - the operation clips to the smallest pix; if the width or height 00478 * of pixd is larger than pixs, some pixels in pixd will be unchanged 00479 */ 00480 l_int32 00481 pixRasteropFullImage(PIX *pixd, 00482 PIX *pixs, 00483 l_int32 op) 00484 { 00485 PROCNAME("pixRasteropFullImage"); 00486 00487 if (!pixd) 00488 return ERROR_INT("pixd not defined", procName, 1); 00489 if (!pixs) 00490 return ERROR_INT("pixs not defined", procName, 1); 00491 00492 pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd), op, 00493 pixs, 0, 0); 00494 return 0; 00495 } 00496