Leptonica 1.68
C Image Processing Library

rop.c

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines