mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:57:46 +00:00
LibGfx/TIFF: Accept images with a single strip and no RowsPerStrip tag
This tag is required by the specification, but some encoders (at least Krita) don't write it for images with a single strip. The test file was generated by opening deflate.tiff in Krita and saving it with the DEFLATE compression.
This commit is contained in:
parent
284e785053
commit
c2c7365494
4 changed files with 20 additions and 4 deletions
|
@ -591,6 +591,18 @@ TEST_CASE(test_tiff_deflate)
|
|||
EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red);
|
||||
}
|
||||
|
||||
TEST_CASE(test_tiff_krita)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("tiff/krita.tif"sv)));
|
||||
EXPECT(Gfx::TIFFImageDecoderPlugin::sniff(file->bytes()));
|
||||
auto plugin_decoder = TRY_OR_FAIL(Gfx::TIFFImageDecoderPlugin::create(file->bytes()));
|
||||
|
||||
auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 400, 300 }));
|
||||
|
||||
EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::White);
|
||||
EXPECT_EQ(frame.image->get_pixel(60, 75), Gfx::Color::NamedColor::Red);
|
||||
}
|
||||
|
||||
TEST_CASE(test_tiff_orientation)
|
||||
{
|
||||
auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("tiff/orientation.tiff"sv)));
|
||||
|
|
BIN
Tests/LibGfx/test-inputs/tiff/krita.tif
Normal file
BIN
Tests/LibGfx/test-inputs/tiff/krita.tif
Normal file
Binary file not shown.
|
@ -75,6 +75,9 @@ public:
|
|||
if (m_metadata.strip_offsets()->size() != m_metadata.strip_byte_counts()->size())
|
||||
return Error::from_string_literal("TIFFImageDecoderPlugin: StripsOffset and StripByteCount have different sizes");
|
||||
|
||||
if (!m_metadata.rows_per_strip().has_value() && m_metadata.strip_byte_counts()->size() != 1)
|
||||
return Error::from_string_literal("TIFFImageDecoderPlugin: RowsPerStrip is not provided and impossible to deduce");
|
||||
|
||||
if (any_of(*m_metadata.bits_per_sample(), [](auto bit_depth) { return bit_depth == 0 || bit_depth > 32; }))
|
||||
return Error::from_string_literal("TIFFImageDecoderPlugin: Invalid value in BitsPerSample");
|
||||
|
||||
|
@ -238,19 +241,20 @@ private:
|
|||
{
|
||||
auto const strips_offset = *m_metadata.strip_offsets();
|
||||
auto const strip_byte_counts = *m_metadata.strip_byte_counts();
|
||||
auto const rows_per_strip = m_metadata.rows_per_strip().value_or(*m_metadata.image_height());
|
||||
|
||||
auto oriented_bitmap = TRY(ExifOrientedBitmap::create(BitmapFormat::BGRA8888, { *metadata().image_width(), *metadata().image_height() }, *metadata().orientation()));
|
||||
|
||||
for (u32 strip_index = 0; strip_index < strips_offset.size(); ++strip_index) {
|
||||
TRY(m_stream->seek(strips_offset[strip_index]));
|
||||
|
||||
auto const rows_in_strip = strip_index < strips_offset.size() - 1 ? *m_metadata.rows_per_strip() : *m_metadata.image_height() - *m_metadata.rows_per_strip() * strip_index;
|
||||
auto const rows_in_strip = strip_index < strips_offset.size() - 1 ? rows_per_strip : *m_metadata.image_height() - rows_per_strip * strip_index;
|
||||
auto const decoded_bytes = TRY(strip_decoder(strip_byte_counts[strip_index], rows_in_strip));
|
||||
auto decoded_strip = make<FixedMemoryStream>(decoded_bytes);
|
||||
auto decoded_stream = make<BigEndianInputBitStream>(move(decoded_strip));
|
||||
|
||||
for (u32 row = 0; row < *m_metadata.rows_per_strip(); row++) {
|
||||
auto const scanline = row + *m_metadata.rows_per_strip() * strip_index;
|
||||
for (u32 row = 0; row < rows_per_strip; row++) {
|
||||
auto const scanline = row + rows_per_strip * strip_index;
|
||||
if (scanline >= *m_metadata.image_height())
|
||||
break;
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ known_tags: List[Tag] = [
|
|||
Tag('273', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripOffsets", is_required=True),
|
||||
Tag('274', [TIFFType.UnsignedShort], [1], Orientation.Default, "Orientation", Orientation),
|
||||
Tag('277', [TIFFType.UnsignedShort], [1], None, "SamplesPerPixel", is_required=True),
|
||||
Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip", is_required=True),
|
||||
Tag('278', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [1], None, "RowsPerStrip", is_required=False),
|
||||
Tag('279', [TIFFType.UnsignedShort, TIFFType.UnsignedLong], [], None, "StripByteCounts", is_required=True),
|
||||
Tag('282', [TIFFType.UnsignedRational], [1], None, "XResolution"),
|
||||
Tag('283', [TIFFType.UnsignedRational], [1], None, "YResolution"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue