From: Tony Cook Date: Sun, 5 Sep 2010 06:45:57 +0000 (+0000) Subject: optimize filled box drawing X-Git-Tag: Imager-0.79~68 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/3b0005868a876f94903b50b42eaf5328ad970280 optimize filled box drawing --- diff --git a/Imager.pm b/Imager.pm index a42a6187..e8ec8155 100644 --- a/Imager.pm +++ b/Imager.pm @@ -2651,14 +2651,27 @@ sub i_color_set { # Draws a box between the specified corner points. sub box { my $self=shift; - unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; } - my %opts=(xmin=>0,ymin=>0,xmax=>$self->getwidth()-1,ymax=>$self->getheight()-1,@_); + my $raw = $self->{IMG}; + + unless ($raw) { + $self->{ERRSTR}='empty input image'; + return undef; + } + + my %opts = @_; + my ($xmin, $ymin, $xmax, $ymax); if (exists $opts{'box'}) { - $opts{'xmin'} = _min($opts{'box'}->[0],$opts{'box'}->[2]); - $opts{'xmax'} = _max($opts{'box'}->[0],$opts{'box'}->[2]); - $opts{'ymin'} = _min($opts{'box'}->[1],$opts{'box'}->[3]); - $opts{'ymax'} = _max($opts{'box'}->[1],$opts{'box'}->[3]); + $xmin = _min($opts{'box'}->[0],$opts{'box'}->[2]); + $xmax = _max($opts{'box'}->[0],$opts{'box'}->[2]); + $ymin = _min($opts{'box'}->[1],$opts{'box'}->[3]); + $ymax = _max($opts{'box'}->[1],$opts{'box'}->[3]); + } + else { + defined($xmin = $opts{xmin}) or $xmin = 0; + defined($xmax = $opts{xmax}) or $xmax = $self->getwidth()-1; + defined($ymin = $opts{ymin}) or $ymin = 0; + defined($ymax = $opts{ymax}) or $ymax = $self->getheight()-1; } if ($opts{filled}) { @@ -2679,8 +2692,7 @@ sub box { $color = i_color_new(255,255,255,255); } - i_box_filled($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax}, - $opts{ymax}, $color); + i_box_filled($raw, $xmin, $ymin,$xmax, $ymax, $color); } elsif ($opts{fill}) { unless (UNIVERSAL::isa($opts{fill}, 'Imager::Fill')) { @@ -2691,8 +2703,7 @@ sub box { return undef; } } - i_box_cfill($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax}, - $opts{ymax},$opts{fill}{fill}); + i_box_cfill($raw, $xmin, $ymin, $xmax, $ymax, $opts{fill}{fill}); } else { my $color = $opts{'color'}; @@ -2714,9 +2725,9 @@ sub box { $self->{ERRSTR} = $Imager::ERRSTR; return; } - i_box($self->{IMG},$opts{xmin},$opts{ymin},$opts{xmax},$opts{ymax}, - $color); + i_box($raw, $xmin, $ymin, $xmax, $ymax, $color); } + return $self; } @@ -3520,16 +3531,26 @@ sub border { sub getwidth { my $self = shift; - if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; } - return (i_img_info($self->{IMG}))[0]; + + if (my $raw = $self->{IMG}) { + return i_img_get_width($raw); + } + else { + $self->{ERRSTR} = 'image is empty'; return undef; + } } # Get the height of an image sub getheight { my $self = shift; - if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; } - return (i_img_info($self->{IMG}))[1]; + + if (my $raw = $self->{IMG}) { + return i_img_get_height($raw); + } + else { + $self->{ERRSTR} = 'image is empty'; return undef; + } } # Get number of channels in an image diff --git a/Imager.xs b/Imager.xs index 696eebf9..31f0e3a8 100644 --- a/Imager.xs +++ b/Imager.xs @@ -951,6 +951,9 @@ static im_pl_ext_funcs im_perl_funcs = /* trying to use more C style names, map them here */ #define i_io_DESTROY(ig) io_glue_destroy(ig) +#define i_img_get_width(im) ((im)->xsize) +#define i_img_get_height(im) ((im)->ysize) + MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_ Imager::Color @@ -1384,6 +1387,15 @@ i_img_getdata(im) sv_2mortal(newSVpv((char *)im->idata, im->bytes)) : &PL_sv_undef); +IV +i_img_get_width(im) + Imager::ImgRaw im + +IV +i_img_get_height(im) + Imager::ImgRaw im + + void i_img_is_monochrome(im) Imager::ImgRaw im diff --git a/bench/box.pl b/bench/box.pl index 611a9fce..19e53735 100644 --- a/bench/box.pl +++ b/bench/box.pl @@ -156,3 +156,72 @@ palbox0010: 740.9 /s (0.001350 / iter) palbox0100: 473.2 /s (0.002113 / iter) palbox0500: 186.2 /s (0.005371 / iter) palbox1000: 109.1 /s (0.009167 / iter) + +re-work i_box_filled(): + +box0010: 783.0 /s (0.001277 / iter) +box0010c: 3.3 /s (0.300588 / iter) +box0010d: 463.7 /s (0.002157 / iter) +box0100: 548.2 /s (0.001824 / iter) +box0500: 250.2 /s (0.003997 / iter) +box1000: 155.1 /s (0.006448 / iter) +fbox0010: 743.7 /s (0.001345 / iter) +fbox0010c: 3.3 /s (0.302941 / iter) +fbox0010d: 448.3 /s (0.002231 / iter) +fbox0100: 147.8 /s (0.006765 / iter) +fbox0500: 7.6 /s (0.132308 / iter) +fbox1000: 1.9 /s (0.521000 / iter) +fpalbox0010: 784.9 /s (0.001274 / iter) +fpalbox0100: 424.7 /s (0.002355 / iter) +fpalbox0500: 42.6 /s (0.023496 / iter) +fpalbox1000: 11.4 /s (0.087966 / iter) +palbox0010: 778.8 /s (0.001284 / iter) +palbox0100: 541.5 /s (0.001847 / iter) +palbox0500: 238.0 /s (0.004203 / iter) +palbox1000: 141.1 /s (0.007088 / iter) + +optimize getwidth/getheight: + +box0010: 832.5 /s (0.001201 / iter) +box0010c: 3.4 /s (0.297647 / iter) +box0010d: 491.3 /s (0.002035 / iter) +box0100: 594.7 /s (0.001682 / iter) +box0500: 259.1 /s (0.003859 / iter) +box1000: 158.5 /s (0.006310 / iter) +fbox0010: 798.1 /s (0.001253 / iter) +fbox0010c: 3.3 /s (0.300588 / iter) +fbox0010d: 477.7 /s (0.002093 / iter) +fbox0100: 148.5 /s (0.006735 / iter) +fbox0500: 7.5 /s (0.134103 / iter) +fbox1000: 1.9 /s (0.530000 / iter) +fpalbox0010: 829.0 /s (0.001206 / iter) +fpalbox0100: 444.1 /s (0.002252 / iter) +fpalbox0500: 43.0 /s (0.023260 / iter) +fpalbox1000: 11.5 /s (0.087333 / iter) +palbox0010: 826.0 /s (0.001211 / iter) +palbox0100: 553.2 /s (0.001808 / iter) +palbox0500: 242.7 /s (0.004119 / iter) +palbox1000: 144.4 /s (0.006923 / iter) + +pull stuff out of the hash fast: + +box0010: 1332.0 /s (0.000751 / iter) +box0010c: 3.4 /s (0.295882 / iter) +box0010d: 646.6 /s (0.001546 / iter) +box0100: 805.3 /s (0.001242 / iter) +box0500: 293.1 /s (0.003412 / iter) +box1000: 161.7 /s (0.006183 / iter) +fbox0010: 1215.2 /s (0.000823 / iter) +fbox0010c: 3.4 /s (0.295294 / iter) +fbox0010d: 600.9 /s (0.001664 / iter) +fbox0100: 160.2 /s (0.006241 / iter) +fbox0500: 7.6 /s (0.131250 / iter) +fbox1000: 1.9 /s (0.519000 / iter) +fpalbox0010: 1295.2 /s (0.000772 / iter) +fpalbox0100: 547.2 /s (0.001828 / iter) +fpalbox0500: 43.8 /s (0.022845 / iter) +fpalbox1000: 11.5 /s (0.087333 / iter) +palbox0010: 1314.1 /s (0.000761 / iter) +palbox0100: 752.2 /s (0.001330 / iter) +palbox0500: 269.4 /s (0.003712 / iter) +palbox1000: 145.3 /s (0.006884 / iter) diff --git a/draw.c b/draw.c index 240d22cc..93ae7ab0 100644 --- a/draw.c +++ b/draw.c @@ -1076,9 +1076,50 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with color. void i_box_filled(i_img *im,int x1,int y1,int x2,int y2, const i_color *val) { - int x,y; + i_img_dim x, y, width; + i_palidx index; + mm_log((1,"i_box_filled(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val)); - for(x=x1;x x2 || y1 > y2 + || x2 < 0 || y2 < 0 + || x1 >= im->xsize || y1 > im->ysize) + return; + + if (x1 < 0) + x1 = 0; + if (x2 >= im->xsize) + x2 = im->xsize - 1; + if (y1 < 0) + y1 = 0; + if (y2 >= im->ysize) + y2 = im->ysize - 1; + + width = x2 - x1 + 1; + + if (im->type == i_palette_type + && i_findcolor(im, val, &index)) { + i_palidx *line = mymalloc(sizeof(i_palidx) * width); + + for (x = 0; x < width; ++x) + line[x] = index; + + for (y = y1; y <= y2; ++y) + i_ppal(im, x1, x2+1, y, line); + + myfree(line); + } + else { + i_color *line = mymalloc(sizeof(i_color) * width); + + for (x = 0; x < width; ++x) + line[x] = *val; + + for (y = y1; y <= y2; ++y) + i_plin(im, x1, x2+1, y, line); + + myfree(line); + } } /* diff --git a/t/t01introvert.t b/t/t01introvert.t index 85d3792f..c0f3baf3 100644 --- a/t/t01introvert.t +++ b/t/t01introvert.t @@ -3,7 +3,7 @@ # to make sure we get expected values use strict; -use Test::More tests => 220; +use Test::More tests => 224; BEGIN { use_ok(Imager => qw(:handy :all)) } @@ -28,6 +28,8 @@ ok(Imager::i_img_getmask($im_g) & 1, "1 channel image mask"); ok(!Imager::i_img_virtual($im_g), "1 channel image not virtual"); is(Imager::i_img_bits($im_g), 8, "1 channel image has 8 bits/sample"); is(Imager::i_img_type($im_g), 0, "1 channel image is direct"); +is(Imager::i_img_get_width($im_g), 100, "100 pixels wide"); +is(Imager::i_img_get_height($im_g), 101, "101 pixels high"); my @ginfo = Imager::i_img_info($im_g); is($ginfo[0], 100, "1 channel image width"); @@ -120,6 +122,8 @@ ok($impal2, "make paletted via OO"); is($impal2->getchannels, 3, "check channels"); is($impal2->bits, 8, "check bits"); is($impal2->type, 'paletted', "check type"); +is($impal2->getwidth, 200, "check width"); +is($impal2->getheight, 201, "check height"); { my $red_idx = $impal2->addcolors(colors=>[$red]);