From 71dc4a8349379692cae40b2f7e1152544a2ff2ef Mon Sep 17 00:00:00 2001 From: Arnar Mar Hrafnkelsson Date: Sat, 29 Mar 2003 12:24:05 +0000 Subject: [PATCH] Added extra parameters to rubthrough so only a subimage of the source image is copied. --- Changes | 3 ++- Imager.pm | 11 ++++++++-- Imager.xs | 7 +++++- MANIFEST | 1 + image.c | 40 ++++++++++++++++++---------------- image.h | 3 ++- lib/Imager/Transformations.pod | 22 +++++++++++++------ t/t69rubthru.t | 19 +++++++++------- 8 files changed, 67 insertions(+), 39 deletions(-) diff --git a/Changes b/Changes index b93f9df9..ef63b773 100644 --- a/Changes +++ b/Changes @@ -716,7 +716,8 @@ Revision history for Perl extension Imager. instead. - some older FT1 don't define TT_MS_LANGID_ENGLISH_GENERAL, which we use, define it if freetype doesn't. - + - Added extra options to rubthrough() so only a subpart of + source image is used. ================================================================= For latest versions check the Imager-devel pages: diff --git a/Imager.pm b/Imager.pm index 6d282dff..9ddd35c0 100644 --- a/Imager.pm +++ b/Imager.pm @@ -1737,12 +1737,19 @@ sub transform2 { sub rubthrough { my $self=shift; - my %opts=(tx=>0,ty=>0,@_); + my %opts=(tx => 0,ty => 0, @_); unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; } unless ($opts{src} && $opts{src}->{IMG}) { $self->{ERRSTR}='empty input image for source'; return undef; } - unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx},$opts{ty})) { + %opts = (src_minx => 0, + src_miny => 0, + src_maxx => $opts{src}->getwidth(), + src_maxy => $opts{src}->getheight(), + %opts); + + unless (i_rubthru($self->{IMG}, $opts{src}->{IMG}, $opts{tx}, $opts{ty}, + $opts{src_minx}, $opts{src_miny}, $opts{src_maxx}, $opts{src_maxy})) { $self->{ERRSTR} = $self->_error_as_msg(); return undef; } diff --git a/Imager.xs b/Imager.xs index a6fb5125..5e79c193 100644 --- a/Imager.xs +++ b/Imager.xs @@ -1478,11 +1478,16 @@ i_copy(im,src) undef_int -i_rubthru(im,src,tx,ty) +i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy) Imager::ImgRaw im Imager::ImgRaw src int tx int ty + int src_minx + int src_miny + int src_maxx + int src_maxy + undef_int i_flipxy(im, direction) diff --git a/MANIFEST b/MANIFEST index ac14cf11..d4cbfc21 100644 --- a/MANIFEST +++ b/MANIFEST @@ -77,6 +77,7 @@ lib/Imager/Font/Truetype.pm lib/Imager/Font/FreeType2.pm lib/Imager/Font/Win32.pm lib/Imager/Font/Wrap.pm +lib/Imager/Font/Image.pm lib/Imager/Fountain.pm lib/Imager/interface.pod lib/Imager/Matrix2d.pm diff --git a/image.c b/image.c index 0b568a0a..9de1e092 100644 --- a/image.c +++ b/image.c @@ -649,9 +649,10 @@ i_copy(i_img *im, i_img *src) { /* -=item i_rubthru(im, src, tx, ty) +=item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy ) -Takes the image I and applies it at an original (I,I) in I. +Takes the sub image I and +overlays it at (I,I) on the image object. The alpha channel of each pixel in I is used to control how much the existing colour in I is replaced, if it is 255 then the colour @@ -662,14 +663,17 @@ unmodified. */ int -i_rubthru(i_img *im,i_img *src,int tx,int ty) { +i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, + int src_maxx, int src_maxy) { int x, y, ttx, tty; int chancount; int chans[3]; int alphachan; int ch; - mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d)\n", im, src, tx, ty)); + mm_log((1,"i_rubthru(im %p, src %p, tx %d, ty %d, src_minx %d, " + "src_miny %d, src_maxx %d, src_maxy %d)\n", + im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy)); i_clear_error(); if (im->channels == 3 && src->channels == 4) { @@ -697,11 +701,10 @@ i_rubthru(i_img *im,i_img *src,int tx,int ty) { changed in a similar fashion - TC */ int alpha; i_color pv, orig, dest; - ttx = tx; - for(x=0; xxsize; x++) { - tty=ty; - for(y=0;yysize;y++) { - /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */ + tty = ty; + for(y = src_miny; y < src_maxy; y++) { + ttx = tx; + for(x = src_minx; x < src_maxx; x++) { i_gpix(src, x, y, &pv); i_gpix(im, ttx, tty, &orig); alpha = pv.channel[alphachan]; @@ -710,31 +713,30 @@ i_rubthru(i_img *im,i_img *src,int tx,int ty) { + (255 - alpha) * orig.channel[ch])/255; } i_ppix(im, ttx, tty, &dest); - tty++; + ttx++; } - ttx++; + tty++; } } else { double alpha; i_fcolor pv, orig, dest; - ttx = tx; - for(x=0; xxsize; x++) { - tty=ty; - for(y=0;yysize;y++) { - /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */ + tty = ty; + for(y = src_miny; y < src_maxy; y++) { + ttx = tx; + for(x = src_minx; x < src_maxx; x++) { i_gpixf(src, x, y, &pv); i_gpixf(im, ttx, tty, &orig); alpha = pv.channel[alphachan]; for (ch = 0; ch < chancount; ++ch) { dest.channel[ch] = alpha * pv.channel[chans[ch]] - + (1 - alpha) * orig.channel[ch]; + + (1 - alpha) * orig.channel[ch]; } i_ppixf(im, ttx, tty, &dest); - tty++; + ttx++; } - ttx++; + tty++; } } diff --git a/image.h b/image.h index 1acd9f83..e90d30f0 100644 --- a/image.h +++ b/image.h @@ -211,7 +211,8 @@ void i_circle_aa (i_img *im,float x, float y,float rad,i_color *val); void i_copyto (i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty); void i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans); void i_copy (i_img *im,i_img *src); -int i_rubthru (i_img *im,i_img *src,int tx,int ty); +int i_rubthru (i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy); + undef_int i_flipxy (i_img *im, int direction); extern i_img *i_rotate90(i_img *im, int degrees); diff --git a/lib/Imager/Transformations.pod b/lib/Imager/Transformations.pod index f790fa79..46ccaeb3 100644 --- a/lib/Imager/Transformations.pod +++ b/lib/Imager/Transformations.pod @@ -18,7 +18,10 @@ Imager::Transformations - Simple transformations of one image into another. $dest->paste(left=>40,top=>20,img=>$logo); - $img->rubthrough(src=>$srcimage,tx=>30,ty=>50); + $img->rubthrough(src=>$srcimage,tx=>30, ty=>50); + $img->rubthrough(src=>$srcimage,tx=>30, ty=>50, + src_minx=>20, src_miny=>30, + src_maxx=>20, src_maxy=>30); $img->flip(dir=>"h"); # horizontal flip @@ -167,12 +170,17 @@ A more complicated way of blending images is where one image is put 'over' the other with a certain amount of opaqueness. The method that does this is rubthrough. - $img->rubthrough(src=>$srcimage,tx=>30,ty=>50); - -That will take the image C<$srcimage> and overlay it with the upper -left corner at (30,50). You can rub 2 or 4 channel images onto a 3 -channel image, or a 2 channel image onto a 1 channel image. The last -channel is used as an alpha channel. + $img->rubthrough(src=>$overlay, + tx=>30, ty=>50, + src_minx=>20, src_miny=>30, + src_maxx=>20, src_maxy=>30); + +That will take the sub image defined by I<$overlay> and +I<[src_minx,src_maxx)[src_miny,src_maxy)> and overlay it on top of +I<$img> with the upper left corner at (30,50). You can rub 2 or 4 +channel images onto a 3 channel image, or a 2 channel image onto a 1 +channel image. The last channel is used as an alpha channel. To add +an alpha channel to an image see I. =item flip diff --git a/t/t69rubthru.t b/t/t69rubthru.t index 7c62a774..3b37b3e4 100644 --- a/t/t69rubthru.t +++ b/t/t69rubthru.t @@ -7,12 +7,15 @@ $loaded = 1; print "ok 1\n"; init_log("testout/t69rubthru.log", 1); +my $src_height = 80; +my $src_width = 80; + # raw interface my $targ = Imager::ImgRaw::new(100, 100, 3); -my $src = Imager::ImgRaw::new(80, 80, 4); +my $src = Imager::ImgRaw::new($src_height, $src_width, 4); my $halfred = NC(255, 0, 0, 128); i_box_filled($src, 20, 20, 60, 60, $halfred); -i_rubthru($targ, $src, 10, 10) or print "not "; +i_rubthru($targ, $src, 10, 10, 0, 0, $src_width, $src_height) or print "not "; print "ok 2\n"; my $c = Imager::i_get_pixel($targ, 10, 10) or print "not "; print "ok 3\n"; @@ -26,10 +29,10 @@ print "ok 6\n"; my $black = NC(0, 0, 0); # reset the target and try a grey+alpha source i_box_filled($targ, 0, 0, 100, 100, $black); -my $gsrc = Imager::ImgRaw::new(80, 80, 2); +my $gsrc = Imager::ImgRaw::new($src_width, $src_height, 2); my $halfwhite = NC(255, 128, 0); i_box_filled($gsrc, 20, 20, 60, 60, $halfwhite); -i_rubthru($targ, $gsrc, 10, 10) or print "not "; +i_rubthru($targ, $gsrc, 10, 10, 0, 0, $src_width, $src_height) or print "not "; print "ok 7\n"; $c = Imager::i_get_pixel($targ, 15, 15) or print "not "; print "ok 8\n"; @@ -42,7 +45,7 @@ print "ok 11\n"; # try grey target and grey alpha source my $gtarg = Imager::ImgRaw::new(100, 100, 1); -i_rubthru($gtarg, $gsrc, 10, 10) or print "not "; +i_rubthru($gtarg, $gsrc, 10, 10, 0, 0, $src_width, $src_height) or print "not "; print "ok 12\n"; $c = Imager::i_get_pixel($gtarg, 10, 10) or print "not "; print "ok 13\n"; @@ -52,12 +55,12 @@ print "ok 14\n"; print "ok 15\n"; # an attempt rub a 4 channel image over 1 channel should fail -i_rubthru($gtarg, $src, 10, 10) and print "not "; +i_rubthru($gtarg, $src, 10, 10, 0, 0, $src_width, $src_height) and print "not "; print "ok 16\n"; # simple test for 16-bit/sample images my $targ16 = Imager::i_img_16_new(100, 100, 3); -i_rubthru($targ16, $src, 10, 10) or print "not "; +i_rubthru($targ16, $src, 10, 10, 0, 0, $src_width, $src_height) or print "not "; print "ok 17\n"; $c = Imager::i_get_pixel($targ16, 30, 30) or print "not "; print "ok 18\n"; @@ -67,7 +70,7 @@ print "ok 19\n"; # check the OO interface my $ootarg = Imager->new(xsize=>100, ysize=>100); my $oosrc = Imager->new(xsize=>80, ysize=>80, channels=>4); -$oosrc->box(color=>$halfred, xmin=>20, ymin=>20, xmax=>60, ymax=>60, +$oosrc->box(color=>$halfred, xmin=>20, ymin=>20, xmax=>60, ymax=>60, filled=>1); $ootarg->rubthrough(src=>$oosrc, tx=>10, ty=>10) or print "not "; print "ok 20\n"; -- 2.30.2