From: Tony Cook Date: Sat, 1 Dec 2001 03:25:12 +0000 (+0000) Subject: write paletted images as paletted for tiff X-Git-Tag: Imager-0.48^2~474 X-Git-Url: http://git.imager.perl.org/imager.git/commitdiff_plain/f62b2d84592a72eed5a3cb4a92ba315a706e7dcd write paletted images as paletted for tiff minor doc fix in freetyp2.c --- diff --git a/Changes b/Changes index 04b28960..7414ba3d 100644 --- a/Changes +++ b/Changes @@ -558,7 +558,8 @@ Revision history for Perl extension Imager. - use the error stack value from reading bmp files - fix an error message in bmp.c - added has_chars() method to Imager::Font::FreeType2 - - freetype 2 bounding box function didn't know UTF8 (doh!) + - freetype 2 bounding box function didn't know UTF8 (doh!) + - write paletted images as paletted to tiff ================================================================= diff --git a/TODO b/TODO index b97b2e32..1939efd7 100644 --- a/TODO +++ b/TODO @@ -55,6 +55,8 @@ New Features: - read_multi() needs to handle other multi-image types, such as TIFF (probably the most common) +- write_multi() to save other multi-image types, especially TIFF + - compose channels - build a new image based on channels from several images @@ -96,10 +98,12 @@ Format specific issues: pbm images which needs ties to the quantization code. - save paletted images as paletted where that's supported. Done - for gif/tga. Not done for png/tiff yet. + for gif/tga/bmp/tiff. Not done for png yet. - read other format paletted images as paletted images. This has - been done for gif/tga formats but not for tiff/png. + been done for gif/tga/bmp/tiff formats but not for png. + +- read/write 16-bit/sample images as such for tiff Documentation: - Add to the documentation diff --git a/freetyp2.c b/freetyp2.c index f180d4df..e155d525 100644 --- a/freetyp2.c +++ b/freetyp2.c @@ -13,7 +13,7 @@ freetyp2.c - font support via the FreeType library version 2. double matrix[6]; if (!i_ft2_settransform(font, matrix)) { error } int bbox[6]; - if (!i_ft2_bbox(font, cheight, cwidth, text, length, bbox)) { error } + if (!i_ft2_bbox(font, cheight, cwidth, text, length, bbox, utf8)) { error } i_img *im = ...; i_color cl; if (!i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, length, align, diff --git a/t/t106tiff.t b/t/t106tiff.t index 4c6b7b1b..412b1f59 100644 --- a/t/t106tiff.t +++ b/t/t106tiff.t @@ -1,5 +1,5 @@ #!perl -w -print "1..33\n"; +print "1..43\n"; use Imager qw(:all); $^W=1; # warnings during command-line tests $|=1; # give us some progress in the test harness @@ -24,7 +24,7 @@ i_box_filled($timg, 2, 2, 18, 18, $trans); my $test_num; if (!i_has_format("tiff")) { - for (1..33) { + for (1..43) { print "ok $_ # skip no tiff support\n"; } } else { @@ -188,6 +188,22 @@ if (!i_has_format("tiff")) { my $bad = Imager->new; ok($bad->read(file=>'testimg/comp4bad.tif'), "bad image not returned"); ok(scalar $bad->tags(name=>'i_incomplete'), "incomplete tag not set"); + ok($img8->write(file=>'testout/t106_pal8.tif'), "writing 8-bit paletted"); + ok(my $cmp8 = Imager->new->read(file=>'testout/t106pal8.tif'), + "reading 8-bit paletted"); + ok($cmp8->type eq 'paletted', "pal8 isn't paletted"); + ok($cmp8->colorcount == 256, "pal8 bad colorcount"); + $diff = i_img_diff($img8->{IMG}, $cmp8->{IMG}); + print "# diff $diff\n"; + ok($diff == 0, "written image doesn't match read"); + ok($img4->write(file=>'testout/t106_pal4.tif'), "writing 4-bit paletted"); + ok(my $cmp4 = Imager->new->read(file=>'testout/t106_pal4.tif'), + "reading 4-bit paletted"); + ok($cmp4->type eq 'paletted', "pal4 isn't paletted"); + ok($cmp4->colorcount == 16, "pal4 bad colorcount"); + $diff = i_img_diff($img4->{IMG}, $cmp4->{IMG}); + print "# diff $diff\n"; + ok($diff == 0, "written image doesn't match read"); } sub ok { diff --git a/tiff.c b/tiff.c index bd6d8cd0..0535ab4d 100644 --- a/tiff.c +++ b/tiff.c @@ -65,6 +65,8 @@ static int save_tiff_tags(TIFF *tif, i_img *im); static void expand_4bit_hl(unsigned char *buf, int count); +static void pack_4bit_hl(unsigned char *buf, int count); + /* =item comp_seek(h, o, w) @@ -384,6 +386,9 @@ i_writetiff_wiol(i_img *im, io_glue *ig) { TIFF* tif; int got_xres, got_yres, got_aspectonly, aspect_only, resunit; double xres, yres; + uint16 bitspersample = 8; + uint16 samplesperpixel; + uint16 *colors = NULL; char *cc = mymalloc( 123 ); myfree(cc); @@ -400,6 +405,9 @@ i_writetiff_wiol(i_img *im, io_glue *ig) { case 3: photometric = PHOTOMETRIC_RGB; if (compression == COMPRESSION_JPEG && jpegcolormode == JPEGCOLORMODE_RGB) photometric = PHOTOMETRIC_YCBCR; + else if (im->type == i_palette_type) { + photometric = PHOTOMETRIC_PALETTE; + } break; default: /* This means a colorspace we don't handle yet */ @@ -437,12 +445,60 @@ i_writetiff_wiol(i_img *im, io_glue *ig) { if (!TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width) ) { mm_log((1, "i_writetiff_wiol: TIFFSetField width=%d failed\n", width)); return 0; } if (!TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height) ) { mm_log((1, "i_writetiff_wiol: TIFFSetField length=%d failed\n", height)); return 0; } - if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels)) { mm_log((1, "i_writetiff_wiol: TIFFSetField samplesperpixel=%d failed\n", channels)); return 0; } if (!TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)) { mm_log((1, "i_writetiff_wiol: TIFFSetField Orientation=topleft\n")); return 0; } - if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8) ) { mm_log((1, "i_writetiff_wiol: TIFFSetField bitpersample=8\n")); return 0; } if (!TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) { mm_log((1, "i_writetiff_wiol: TIFFSetField planarconfig\n")); return 0; } if (!TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, photometric)) { mm_log((1, "i_writetiff_wiol: TIFFSetField photometric=%d\n", photometric)); return 0; } if (!TIFFSetField(tif, TIFFTAG_COMPRESSION, compression)) { mm_log((1, "i_writetiff_wiol: TIFFSetField compression=%d\n", compression)); return 0; } + samplesperpixel = channels; + if (photometric == PHOTOMETRIC_PALETTE) { + uint16 *out[3]; + i_color c; + int count = i_colorcount(im); + int size; + int bits; + int ch, i; + + samplesperpixel = 1; + if (count > 16) + bitspersample = 8; + else + bitspersample = 4; + size = 1 << bitspersample; + colors = (uint16 *)_TIFFmalloc(sizeof(uint16) * 3 * size); + out[0] = colors; + out[1] = colors + size; + out[2] = colors + 2 * size; + + for (i = 0; i < count; ++i) { + i_getcolors(im, i, &c, 1); + for (ch = 0; ch < 3; ++ch) + out[ch][i] = c.channel[ch] * 257; + } + for (; i < size; ++i) { + for (ch = 0; ch < 3; ++ch) + out[ch][i] = 0; + } + if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample)) { + mm_log((1, "i_writetiff_wiol: TIFFSetField bitpersample=%d\n", + bitspersample)); + return 0; + } + if (!TIFFSetField(tif, TIFFTAG_COLORMAP, out[0], out[1], out[2])) { + mm_log((1, "i_writetiff_wiol: TIFFSetField colormap\n")); + return 0; + } + } + else { + if (!TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitspersample)) { + mm_log((1, "i_writetiff_wiol: TIFFSetField bitpersample=%d\n", + bitspersample)); + return 0; + } + } + if (!TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel)) { + mm_log((1, "i_writetiff_wiol: TIFFSetField samplesperpixel=%d failed\n", samplesperpixel)); + return 0; + } switch (compression) { case COMPRESSION_JPEG: @@ -467,8 +523,12 @@ i_writetiff_wiol(i_img *im, io_glue *ig) { } linebytes = channels * width; - linebuf = (unsigned char *)_TIFFmalloc( TIFFScanlineSize(tif) > linebytes ? - linebytes : TIFFScanlineSize(tif) ); + linebytes = TIFFScanlineSize(tif) > linebytes ? linebytes + : TIFFScanlineSize(tif); + /* working space for the scanlines - we go from 8-bit/pixel to 4 */ + if (photometric == PHOTOMETRIC_PALETTE && bitspersample == 4) + linebytes += linebytes + 1; + linebuf = (unsigned char *)_TIFFmalloc(linebytes); if (!TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, rowsperstrip))) { mm_log((1, "i_writetiff_wiol: TIFFSetField rowsperstrip=%d\n", rowsperstrip)); return 0; } @@ -528,19 +588,34 @@ i_writetiff_wiol(i_img *im, io_glue *ig) { return 0; } - for (y=0; y