static int setup_cmyk16(read_state_t *state);
static int putter_cmyk16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
+static void
+rgb_channels(read_state_t *state, int *out_channels);
+static void
+grey_channels(read_state_t *state, int *out_channels);
+static void
+cmyk_channels(read_state_t *state, int *out_channels);
+static void
+fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan);
static const int text_tag_count =
sizeof(text_tag_names) / sizeof(*text_tag_names);
read_setup_t setupf = NULL;
read_getter_t getterf = NULL;
read_putter_t putterf = NULL;
+ int channels = MAXCHANNELS;
+ size_t sample_size = ~0; /* force failure if some code doesn't set it */
+ i_img_dim total_pixels;
error = 0;
mm_log((1, "i_readtiff_wiol: %stiled\n", tiled?"":"not "));
mm_log((1, "i_readtiff_wiol: %sbyte swapped\n", TIFFIsByteSwapped(tif)?"":"not "));
+ total_pixels = width * height;
+ memset(&state, 0, sizeof(state));
+ state.tif = tif;
+ state.allow_incomplete = allow_incomplete;
+ state.width = width;
+ state.height = height;
+ state.bits_per_sample = bits_per_sample;
+ state.samples_per_pixel = samples_per_pixel;
+ state.photometric = photometric;
+
/* yes, this if() is horrible */
if (photometric == PHOTOMETRIC_PALETTE && bits_per_sample <= 8) {
setupf = setup_paletted;
putterf = paletted_putter4;
else
mm_log((1, "unsupported paletted bits_per_sample %d\n", bits_per_sample));
+
+ sample_size = sizeof(i_sample_t);
+ channels = 1;
}
else if (bits_per_sample == 16
&& photometric == PHOTOMETRIC_RGB
&& samples_per_pixel >= 3) {
setupf = setup_16_rgb;
putterf = putter_16;
+ sample_size = 2;
+ rgb_channels(&state, &channels);
}
else if (bits_per_sample == 16
&& photometric == PHOTOMETRIC_MINISBLACK) {
setupf = setup_16_grey;
putterf = putter_16;
+ sample_size = 2;
+ grey_channels(&state, &channels);
}
else if (bits_per_sample == 8
&& photometric == PHOTOMETRIC_MINISBLACK) {
setupf = setup_8_grey;
putterf = putter_8;
+ sample_size = 1;
+ grey_channels(&state, &channels);
}
else if (bits_per_sample == 8
&& photometric == PHOTOMETRIC_RGB) {
setupf = setup_8_rgb;
putterf = putter_8;
+ sample_size = 1;
+ rgb_channels(&state, &channels);
}
else if (bits_per_sample == 32
&& photometric == PHOTOMETRIC_RGB
&& samples_per_pixel >= 3) {
setupf = setup_32_rgb;
putterf = putter_32;
+ sample_size = sizeof(i_fsample_t);
+ rgb_channels(&state, &channels);
}
else if (bits_per_sample == 32
&& photometric == PHOTOMETRIC_MINISBLACK) {
setupf = setup_32_grey;
putterf = putter_32;
+ sample_size = sizeof(i_fsample_t);
+ grey_channels(&state, &channels);
}
else if (bits_per_sample == 1
&& (photometric == PHOTOMETRIC_MINISBLACK
&& samples_per_pixel == 1) {
setupf = setup_bilevel;
putterf = putter_bilevel;
+ sample_size = sizeof(i_palidx);
+ channels = 1;
}
else if (bits_per_sample == 8
&& photometric == PHOTOMETRIC_SEPARATED
&& samples_per_pixel >= 4) {
setupf = setup_cmyk8;
putterf = putter_cmyk8;
+ sample_size = 1;
+ cmyk_channels(&state, &channels);
}
else if (bits_per_sample == 16
&& photometric == PHOTOMETRIC_SEPARATED
&& samples_per_pixel >= 4) {
setupf = setup_cmyk16;
putterf = putter_cmyk16;
+ sample_size = 2;
+ cmyk_channels(&state, &channels);
}
+ else {
+ int alpha;
+ fallback_rgb_channels(tif, width, height, &channels, &alpha);
+ sample_size = 1;
+ }
+
+ if (!i_int_check_image_file_limits(width, height, channels, sample_size)) {
+ return NULL;
+ }
+
if (tiled) {
if (planar_config == PLANARCONFIG_CONTIG)
getterf = tile_contig_getter;
getterf = strip_contig_getter;
}
if (setupf && getterf && putterf) {
- i_img_dim total_pixels = width * height;
- memset(&state, 0, sizeof(state));
- state.tif = tif;
- state.allow_incomplete = allow_incomplete;
- state.width = width;
- state.height = height;
- state.bits_per_sample = bits_per_sample;
- state.samples_per_pixel = samples_per_pixel;
- state.photometric = photometric;
if (!setupf(&state))
return NULL;
}
}
-static i_img *
-make_rgb(TIFF *tif, i_img_dim width, i_img_dim height, int *alpha_chan) {
+/*
+=item fallback_rgb_channels
+
+Calculate the number of output channels when we fallback to the RGBA
+family of functions.
+
+=cut
+*/
+
+static void
+fallback_rgb_channels(TIFF *tif, i_img_dim width, i_img_dim height, int *channels, int *alpha_chan) {
uint16 photometric;
- uint16 channels, in_channels;
+ uint16 in_channels;
uint16 extra_count;
uint16 *extras;
switch (photometric) {
case PHOTOMETRIC_SEPARATED:
- channels = 3;
+ *channels = 3;
break;
case PHOTOMETRIC_MINISWHITE:
/* the TIFF RGBA functions expand single channel grey into RGB,
so reduce it, we move the alpha channel into the right place
if needed */
- channels = 1;
+ *channels = 1;
break;
default:
- channels = 3;
+ *channels = 3;
break;
}
/* TIFF images can have more than one alpha channel, but Imager can't
*alpha_chan = 0;
if (TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &extra_count, &extras)
&& extra_count) {
- *alpha_chan = channels++;
+ *alpha_chan = (*channels)++;
}
+}
+
+static i_img *
+make_rgb(TIFF *tif, i_img_dim width, i_img_dim height, int *alpha_chan) {
+ int channels = 0;
+
+ fallback_rgb_channels(tif, width, height, &channels, alpha_chan);
return i_img_8_new(width, height, channels);
}
#!perl -w
use strict;
-use Test::More tests => 217;
+use Test::More tests => 232;
use Imager qw(:all);
use Imager::Test qw(is_image is_image_similar test_image test_image_16 test_image_double test_image_raw);
}
+{ # check file limits are checked
+ my $limit_file = "testout/t106.tiff";
+ ok(Imager->set_file_limits(reset=>1, width=>149), "set width limit 149");
+ my $im = Imager->new;
+ ok(!$im->read(file=>$limit_file),
+ "should fail read due to size limits");
+ print "# ",$im->errstr,"\n";
+ like($im->errstr, qr/image width/, "check message");
+
+ ok(Imager->set_file_limits(reset=>1, height=>149), "set height limit 149");
+ ok(!$im->read(file=>$limit_file),
+ "should fail read due to size limits");
+ print "# ",$im->errstr,"\n";
+ like($im->errstr, qr/image height/, "check message");
+
+ ok(Imager->set_file_limits(reset=>1, width=>150), "set width limit 150");
+ ok($im->read(file=>$limit_file),
+ "should succeed - just inside width limit");
+ ok(Imager->set_file_limits(reset=>1, height=>150), "set height limit 150");
+ ok($im->read(file=>$limit_file),
+ "should succeed - just inside height limit");
+
+ # 150 x 150 x 3 channel image uses 67500 bytes
+ ok(Imager->set_file_limits(reset=>1, bytes=>67499),
+ "set bytes limit 67499");
+ ok(!$im->read(file=>$limit_file),
+ "should fail - too many bytes");
+ print "# ",$im->errstr,"\n";
+ like($im->errstr, qr/storage size/, "check error message");
+ ok(Imager->set_file_limits(reset=>1, bytes=>67500),
+ "set bytes limit 67500");
+ ok($im->read(file=>$limit_file),
+ "should succeed - just inside bytes limit");
+ Imager->set_file_limits(reset=>1);
+}