package Image::Leptonica::Func::rop;
$Image::Leptonica::Func::rop::VERSION = '0.03';

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Image::Leptonica::Func::rop

=head1 VERSION

version 0.03

=head1 C<rop.c>

  rop.c

      General rasterop
           l_int32    pixRasterop()

      In-place full band translation
           l_int32    pixRasteropVip()
           l_int32    pixRasteropHip()

      Full image translation (general and in-place)
           l_int32    pixTranslate()
           l_int32    pixRasteropIP()

      Full image rasterop with no translation
           l_int32    pixRasteropFullImage()

=head1 FUNCTIONS

=head2 pixRasterop

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.

=head2 pixRasteropFullImage

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

=head2 pixRasteropHip

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.

=head2 pixRasteropIP

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

=head2 pixRasteropVip

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.

=head2 pixTranslate

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.

=head1 AUTHOR

Zakariyya Mughal <zmughal@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by Zakariyya Mughal.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
