Leptonica  1.54
Файл src/rop.c
#include <string.h>
#include "allheaders.h"

Функции

l_int32 pixRasterop (PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
l_int32 pixRasteropVip (PIX *pixd, l_int32 bx, l_int32 bw, l_int32 vshift, l_int32 incolor)
l_int32 pixRasteropHip (PIX *pixd, l_int32 by, l_int32 bh, l_int32 hshift, l_int32 incolor)
PIXpixTranslate (PIX *pixd, PIX *pixs, l_int32 hshift, l_int32 vshift, l_int32 incolor)
l_int32 pixRasteropIP (PIX *pixd, l_int32 hshift, l_int32 vshift, l_int32 incolor)
l_int32 pixRasteropFullImage (PIX *pixd, PIX *pixs, l_int32 op)

Функции

l_int32 pixRasterop ( PIX pixd,
l_int32  dx,
l_int32  dy,
l_int32  dw,
l_int32  dh,
l_int32  op,
PIX pixs,
l_int32  sx,
l_int32  sy 
)

pixRasterop()

Input: pixd (dest pix) dx (x val of UL corner of dest rectangle) dy (y val of UL corner of dest rectangle) dw (width of dest rectangle) dh (height of dest rectangle) op (op code) pixs (src pix) sx (x val of UL corner of src rectangle) sy (y val of UL corner of src rectangle) Return: 0 if OK; 1 on error.

Notes: (1) This has the standard set of 9 args for rasterop. This function is your friend; it is worth memorizing! (2) If the operation involves only dest, this calls rasteropUniLow(). Otherwise, checks depth of the src and dest, and if they match, calls rasteropLow(). (3) For the two-image operation, where both pixs and pixd are defined, they are typically different images. However there are cases, such as pixSetMirroredBorder(), where in-place operations can be done, blitting pixels from one part of pixd to another. Consequently, we permit such operations. If you use them, be sure that there is no overlap between the source and destination rectangles in pixd (!)

Background: -----------

There are 18 operations, described by the op codes in pix.h.

One, PIX_DST, is a no-op.

Three, PIX_CLR, PIX_SET, and PIX_NOT(PIX_DST) operate only on the dest. These are handled by the low-level rasteropUniLow().

The other 14 involve the both the src and the dest, and depend on the bit values of either just the src or the bit values of both src and dest. They are handled by rasteropLow():

PIX_SRC s PIX_NOT(PIX_SRC) ~s PIX_SRC | PIX_DST s | d PIX_SRC & PIX_DST s & d PIX_SRC ^ PIX_DST s ^ d PIX_NOT(PIX_SRC) | PIX_DST ~s | d PIX_NOT(PIX_SRC) & PIX_DST ~s & d PIX_NOT(PIX_SRC) ^ PIX_DST ~s ^ d PIX_SRC | PIX_NOT(PIX_DST) s | ~d PIX_SRC & PIX_NOT(PIX_DST) s & ~d PIX_SRC ^ PIX_NOT(PIX_DST) s ^ ~d PIX_NOT(PIX_SRC | PIX_DST) ~(s | d) PIX_NOT(PIX_SRC & PIX_DST) ~(s & d) PIX_NOT(PIX_SRC ^ PIX_DST) ~(s ^ d)

Each of these is implemented with one of three low-level functions, depending on the alignment of the left edge of the src and dest rectangles: * a fastest implementation if both left edges are (32-bit) word aligned * a very slightly slower implementation if both left edges have the same relative (32-bit) word alignment * the general routine that is invoked when both left edges have different word alignment

Of the 14 binary rasterops above, only 12 are unique logical combinations (out of a possible 16) of src and dst bits:

(sd) (11) (10) (01) (00) ----------------------------------------------- s 1 1 0 0 ~s 0 1 0 1 s | d 1 1 1 0 s & d 1 0 0 0 s ^ d 0 1 1 0 ~s | d 1 0 1 1 ~s & d 0 0 1 0 ~s ^ d 1 0 0 1 s | ~d 1 1 0 1 s & ~d 0 1 0 0 s ^ ~d 1 0 0 1 ~(s | d) 0 0 0 1 ~(s & d) 0 1 1 1 ~(s ^ d) 1 0 0 1

Note that the following three operations are equivalent: ~(s ^ d) ~s ^ d s ^ ~d and in the implementation, we call them out with the first form; namely, ~(s ^ d).

Of the 16 possible binary combinations of src and dest bits, the remaining 4 unique ones are independent of the src bit. They depend on either just the dest bit or on neither the src nor dest bits:

d 1 0 1 0 (indep. of s) ~d 0 1 0 1 (indep. of s) CLR 0 0 0 0 (indep. of both s & d) SET 1 1 1 1 (indep. of both s & d)

As mentioned above, three of these are implemented by rasteropUniLow(), and one is a no-op.

How can these operation codes be represented by bits in such a way that when the basic operations are performed on the bits the results are unique for unique operations, and mimic the logic table given above?

The answer is to choose a particular order of the pairings: (sd) (11) (10) (01) (00) (which happens to be the same as in the above table) and to translate the result into 4-bit representations of s and d. For example, the Sun rasterop choice (omitting the extra bit for clipping) is

PIX_SRC 0xc PIX_DST 0xa

This corresponds to our pairing order given above: (sd) (11) (10) (01) (00) where for s = 1 we get the bit pattern PIX_SRC: 1 1 0 0 (0xc) and for d = 1 we get the pattern PIX_DST: 1 0 1 0 (0xa)

OK, that's the pairing order that Sun chose. How many different ways can we assign bit patterns to PIX_SRC and PIX_DST to get the boolean ops to work out? Any of the 4 pairs can be put in the first position, any of the remaining 3 pairs can go in the second; and one of the remaining 2 pairs can go the the third. There is a total of 4*3*2 = 24 ways these pairs can be permuted.

l_int32 pixRasteropFullImage ( PIX pixd,
PIX pixs,
l_int32  op 
)

pixRasteropFullImage()

Input: pixd pixs op (any of the op-codes) Return: 0 if OK; 1 on error

Notes:

  • this is a wrapper for a common 2-image raster operation
  • both pixs and pixd must be defined
  • the operation is performed with aligned UL corners of pixs and pixd
  • the operation clips to the smallest pix; if the width or height of pixd is larger than pixs, some pixels in pixd will be unchanged
l_int32 pixRasteropHip ( PIX pixd,
l_int32  by,
l_int32  bh,
l_int32  hshift,
l_int32  incolor 
)

pixRasteropHip()

Input: pixd (in-place operation) by (top of horizontal band) bh (height of horizontal band) hshift (horizontal shift of band; hshift > 0 is to right) incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) Return: 0 if OK; 1 on error

Notes: (1) This rasterop translates a horizontal band of the image either left or right, bringing in either white or black pixels from outside the image. (2) The horizontal band extends the full width of pixd. (3) If a colormap exists, the nearest color to white or black is brought in.

l_int32 pixRasteropIP ( PIX pixd,
l_int32  hshift,
l_int32  vshift,
l_int32  incolor 
)

pixRasteropIP()

Input: pixd (in-place translation) hshift (horizontal shift; hshift > 0 is to right) vshift (vertical shift; vshift > 0 is down) incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) Return: 0 if OK; 1 on error

l_int32 pixRasteropVip ( PIX pixd,
l_int32  bx,
l_int32  bw,
l_int32  vshift,
l_int32  incolor 
)

pixRasteropVip()

Input: pixd (in-place) bx (left edge of vertical band) bw (width of vertical band) vshift (vertical shift of band; vshift > 0 is down) incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) Return: 0 if OK; 1 on error

Notes: (1) This rasterop translates a vertical band of the image either up or down, bringing in either white or black pixels from outside the image. (2) The vertical band extends the full height of pixd. (3) If a colormap exists, the nearest color to white or black is brought in.

PIX* pixTranslate ( PIX pixd,
PIX pixs,
l_int32  hshift,
l_int32  vshift,
l_int32  incolor 
)

pixTranslate()

Input: pixd (<optional> destination: this can be null, equal to pixs, or different from pixs) pixs hshift (horizontal shift; hshift > 0 is to right) vshift (vertical shift; vshift > 0 is down) incolor (L_BRING_IN_WHITE, L_BRING_IN_BLACK) Return: pixd, or null on error.

Notes: (1) The general pattern is: pixd = pixTranslate(pixd, pixs, ...); For clarity, when you know the case, use one of these: pixd = pixTranslate(NULL, pixs, ...); // new pixTranslate(pixs, pixs, ...); // in-place pixTranslate(pixd, pixs, ...); // to existing pixd (2) If an existing pixd is not the same size as pixs, the image data will be reallocated.