]> git.imager.perl.org - imager.git/commitdiff
- added comment support the postfix transform2() expression
authorTony Cook <tony@develop=help.com>
Thu, 26 Jun 2003 03:50:00 +0000 (03:50 +0000)
committerTony Cook <tony@develop=help.com>
Thu, 26 Jun 2003 03:50:00 +0000 (03:50 +0000)
          parser
        - transform2() can now produce images with other than 3 channels.
        - added a correct T_AVREF input mapping to the typemap to
          simplify parameter lists

Changes
Imager.pm
Imager.xs
lib/Imager/Engines.pod
lib/Imager/Expr.pm
lib/Imager/Regops.pm
regmach.c
regmach.h
t/t56postfix.t
t/t58trans2.t
typemap

diff --git a/Changes b/Changes
index 63a29956905bc17b4872c62398adc3a065d41151..a32d377d0bdf60e992a33bbf103d1f61d0cb510a 100644 (file)
--- a/Changes
+++ b/Changes
@@ -720,6 +720,11 @@ Revision history for Perl extension Imager.
           source image is used.
         - the image fills didn't handle filling with source images of
           less than four channels correctly
           source image is used.
         - the image fills didn't handle filling with source images of
           less than four channels correctly
+        - added comment support the postfix transform2() expression
+          parser
+        - transform2() can now produce images with other than 3 channels.
+        - added a correct T_AVREF input mapping to the typemap to 
+          simplify parameter lists
 
 =================================================================
 
 
 =================================================================
 
index 9ddd35c052f66fbb72c818303995cbd9c96a6e40..953e11147605b20ba5e09079da0ed70f12ae69e4 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -1722,9 +1722,14 @@ sub transform2 {
     $Imager::ERRSTR = Imager::Expr::error();
     return;
   }
     $Imager::ERRSTR = Imager::Expr::error();
     return;
   }
+  my $channels = $opts->{channels} || 3;
+  unless ($channels >= 1 && $channels <= 4) {
+    return Imager->_set_error("channels must be an integer between 1 and 4");
+  }
 
   my $img = Imager->new();
 
   my $img = Imager->new();
-  $img->{IMG} = i_transform2($opts->{width}, $opts->{height}, $code->code(),
+  $img->{IMG} = i_transform2($opts->{width}, $opts->{height}, 
+                            $channels, $code->code(),
                              $code->nregs(), $code->cregs(),
                              [ map { $_->{IMG} } @imgs ]);
   if (!defined $img->{IMG}) {
                              $code->nregs(), $code->cregs(),
                              [ map { $_->{IMG} } @imgs ]);
   if (!defined $img->{IMG}) {
index 5e79c193e67d147d8ec31d5d5bfeafa91f39327e..81ff9c62fa6ae515563cc8641a00813df6ba72f0 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -2870,7 +2870,14 @@ i_transform(im,opx,opy,parm)
              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
 
 Imager::ImgRaw
              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
 
 Imager::ImgRaw
-i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
+i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
+       SV *sv_width
+       SV *sv_height
+       SV *sv_ops
+       AV *av_n_regs
+       AV *av_c_regs
+       AV *av_in_imgs
+       int channels
             PREINIT:
              int width;
              int height;
             PREINIT:
              int width;
              int height;
@@ -2889,32 +2896,18 @@ i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
              IV tmp;
             int i;
              CODE:
              IV tmp;
             int i;
              CODE:
-            if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
-            if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
-            if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
-            if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
-
-       /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
-
-             if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
-              av = (AV*)SvRV(ST(5));
-               in_imgs_count = av_len(av)+1;
-              for (i = 0; i < in_imgs_count; ++i) {
-                sv1 = *av_fetch(av, i, 0);
-                if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
-                  croak("Parameter 5 must contain only images");
-                }
+
+             in_imgs_count = av_len(av_in_imgs)+1;
+            for (i = 0; i < in_imgs_count; ++i) {
+              sv1 = *av_fetch(av_in_imgs, i, 0);
+              if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
+                croak("sv_in_img must contain only images");
               }
             }
               }
             }
-            else {
-              in_imgs_count = 0;
-             }
              if (in_imgs_count > 0) {
              if (in_imgs_count > 0) {
-               av = (AV*)SvRV(ST(5));
                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
                for (i = 0; i < in_imgs_count; ++i) {              
                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
                for (i = 0; i < in_imgs_count; ++i) {              
-                sv1 = *av_fetch(av,i,0);
+                sv1 = *av_fetch(av_in_imgs,i,0);
                 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
                   croak("Parameter 5 must contain only images");
                 }
                 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
                   croak("Parameter 5 must contain only images");
                 }
@@ -2927,38 +2920,37 @@ i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
               in_imgs = NULL;
              }
              /* default the output size from the first input if possible */
               in_imgs = NULL;
              }
              /* default the output size from the first input if possible */
-             if (SvOK(ST(0)))
-              width = SvIV(ST(0));
+             if (SvOK(sv_width))
+              width = SvIV(sv_width);
              else if (in_imgs_count)
               width = in_imgs[0]->xsize;
              else
               croak("No output image width supplied");
 
              else if (in_imgs_count)
               width = in_imgs[0]->xsize;
              else
               croak("No output image width supplied");
 
-             if (SvOK(ST(1)))
-              height = SvIV(ST(1));
+             if (SvOK(sv_height))
+              height = SvIV(sv_height);
              else if (in_imgs_count)
               height = in_imgs[0]->ysize;
              else
               croak("No output image height supplied");
 
              else if (in_imgs_count)
               height = in_imgs[0]->ysize;
              else
               croak("No output image height supplied");
 
-            ops = (struct rm_op *)SvPV(ST(2), ops_len);
+            ops = (struct rm_op *)SvPV(sv_ops, ops_len);
              if (ops_len % sizeof(struct rm_op))
                 croak("Imager: Parameter 3 must be a bitmap of regops\n");
             ops_count = ops_len / sizeof(struct rm_op);
              if (ops_len % sizeof(struct rm_op))
                 croak("Imager: Parameter 3 must be a bitmap of regops\n");
             ops_count = ops_len / sizeof(struct rm_op);
-            av = (AV*)SvRV(ST(3));
-            n_regs_count = av_len(av)+1;
+
+            n_regs_count = av_len(av_n_regs)+1;
              n_regs = mymalloc(n_regs_count * sizeof(double));
             for (i = 0; i < n_regs_count; ++i) {
              n_regs = mymalloc(n_regs_count * sizeof(double));
             for (i = 0; i < n_regs_count; ++i) {
-              sv1 = *av_fetch(av,i,0);
+              sv1 = *av_fetch(av_n_regs,i,0);
               if (SvOK(sv1))
                 n_regs[i] = SvNV(sv1);
             }
               if (SvOK(sv1))
                 n_regs[i] = SvNV(sv1);
             }
-             av = (AV*)SvRV(ST(4));
-             c_regs_count = av_len(av)+1;
+             c_regs_count = av_len(av_c_regs)+1;
              c_regs = mymalloc(c_regs_count * sizeof(i_color));
              /* I don't bother initializing the colou?r registers */
 
              c_regs = mymalloc(c_regs_count * sizeof(i_color));
              /* I don't bother initializing the colou?r registers */
 
-            RETVAL=i_transform2(width, height, 3, ops, ops_count, 
+            RETVAL=i_transform2(width, height, channels, ops, ops_count, 
                                 n_regs, n_regs_count, 
                                 c_regs, c_regs_count, in_imgs, in_imgs_count);
             if (in_imgs)
                                 n_regs, n_regs_count, 
                                 c_regs, c_regs_count, in_imgs, in_imgs_count);
             if (in_imgs)
index 17914006868d605a24053e4acfe691ccb0467399..68aec86c9aac94cec5a268944a2a44946f4ab1bd 100644 (file)
@@ -91,6 +91,11 @@ images an error occurs.
 constants - a reference to hash of constants to define for the
 expression engine.  Some extra constants are defined by Imager
 
 constants - a reference to hash of constants to define for the
 expression engine.  Some extra constants are defined by Imager
 
+=item *
+
+channels - the number of channels in the output image.  If this isn't
+supplied a 3 channel image will be created.
+
 =back
 
 The tranformation function is specified using either the expr or
 =back
 
 The tranformation function is specified using either the expr or
@@ -180,16 +185,21 @@ respectively.  I may add a getpn() function at some point, but this
 prevents static checking of the instructions against the number of
 images actually passed in.
 
 prevents static checking of the instructions against the number of
 images actually passed in.
 
-=item value(c), hue(c), sat(c), hsv(h,s,v)
+=item value(c), hue(c), sat(c), hsv(h,s,v), hsva(h,s,v,alpha)
 
 Separates a colour value into it's value (brightness), hue (colour)
 and saturation elements.  Use hsv() to put them back together (after
 
 Separates a colour value into it's value (brightness), hue (colour)
 and saturation elements.  Use hsv() to put them back together (after
-suitable manipulation).
+suitable manipulation), or hsva() to include a tranparency value.
 
 =item red(c), green(c), blue(c), rgb(r,g,b)
 
 Separates a colour value into it's red, green and blue colours.  Use
 
 =item red(c), green(c), blue(c), rgb(r,g,b)
 
 Separates a colour value into it's red, green and blue colours.  Use
-rgb(r,g,b) to put it back together.
+rgb(r,g,b) to put it back together, or rgba() to include a
+transparency value.
+
+=item alpha(c)
+
+Retrieve the alpha value from a colour.
 
 =item int(n)
 
 
 =item int(n)
 
@@ -262,6 +272,17 @@ L<Imager::regmach.pod>.
   EOS
                                   });
 
   EOS
                                   });
 
+  # replace green portions of an image with another image
+  my $newimg = Imager::transform2({
+                                   rpnexpr => <<EOS
+  x y getp2 !pat # used to replace green portions
+  x y getp1 !pix # source with "green screen"
+  @pix red 10 lt @pix blue 10 lt && # low blue and red
+  @pix green 254 gt && # and high green
+  @pat @pix ifp
+  EOS
+                                  }, $source, $background);
+
 =head2 Matrix Transformations
 
 Rather than having to write code in a little language, you can use a
 =head2 Matrix Transformations
 
 Rather than having to write code in a little language, you can use a
index 5effa507a10ca35727a8edc85d9764a1e7708dee..8833dc9f51f559535cb4e96229a26745d1302bca 100644 (file)
@@ -298,6 +298,7 @@ my %op_names = ( '+'=>'add', '-'=>'subtract', '*'=>'mult', '/' => 'div',
 sub compile {
   my ($self, $expr, $opts) = @_;
 
 sub compile {
   my ($self, $expr, $opts) = @_;
 
+  $expr =~ s/#.*//; # remove comments
   my @st_ops = split ' ', $expr;
 
   for (@st_ops) {
   my @st_ops = split ' ', $expr;
 
   for (@st_ops) {
index 01712f1f6dbdd7af444f7438ea3de775f728a06a..644b8b5e49815fa3c58e108acb8f1bee4bbcbcec 100644 (file)
@@ -52,340 +52,364 @@ use constant RBC_JUMPNZ => 42;
 use constant RBC_SET => 43;
 use constant RBC_SETP => 44;
 use constant RBC_PRINT => 45;
 use constant RBC_SET => 43;
 use constant RBC_SETP => 44;
 use constant RBC_PRINT => 45;
-use constant RBC_OP_COUNT => 46;
+use constant RBC_RGBA => 46;
+use constant RBC_HSVA => 47;
+use constant RBC_ALPHA => 48;
+use constant RBC_OP_COUNT => 49;
 
 
-@EXPORT = qw(RBC_ADD RBC_SUBTRACT RBC_MULT RBC_DIV RBC_MOD RBC_POW RBC_UMINUS RBC_MULTP RBC_ADDP RBC_SUBTRACTP RBC_SIN RBC_COS RBC_ATAN2 RBC_SQRT RBC_DISTANCE RBC_GETP1 RBC_GETP2 RBC_GETP3 RBC_VALUE RBC_HUE RBC_SAT RBC_HSV RBC_RED RBC_GREEN RBC_BLUE RBC_RGB RBC_INT RBC_IF RBC_IFP RBC_LE RBC_LT RBC_GE RBC_GT RBC_EQ RBC_NE RBC_AND RBC_OR RBC_NOT RBC_ABS RBC_RET RBC_JUMP RBC_JUMPZ RBC_JUMPNZ RBC_SET RBC_SETP RBC_PRINT RBC_OP_COUNT);
+@EXPORT = qw(RBC_ADD RBC_SUBTRACT RBC_MULT RBC_DIV RBC_MOD RBC_POW RBC_UMINUS RBC_MULTP RBC_ADDP RBC_SUBTRACTP RBC_SIN RBC_COS RBC_ATAN2 RBC_SQRT RBC_DISTANCE RBC_GETP1 RBC_GETP2 RBC_GETP3 RBC_VALUE RBC_HUE RBC_SAT RBC_HSV RBC_RED RBC_GREEN RBC_BLUE RBC_RGB RBC_INT RBC_IF RBC_IFP RBC_LE RBC_LT RBC_GE RBC_GT RBC_EQ RBC_NE RBC_AND RBC_OR RBC_NOT RBC_ABS RBC_RET RBC_JUMP RBC_JUMPZ RBC_JUMPNZ RBC_SET RBC_SETP RBC_PRINT RBC_RGBA RBC_HSVA RBC_ALPHA RBC_OP_COUNT);
 
 %Attr = (
 
 %Attr = (
-          'or' => {
-                    'opcode' => 36,
-                    'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
-                  },
-          'getp1' => {
-                       'opcode' => 15,
-                       'parms' => 2,
-                       'func' => 1,
-                       'types' => 'rr',
-                       'result' => 'p'
-                     },
-          'uminus' => {
-                        'opcode' => 6,
-                        'parms' => 1,
-                        'func' => '0',
-                        'types' => 'r',
-                        'result' => 'r'
-                      },
-          'getp2' => {
-                       'opcode' => 16,
-                       'parms' => 2,
-                       'func' => 1,
-                       'types' => 'rr',
-                       'result' => 'p'
-                     },
-          'getp3' => {
-                       'opcode' => 17,
-                       'parms' => 2,
-                       'func' => 1,
-                       'types' => 'rr',
-                       'result' => 'p'
-                     },
-          'jumpnz' => {
-                        'opcode' => 42,
-                        'parms' => 1,
-                        'func' => '0',
-                        'types' => 'r',
-                        'result' => undef
-                      },
-          'op_count' => {
-                          'opcode' => 46,
-                          'parms' => '0',
-                          'func' => '0',
-                          'types' => '',
-                          'result' => undef
-                        },
-          'blue' => {
-                      'opcode' => 24,
+          'setp' => {
+                      'result' => 'p',
                       'parms' => 1,
                       'parms' => 1,
-                      'func' => 1,
-                      'types' => 'p',
-                      'result' => 'r'
+                      'opcode' => 44,
+                      'func' => 0,
+                      'types' => 'p'
                     },
                     },
-          'int' => {
-                     'opcode' => 26,
+          'green' => {
+                       'result' => 'r',
+                       'parms' => 1,
+                       'opcode' => 23,
+                       'func' => 1,
+                       'types' => 'p'
+                     },
+          'abs' => {
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
+                     'opcode' => 38,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'r',
-                     'result' => 'r'
+                     'types' => 'r'
                    },
           'le' => {
                    },
           'le' => {
-                    'opcode' => 29,
+                    'result' => 'r',
                     'parms' => 2,
                     'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
+                    'opcode' => 29,
+                    'func' => 0,
+                    'types' => 'rr'
                   },
                   },
-          'multp' => {
-                       'opcode' => 7,
-                       'parms' => 2,
-                       'func' => '0',
-                       'types' => 'pr',
-                       'result' => 'p'
-                     },
+          'cos' => {
+                     'result' => 'r',
+                     'parms' => 1,
+                     'opcode' => 11,
+                     'func' => 1,
+                     'types' => 'r'
+                   },
+          'not' => {
+                     'result' => 'r',
+                     'parms' => 1,
+                     'opcode' => 37,
+                     'func' => 0,
+                     'types' => 'r'
+                   },
           'ne' => {
           'ne' => {
+                    'result' => 'r',
+                    'parms' => 2,
                     'opcode' => 34,
                     'opcode' => 34,
+                    'func' => 0,
+                    'types' => 'rr'
+                  },
+          'blue' => {
+                      'result' => 'r',
+                      'parms' => 1,
+                      'opcode' => 24,
+                      'func' => 1,
+                      'types' => 'p'
+                    },
+          'and' => {
+                     'result' => 'r',
+                     'parms' => 2,
+                     'opcode' => 35,
+                     'func' => 0,
+                     'types' => 'rr'
+                   },
+          'mult' => {
+                      'result' => 'r',
+                      'parms' => 2,
+                      'opcode' => 2,
+                      'func' => 0,
+                      'types' => 'rr'
+                    },
+          'rgba' => {
+                      'result' => 'p',
+                      'parms' => 4,
+                      'opcode' => 46,
+                      'func' => 1,
+                      'types' => 'rrrr'
+                    },
+          'pow' => {
+                     'result' => 'r',
+                     'parms' => 2,
+                     'opcode' => 5,
+                     'func' => 0,
+                     'types' => 'rr'
+                   },
+          'lt' => {
+                    'result' => 'r',
                     'parms' => 2,
                     'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
+                    'opcode' => 30,
+                    'func' => 0,
+                    'types' => 'rr'
                   },
                   },
-          'jumpz' => {
-                       'opcode' => 41,
-                       'parms' => 1,
-                       'func' => '0',
-                       'types' => 'r',
-                       'result' => undef
+          'mod' => {
+                     'result' => 'r',
+                     'parms' => 2,
+                     'opcode' => 4,
+                     'func' => 0,
+                     'types' => 'rr'
+                   },
+          'getp1' => {
+                       'result' => 'p',
+                       'parms' => 2,
+                       'opcode' => 15,
+                       'func' => 1,
+                       'types' => 'rr'
                      },
           'atan2' => {
                      },
           'atan2' => {
+                       'result' => 'r',
+                       'parms' => 2,
                        'opcode' => 12,
                        'opcode' => 12,
+                       'func' => 1,
+                       'types' => 'rr'
+                     },
+          'getp2' => {
+                       'result' => 'p',
+                       'parms' => 2,
+                       'opcode' => 16,
+                       'func' => 1,
+                       'types' => 'rr'
+                     },
+          'getp3' => {
+                       'result' => 'p',
                        'parms' => 2,
                        'parms' => 2,
+                       'opcode' => 17,
+                       'func' => 1,
+                       'types' => 'rr'
+                     },
+          'value' => {
+                       'result' => 'r',
+                       'parms' => 1,
+                       'opcode' => 18,
                        'func' => 1,
                        'func' => 1,
-                       'types' => 'rr',
-                       'result' => 'r'
+                       'types' => 'p'
                      },
           'subtractp' => {
                      },
           'subtractp' => {
-                           'opcode' => 9,
+                           'result' => 'p',
                            'parms' => 2,
                            'parms' => 2,
-                           'func' => '0',
-                           'types' => 'pp',
-                           'result' => 'p'
+                           'opcode' => 9,
+                           'func' => 0,
+                           'types' => 'pp'
                          },
                          },
-          'rgb' => {
-                     'opcode' => 25,
-                     'parms' => 3,
-                     'func' => 1,
-                     'types' => 'rrr',
-                     'result' => 'p'
-                   },
-          'red' => {
-                     'opcode' => 22,
+          'ge' => {
+                    'result' => 'r',
+                    'parms' => 2,
+                    'opcode' => 31,
+                    'func' => 0,
+                    'types' => 'rr'
+                  },
+          'sat' => {
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
+                     'opcode' => 20,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'p',
-                     'result' => 'r'
+                     'types' => 'p'
                    },
                    },
-          'setp' => {
-                      'opcode' => 44,
-                      'parms' => 1,
-                      'func' => '0',
-                      'types' => 'p',
-                      'result' => 'p'
-                    },
           'jump' => {
           'jump' => {
+                      'result' => undef,
+                      'parms' => 0,
                       'opcode' => 40,
                       'opcode' => 40,
-                      'parms' => '0',
-                      'func' => '0',
-                      'types' => '',
-                      'result' => undef
+                      'func' => 0,
+                      'types' => ''
                     },
                     },
-          'value' => {
-                       'opcode' => 18,
-                       'parms' => 1,
-                       'func' => 1,
-                       'types' => 'p',
-                       'result' => 'r'
-                     },
-          'mod' => {
-                     'opcode' => 4,
-                     'parms' => 2,
-                     'func' => '0',
-                     'types' => 'rr',
-                     'result' => 'r'
-                   },
-          'lt' => {
-                    'opcode' => 30,
-                    'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
+          'if' => {
+                    'result' => 'r',
+                    'parms' => 3,
+                    'opcode' => 27,
+                    'func' => 1,
+                    'types' => 'rrr'
                   },
                   },
-          'mult' => {
-                      'opcode' => 2,
-                      'parms' => 2,
-                      'func' => '0',
-                      'types' => 'rr',
-                      'result' => 'r'
-                    },
-          'hue' => {
-                     'opcode' => 19,
-                     'parms' => 1,
-                     'func' => 1,
-                     'types' => 'p',
-                     'result' => 'r'
-                   },
           'div' => {
           'div' => {
-                     'opcode' => 3,
+                     'result' => 'r',
                      'parms' => 2,
                      'parms' => 2,
-                     'func' => '0',
-                     'types' => 'rr',
-                     'result' => 'r'
+                     'opcode' => 3,
+                     'func' => 0,
+                     'types' => 'rr'
                    },
                    },
-          'cos' => {
-                     'opcode' => 11,
-                     'parms' => 1,
+          'ifp' => {
+                     'result' => 'p',
+                     'parms' => 3,
+                     'opcode' => 28,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'r',
-                     'result' => 'r'
+                     'types' => 'rpp'
                    },
                    },
-          'subtract' => {
-                          'opcode' => 1,
-                          'parms' => 2,
-                          'func' => '0',
-                          'types' => 'rr',
-                          'result' => 'r'
-                        },
-          'sat' => {
-                     'opcode' => 20,
+          'set' => {
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
-                     'func' => 1,
-                     'types' => 'p',
-                     'result' => 'r'
-                   },
-          'add' => {
-                     'opcode' => '0',
-                     'parms' => 2,
-                     'func' => '0',
-                     'types' => 'rr',
-                     'result' => 'r'
+                     'opcode' => 43,
+                     'func' => 0,
+                     'types' => 'r'
                    },
                    },
+          'eq' => {
+                    'result' => 'r',
+                    'parms' => 2,
+                    'opcode' => 33,
+                    'func' => 0,
+                    'types' => 'rr'
+                  },
+          'multp' => {
+                       'result' => 'p',
+                       'parms' => 2,
+                       'opcode' => 7,
+                       'func' => 0,
+                       'types' => 'pr'
+                     },
           'sin' => {
           'sin' => {
-                     'opcode' => 10,
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
+                     'opcode' => 10,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'r',
-                     'result' => 'r'
+                     'types' => 'r'
                    },
           'sqrt' => {
                    },
           'sqrt' => {
-                      'opcode' => 13,
+                      'result' => 'r',
                       'parms' => 1,
                       'parms' => 1,
+                      'opcode' => 13,
                       'func' => 1,
                       'func' => 1,
-                      'types' => 'r',
-                      'result' => 'r'
+                      'types' => 'r'
                     },
                     },
-          'ret' => {
-                     'opcode' => 39,
-                     'parms' => 1,
-                     'func' => '0',
-                     'types' => 'p',
-                     'result' => undef
-                   },
+          'alpha' => {
+                       'result' => 'r',
+                       'parms' => 1,
+                       'opcode' => 48,
+                       'func' => 1,
+                       'types' => 'p'
+                     },
           'distance' => {
           'distance' => {
-                          'opcode' => 14,
+                          'result' => 'r',
                           'parms' => 4,
                           'parms' => 4,
+                          'opcode' => 14,
                           'func' => 1,
                           'func' => 1,
-                          'types' => 'rrrr',
-                          'result' => 'r'
+                          'types' => 'rrrr'
                         },
                         },
-          'set' => {
-                     'opcode' => 43,
-                     'parms' => 1,
-                     'func' => '0',
-                     'types' => 'r',
-                     'result' => 'r'
-                   },
-          'ge' => {
-                    'opcode' => 31,
+          'gt' => {
+                    'result' => 'r',
                     'parms' => 2,
                     'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
-                  },
-          'print' => {
-                       'opcode' => 45,
-                       'parms' => 1,
-                       'func' => '0',
-                       'types' => 'r',
-                       'result' => undef
-                     },
-          'if' => {
-                    'opcode' => 27,
-                    'parms' => 3,
-                    'func' => 1,
-                    'types' => 'rrr',
-                    'result' => 'r'
+                    'opcode' => 32,
+                    'func' => 0,
+                    'types' => 'rr'
                   },
                   },
-          'not' => {
-                     'opcode' => 37,
+          'red' => {
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
-                     'func' => '0',
-                     'types' => 'r',
-                     'result' => 'r'
+                     'opcode' => 22,
+                     'func' => 1,
+                     'types' => 'p'
                    },
                    },
-          'hsv' => {
-                     'opcode' => 21,
+          'rgb' => {
+                     'result' => 'p',
                      'parms' => 3,
                      'parms' => 3,
+                     'opcode' => 25,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'rrr',
-                     'result' => 'p'
+                     'types' => 'rrr'
                    },
                    },
-          'green' => {
-                       'opcode' => 23,
+          'hue' => {
+                     'result' => 'r',
+                     'parms' => 1,
+                     'opcode' => 19,
+                     'func' => 1,
+                     'types' => 'p'
+                   },
+          'hsva' => {
+                      'result' => 'p',
+                      'parms' => 4,
+                      'opcode' => 47,
+                      'func' => 1,
+                      'types' => 'rrrr'
+                    },
+          'print' => {
+                       'result' => undef,
                        'parms' => 1,
                        'parms' => 1,
-                       'func' => 1,
-                       'types' => 'p',
-                       'result' => 'r'
+                       'opcode' => 45,
+                       'func' => 0,
+                       'types' => 'r'
                      },
                      },
-          'and' => {
-                     'opcode' => 35,
-                     'parms' => 2,
-                     'func' => '0',
-                     'types' => 'rr',
-                     'result' => 'r'
-                   },
-          'abs' => {
-                     'opcode' => 38,
+          'jumpnz' => {
+                        'result' => undef,
+                        'parms' => 1,
+                        'opcode' => 42,
+                        'func' => 0,
+                        'types' => 'r'
+                      },
+          'addp' => {
+                      'result' => 'p',
+                      'parms' => 2,
+                      'opcode' => 8,
+                      'func' => 0,
+                      'types' => 'pp'
+                    },
+          'int' => {
+                     'result' => 'r',
                      'parms' => 1,
                      'parms' => 1,
+                     'opcode' => 26,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'r',
-                     'result' => 'r'
+                     'types' => 'r'
                    },
                    },
-          'eq' => {
-                    'opcode' => 33,
+          'op_count' => {
+                          'result' => undef,
+                          'parms' => 0,
+                          'opcode' => 49,
+                          'func' => 0,
+                          'types' => ''
+                        },
+          'or' => {
+                    'result' => 'r',
                     'parms' => 2,
                     'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
+                    'opcode' => 36,
+                    'func' => 0,
+                    'types' => 'rr'
                   },
                   },
-          'pow' => {
-                     'opcode' => 5,
+          'jumpz' => {
+                       'result' => undef,
+                       'parms' => 1,
+                       'opcode' => 41,
+                       'func' => 0,
+                       'types' => 'r'
+                     },
+          'add' => {
+                     'result' => 'r',
                      'parms' => 2,
                      'parms' => 2,
-                     'func' => '0',
-                     'types' => 'rr',
-                     'result' => 'r'
+                     'opcode' => 0,
+                     'func' => 0,
+                     'types' => 'rr'
                    },
                    },
-          'addp' => {
-                      'opcode' => 8,
-                      'parms' => 2,
-                      'func' => '0',
-                      'types' => 'pp',
-                      'result' => 'p'
-                    },
-          'gt' => {
-                    'opcode' => 32,
-                    'parms' => 2,
-                    'func' => '0',
-                    'types' => 'rr',
-                    'result' => 'r'
-                  },
-          'ifp' => {
-                     'opcode' => 28,
+          'subtract' => {
+                          'result' => 'r',
+                          'parms' => 2,
+                          'opcode' => 1,
+                          'func' => 0,
+                          'types' => 'rr'
+                        },
+          'ret' => {
+                     'result' => undef,
+                     'parms' => 1,
+                     'opcode' => 39,
+                     'func' => 0,
+                     'types' => 'p'
+                   },
+          'hsv' => {
+                     'result' => 'p',
                      'parms' => 3,
                      'parms' => 3,
+                     'opcode' => 21,
                      'func' => 1,
                      'func' => 1,
-                     'types' => 'rpp',
-                     'result' => 'p'
-                   }
+                     'types' => 'rrr'
+                   },
+          'uminus' => {
+                        'result' => 'r',
+                        'parms' => 1,
+                        'opcode' => 6,
+                        'func' => 0,
+                        'types' => 'r'
+                      }
         );
 $MaxOperands = 4;
 $PackCode = "i";
         );
 $MaxOperands = 4;
 $PackCode = "i";
index 694ed2d9c44d22ab6305993202fff4fd58a4ca72..cea9a791fdaebf683e472d839c45c19c0410e9f1 100644 (file)
--- a/regmach.c
+++ b/regmach.c
@@ -66,7 +66,7 @@ static double hsv_sat(i_color color) {
   }
 }
 
   }
 }
 
-static i_color make_hsv(double hue, double sat, double val) {
+static i_color make_hsv(double hue, double sat, double val, int alpha) {
   int i;
   i_color c;
   for( i=0; i< MAXCHANNELS; i++) c.channel[i]=0;
   int i;
   i_color c;
   for( i=0; i< MAXCHANNELS; i++) c.channel[i]=0;
@@ -119,11 +119,12 @@ static i_color make_hsv(double hue, double sat, double val) {
       break;
     }
   }
       break;
     }
   }
+  c.rgba.a = alpha;
 
   return c;
 }
 
 
   return c;
 }
 
-static i_color make_rgb(int r, int g, int b) {
+static i_color make_rgb(int r, int g, int b, int a) {
   i_color c;
   if (r < 0)
     r = 0;
   i_color c;
   if (r < 0)
     r = 0;
@@ -141,6 +142,8 @@ static i_color make_rgb(int r, int g, int b) {
     b = 255;
   c.rgb.b = b;
 
     b = 255;
   c.rgb.b = b;
 
+  c.rgba.a = a;
+
   return c;
 }
 
   return c;
 }
 
@@ -210,17 +213,17 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count,
       nout = -na;
 
     case rbc_multp:
       nout = -na;
 
     case rbc_multp:
-      cout = make_rgb(ca.rgb.r * nb, ca.rgb.g * nb, ca.rgb.b * nb);
+      cout = make_rgb(ca.rgb.r * nb, ca.rgb.g * nb, ca.rgb.b * nb, 255);
       break;
 
     case rbc_addp:
       cout = make_rgb(ca.rgb.r + cb.rgb.r, ca.rgb.g + cb.rgb.g, 
       break;
 
     case rbc_addp:
       cout = make_rgb(ca.rgb.r + cb.rgb.r, ca.rgb.g + cb.rgb.g, 
-                     ca.rgb.b + cb.rgb.b);
+                     ca.rgb.b + cb.rgb.b, 255);
       break;
 
     case rbc_subtractp:
       cout = make_rgb(ca.rgb.r - cb.rgb.r, ca.rgb.g - cb.rgb.g, 
       break;
 
     case rbc_subtractp:
       cout = make_rgb(ca.rgb.r - cb.rgb.r, ca.rgb.g - cb.rgb.g, 
-                     ca.rgb.b - cb.rgb.b);
+                     ca.rgb.b - cb.rgb.b, 255);
       break;
 
     case rbc_sin:
       break;
 
     case rbc_sin:
@@ -270,7 +273,11 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count,
       break;
       
     case rbc_hsv:
       break;
       
     case rbc_hsv:
-      cout = make_hsv(na, nb, nc);
+      cout = make_hsv(na, nb, nc, 255);
+      break;
+
+    case rbc_hsva:
+      cout = make_hsv(na, nb, nc, nd);
       break;
 
     case rbc_red:
       break;
 
     case rbc_red:
@@ -285,8 +292,16 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count,
       nout = ca.rgb.b;
       break;
 
       nout = ca.rgb.b;
       break;
 
+    case rbc_alpha:
+      nout = ca.rgba.a;
+      break;
+
     case rbc_rgb:
     case rbc_rgb:
-      cout = make_rgb(na, nb, nc);
+      cout = make_rgb(na, nb, nc, 255);
+      break;
+
+    case rbc_rgba:
+      cout = make_rgb(na, nb, nc, nd);
       break;
 
     case rbc_int:
       break;
 
     case rbc_int:
index 083dad53b783c37333ccb0d30d2d7dbba8ea0c1f..79b8fda2713d08538c2c30c1617e6f90644365ff 100644 (file)
--- a/regmach.h
+++ b/regmach.h
@@ -54,6 +54,9 @@ enum rm_byte_codes {
   rbc_set, /* ra -> r */
   rbc_setp, /* pa -> p*/
   rbc_print, /* prints ra */
   rbc_set, /* ra -> r */
   rbc_setp, /* pa -> p*/
   rbc_print, /* prints ra */
+  rbc_rgba, /* rgba(ra, rb, rc, rd) -> p */
+  rbc_hsva, /* hsva(ra, rb, rc, rd) -> p */
+  rbc_alpha, /* alpha(pa) -> r */
   rbc_op_count
 };
 
   rbc_op_count
 };
 
index 4ef18a336d82bad9e732c84a393d68ce569b6103..d1379cef0d51997908eb466643cccd65a390e642 100644 (file)
@@ -7,7 +7,11 @@ print "ok 1\n";
 
 #$Imager::DEBUG=1;
 
 
 #$Imager::DEBUG=1;
 
-my $expr = Imager::Expr->new({rpnexpr=>'x two * y one + getp1', variables=>[ qw(x y) ], constants=>{one=>1, two=>2}});
+my $expr = Imager::Expr->new({rpnexpr=><<EXPR, variables=>[ qw(x y) ], constants=>{one=>1, two=>2}});
+x two * # see if comments work
+y one + 
+getp1
+EXPR
 if ($expr) {
   print "ok 2\n";
 
 if ($expr) {
   print "ok 2\n";
 
index bf92dba8d60a31fffe33ba3368fec4b6db4ac5e3..163570d221fccdad1f24b10dc2880f19e9e24147 100644 (file)
@@ -1,11 +1,14 @@
-BEGIN { $| = 1; print "1..12\n"; }
+#!perl -w
+BEGIN { $| = 1; print "1..15\n"; }
 END {print "not ok 1\n" unless $loaded;}
 use Imager;
 
 END {print "not ok 1\n" unless $loaded;}
 use Imager;
 
-sub ok($$$);
+sub ok($$);
+sub is($$$);
+my $num = 1;
 
 $loaded = 1;
 
 $loaded = 1;
-print "ok 1\n";
+ok(1, "loaded");
 
 #$Imager::DEBUG=1;
 
 
 #$Imager::DEBUG=1;
 
@@ -21,14 +24,14 @@ $im2->open(file=>'testimg/scale.ppm',type=>'pnm')
 # error handling
 my $opts = { rpnexpr=>'x x 10 / sin 10 * y + get1' };
 my $im3 = Imager::transform2($opts);
 # error handling
 my $opts = { rpnexpr=>'x x 10 / sin 10 * y + get1' };
 my $im3 = Imager::transform2($opts);
-ok(2, !$im3, "returned an image on error");
-ok(3, defined($Imager::ERRSTR), "No error message on failure");
+ok(!$im3, "returned an image on error");
+ok(defined($Imager::ERRSTR), "No error message on failure");
 
 # image synthesis
 my $im4 = Imager::transform2({
        width=>300, height=>300,
        rpnexpr=>'x y cx cy distance !d y cy - x cx - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 cy * 3.1416 / 1 @a2 sin 1 + 2 / hsv'});
 
 # image synthesis
 my $im4 = Imager::transform2({
        width=>300, height=>300,
        rpnexpr=>'x y cx cy distance !d y cy - x cx - atan2 !a @d 10 / @a + 3.1416 2 * % !a2 @a2 cy * 3.1416 / 1 @a2 sin 1 + 2 / hsv'});
-ok(4, $im4, "synthesis failed");
+ok($im4, "synthesis failed");
 
 if ($im4) {
   $im4->write(type=>'pnm', file=>'testout/t56a.ppm')
 
 if ($im4) {
   $im4->write(type=>'pnm', file=>'testout/t56a.ppm')
@@ -39,7 +42,7 @@ if ($im4) {
 my $im5 = Imager::transform2({
        rpnexpr=>'x x 10 / sin 10 * y + getp1'
 }, $im1);
 my $im5 = Imager::transform2({
        rpnexpr=>'x x 10 / sin 10 * y + getp1'
 }, $im1);
-ok(5, $im5, "image distortion");
+ok($im5, "image distortion");
 if ($im5) {
   $im5->write(type=>'pnm', file=>'testout/t56b.ppm')
     || die "Cannot write testout/t56b.ppm";
 if ($im5) {
   $im5->write(type=>'pnm', file=>'testout/t56b.ppm')
     || die "Cannot write testout/t56b.ppm";
@@ -50,46 +53,76 @@ $opts = {
 rpnexpr=>'x h / !rat x w2 % y h2 % getp2 !pat x y getp1 @rat * @pat 1 @rat - * +'
 };
 my $im6 = Imager::transform2($opts,$im1,$im2);
 rpnexpr=>'x h / !rat x w2 % y h2 % getp2 !pat x y getp1 @rat * @pat 1 @rat - * +'
 };
 my $im6 = Imager::transform2($opts,$im1,$im2);
-ok(6, $im6, "image combination");
+ok($im6, "image combination");
 if ($im6) {
   $im6->write(type=>'pnm', file=>'testout/t56c.ppm')
     || die "Cannot write testout/t56c.ppm";
 }
 
 if ($im6) {
   $im6->write(type=>'pnm', file=>'testout/t56c.ppm')
     || die "Cannot write testout/t56c.ppm";
 }
 
+# alpha
+$opts = 
+  {
+   rpnexpr => '0 0 255 x y + w h + 2 - / 255 * rgba',
+   channels => 4,
+   width => 50,
+   height => 50,
+  };
+my $im8 = Imager::transform2($opts);
+ok($im8, "alpha output");
+my $c = $im8->getpixel(x=>0, 'y'=>0);
+is(($c->rgba)[3], 0, "zero alpha");
+$c = $im8->getpixel(x=>49, 'y'=>49);
+is(($c->rgba)[3], 255, "max alpha");
+
 use Imager::Transform;
 
 # some simple tests
 use Imager::Transform;
 
 # some simple tests
-my @funcs = Imager::Transform->list or print "not ";
-print "ok 7\n";
-my $tran = Imager::Transform->new($funcs[0]) or print "not ";
-print "ok 8\n";
-$tran->describe() eq Imager::Transform->describe($funcs[0]) or print "not ";
-print "ok 9\n";
+print "# Imager::Transform\n";
+my @funcs = Imager::Transform->list;
+ok(@funcs, "funcs");
+
+my $tran = Imager::Transform->new($funcs[0]);
+ok($tran, "got tranform");
+ok($tran->describe() eq Imager::Transform->describe($funcs[0]),
+   "description");
 # look for a function that takes inputs (at least one does)
 my @needsinputs = grep Imager::Transform->new($_)->inputs, @funcs;
 # make sure they're 
 my @inputs = Imager::Transform->new($needsinputs[0])->inputs;
 # look for a function that takes inputs (at least one does)
 my @needsinputs = grep Imager::Transform->new($_)->inputs, @funcs;
 # make sure they're 
 my @inputs = Imager::Transform->new($needsinputs[0])->inputs;
-$inputs[0]{desc} or print "not ";
-print "ok 10\n";
+ok($inputs[0]{desc}, "input description");
 # at some point I might want to test the actual transformations
 
 # check lower level error handling
 my $im7 = Imager::transform2({rpnexpr=>'x y getp2', width=>100, height=>100});
 # at some point I might want to test the actual transformations
 
 # check lower level error handling
 my $im7 = Imager::transform2({rpnexpr=>'x y getp2', width=>100, height=>100});
-ok(11, !$im7, "expected failure on accessing invalid image");
+ok(!$im7, "expected failure on accessing invalid image");
 print "# ", Imager->errstr, "\n";
 print "# ", Imager->errstr, "\n";
-ok(12, Imager->errstr =~ /not enough images/, "didn't get expected error");
-
+ok(Imager->errstr =~ /not enough images/, "didn't get expected error");
 
 
 
 
-sub ok ($$$) {
-  my ($num, $test, $desc) = @_;
+sub ok ($$) {
+  my ($test, $desc) = @_;
 
   if ($test) {
 
   if ($test) {
-    print "ok $num\n";
+    print "ok $num # $desc\n";
   }
   else {
     print "not ok $num # $desc\n";
   }
   }
   else {
     print "not ok $num # $desc\n";
   }
+  ++$num;
   $test;
 }
 
   $test;
 }
 
+sub is ($$$) {
+  my ($left, $right, $desc) = @_;
+
+  my $eq = $left == $right;
+  unless (ok($eq, $desc)) {
+    $left =~ s/\n/# \n/g;
+    $left =~ s/([^\n\x20-\x7E])/"\\x".sprintf("%02X", ord $1)/ge;
+    $right =~ s/\n/# \n/g;
+    $right =~ s/([^\n\x20-\x7E])/"\\x".sprintf("%02X", ord $1)/ge;
+    print "# not equal, left = '$left'\n";
+    print "# right = '$right'\n";
+  }
+  $eq;
+}
diff --git a/typemap b/typemap
index 7e36a8cecd1bd5ea00a83b247468c59120443b5e..abcf4de9233f0550d5bc5a7ed6709d1d021970bb 100644 (file)
--- a/typemap
+++ b/typemap
@@ -17,6 +17,14 @@ INPUT
 T_PTR_NULL
        if (SvOK($arg)) $var = INT2PTR($type,SvIV($arg));
        else $var = NULL
 T_PTR_NULL
        if (SvOK($arg)) $var = INT2PTR($type,SvIV($arg));
        else $var = NULL
+
+# the pre-5.8.0 T_AVREF input map was fixed in 5.8.0
+T_AVREF
+        if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV)
+            $var = (AV*)SvRV($arg);
+        else
+            Perl_croak(aTHX_ \"$var is not an array reference\")
+
 #############################################################################
 OUTPUT
 T_IV_U
 #############################################################################
 OUTPUT
 T_IV_U