From cf692b64919ff55e15f2428863192378ccc44fbd Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Wed, 22 Aug 2001 00:49:25 +0000 Subject: [PATCH] various JPEG fixes --- Changes | 3 +++ Imager.pm | 25 ++++++++----------------- jpeg.c | 23 +++++++++++++++++++---- t/t101jpeg.t | 28 +++++++++++++++++++++++----- 4 files changed, 53 insertions(+), 26 deletions(-) diff --git a/Changes b/Changes index 2d5f0285..caa23e7b 100644 --- a/Changes +++ b/Changes @@ -477,6 +477,9 @@ Revision history for Perl extension Imager. - added OO interfaces for the mosaic, bumpmap, postlevels and watermark filters - added t/t61filters.t to test the filters + - fixed some problems in jpeg handling from the exp_represent merge + - fixed buffer flushing for wiol jpeg code + - added some tests that will hopefully catch it in the future ================================================================= diff --git a/Imager.pm b/Imager.pm index 6eed0e0b..a091901b 100644 --- a/Imager.pm +++ b/Imager.pm @@ -52,7 +52,6 @@ use Imager::Font; i_haar i_count_colors - i_gaussian i_conv @@ -365,7 +364,6 @@ sub new { return $self; } - # Copy an entire image with no changes # - if an image has magic the copy of it will not be magical @@ -736,7 +734,7 @@ sub read { # yes the code isn't here yet - next week maybe? # Next week? Are you high or something? That comment # has been there for half a year dude. - + # Look, i just work here, ok? if (!$input{type} and $input{file}) { $input{type}=$FORMATGUESS->($input{file}); @@ -821,7 +819,6 @@ sub read { # Old code for reference while changing the new stuff - if (!$input{type} and $input{file}) { $input{type}=$FORMATGUESS->($input{file}); } @@ -879,29 +876,18 @@ sub read { } $self->{DEBUG} && print "loading a gif file\n"; } - - if ( $input{type} eq 'jpeg' ) { - if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) { - $self->{ERRSTR}='unable to write jpeg image'; - return undef; - } - $self->{DEBUG} && print "writing a jpeg file\n"; - } - } return $self; } - # Write an image to file - sub write { my $self = shift; my %input=(jpegquality=>75, gifquant=>'mc', lmdither=>6.0, lmfixed=>[], fax_fine=>1, @_); my ($fh, $rc, $fd, $IO); - my %iolready=( tiff=>1, raw=>1, png=>1, pnm=>1, bmp=>1, ); # this will be SO MUCH BETTER once they are all in there + my %iolready=( tiff=>1, raw=>1, png=>1, pnm=>1, bmp=>1, jpeg=>1 ); # this will be SO MUCH BETTER once they are all in there unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; } @@ -957,6 +943,12 @@ sub write { return undef; } $self->{DEBUG} && print "writing a png file\n"; + } elsif ( $input{type} eq 'jpeg' ) { + if ( !i_writejpeg_wiol($self->{IMG}, $IO, $input{jpegquality})) { + $self->{ERRSTR}='unable to write jpeg image'; + return undef; + } + $self->{DEBUG} && print "writing a jpeg file\n"; } elsif ( $input{type} eq 'bmp' ) { if ( !i_writebmp_wiol($self->{IMG}, $IO) ) { $self->{ERRSTR}='unable to write bmp image'; @@ -975,7 +967,6 @@ sub write { } return $self; } else { - if ( $input{type} eq 'gif' ) { if (not $input{gifplanes}) { my $gp; diff --git a/jpeg.c b/jpeg.c index 6aba1252..5796f003 100644 --- a/jpeg.c +++ b/jpeg.c @@ -177,14 +177,23 @@ wiol_init_destination (j_compress_ptr cinfo) { static boolean wiol_empty_output_buffer(j_compress_ptr cinfo) { wiol_dest_ptr dest = (wiol_dest_ptr) cinfo->dest; - ssize_t nbytes = JPGS - dest->pub.free_in_buffer; ssize_t rc; + /* + Previously this code was checking free_in_buffer to see how much + needed to be written. This does not follow the documentation: + + "In typical applications, it should write out the + *entire* buffer (use the saved start address and buffer length; + ignore the current state of next_output_byte and free_in_buffer)." + + ssize_t nbytes = JPGS - dest->pub.free_in_buffer; + */ mm_log((1,"wiol_emtpy_output_buffer(cinfo 0x%p)\n")); - rc = dest->data->writecb(dest->data, dest->buffer, nbytes); + rc = dest->data->writecb(dest->data, dest->buffer, JPGS); - if (rc != nbytes) { /* XXX: Should raise some jpeg error */ - mm_log((1, "wiol_empty_output_buffer: Error: nbytes = %d != rc = %d\n", nbytes, rc)); + if (rc != JPGS) { /* XXX: Should raise some jpeg error */ + mm_log((1, "wiol_empty_output_buffer: Error: nbytes = %d != rc = %d\n", JPGS, rc)); } dest->pub.free_in_buffer = JPGS; dest->pub.next_output_byte = dest->buffer; @@ -194,6 +203,12 @@ wiol_empty_output_buffer(j_compress_ptr cinfo) { static void wiol_term_destination (j_compress_ptr cinfo) { wiol_dest_ptr dest = (wiol_dest_ptr) cinfo->dest; + + /* yes, this needs to flush the buffer */ + /* needs error handling */ + dest->data->writecb(dest->data, dest->buffer, + JPGS - dest->pub.free_in_buffer); + mm_log((1, "wiol_term_destination(cinfo %p)\n", cinfo)); mm_log((1, "wiol_term_destination: dest %p\n", cinfo->dest)); if (dest != NULL) myfree(dest->buffer); diff --git a/t/t101jpeg.t b/t/t101jpeg.t index 8043c8cb..00c09e6a 100644 --- a/t/t101jpeg.t +++ b/t/t101jpeg.t @@ -1,6 +1,6 @@ use Imager qw(:all); -print "1..2\n"; +print "1..7\n"; init_log("testout/t101jpeg.log",1); @@ -18,8 +18,9 @@ i_conv($img,[0.1, 0.2, 0.4, 0.2, 0.1]); i_has_format("jpeg") && print "# has jpeg\n"; if (!i_has_format("jpeg")) { - print "ok 1 # skip no jpeg support\n"; - print "ok 2 # skip no jpeg support\n"; + for (1..7) { + print "ok $_ # skip no jpeg support\n"; + } } else { open(FH,">testout/t101.jpg") || die "cannot open testout/t101.jpg for writing\n"; binmode(FH); @@ -36,7 +37,24 @@ if (!i_has_format("jpeg")) { close(FH); print "$cmpimg\n"; - - print "# jpeg average mean square pixel difference: ",sqrt(i_img_diff($img,$cmpimg))/150*150,"\n"; + my $diff = sqrt(i_img_diff($img,$cmpimg))/150*150; + print "# jpeg average mean square pixel difference: ",$diff,"\n"; print "ok 2\n"; + + $diff < 10000 or print "not "; + print "ok 3\n"; + + my $imoo = Imager->new; + $imoo->read(file=>'testout/t101.jpg') or print "not "; + print "ok 4\n"; + $imoo->write(file=>'testout/t101_oo.jpg') or print "not "; + print "ok 5\n"; + my $oocmp = Imager->new; + $oocmp->read(file=>'testout/t101_oo.jpg') or print "not "; + print "ok 6\n"; + + $diff = sqrt(i_img_diff($imoo->{IMG},$oocmp->{IMG}))/150*150; + print "# OO image difference $diff\n"; + $diff < 10000 or print "not "; + print "ok 7\n"; } -- 2.39.5