vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif |binary vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx | 51 ++++ vcl/source/filter/itiff/itiff.cxx | 239 ++++++++++---------- 3 files changed, 177 insertions(+), 113 deletions(-)
New commits: commit 520d8c9ec7718cf6678614ecf18656dafcad9445 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Apr 29 13:18:47 2022 +0100 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Sun May 1 11:03:13 2022 +0200 tdf#74331: 16bit "min-is-black" tiff not loaded correctly try an alternative fix git show -w is your friend here Change-Id: Ie9644f73431243ea0e9c6ef7f5c7ca4dadc7ed9e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133638 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif new file mode 100644 index 000000000000..702b8218ca5f Binary files /dev/null and b/vcl/qa/cppunit/graphicfilter/data/tiff/tdf74331.tif differ diff --git a/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx index 5842acf9ae8d..72f12ca565f5 100644 --- a/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx +++ b/vcl/qa/cppunit/graphicfilter/filters-tiff-test.cxx @@ -45,6 +45,7 @@ public: void testTdf126460(); void testTdf115863(); void testTdf138818(); + void testTdf74331(); void testRoundtrip(); void testRGB8bits(); void testRGB16bits(); @@ -54,6 +55,7 @@ public: CPPUNIT_TEST(testTdf126460); CPPUNIT_TEST(testTdf115863); CPPUNIT_TEST(testTdf138818); + CPPUNIT_TEST(testTdf74331); CPPUNIT_TEST(testRoundtrip); CPPUNIT_TEST(testRGB8bits); CPPUNIT_TEST(testRGB16bits); @@ -128,6 +130,55 @@ void TiffFilterTest::testTdf138818() CPPUNIT_ASSERT_EQUAL(sal_uInt32(46428), aGraphic.GetGfxLink().GetDataSize()); } +void TiffFilterTest::testTdf74331() +{ + OUString aURL = getUrl() + "tdf74331.tif"; + SvFileStream aFileStream(aURL, StreamMode::READ); + Graphic aGraphic; + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + + ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream); + + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); + + Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap(); + Size aSize = aBitmap.GetSizePixel(); + CPPUNIT_ASSERT_EQUAL(tools::Long(200), aSize.Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(200), aSize.Height()); + + Bitmap::ScopedReadAccess pReadAccess(aBitmap); + + // Check the image contains different kinds of grays + int nGrayCount = 0; + int nGray3Count = 0; + int nGray7Count = 0; + int nLightGrayCount = 0; + + for (tools::Long nX = 1; nX < aSize.Width() - 1; ++nX) + { + for (tools::Long nY = 1; nY < aSize.Height() - 1; ++nY) + { + const Color aColor = pReadAccess->GetColor(nY, nX); + if (aColor == COL_GRAY) + ++nGrayCount; + else if (aColor == COL_GRAY3) + ++nGray3Count; + else if (aColor == COL_GRAY7) + ++nGray7Count; + else if (aColor == COL_LIGHTGRAY) + ++nLightGrayCount; + } + } + + // Without the fix in place, this test would have failed with + // - Expected: 313 + // - Actual : 0 + CPPUNIT_ASSERT_EQUAL(313, nGrayCount); + CPPUNIT_ASSERT_EQUAL(71, nGray3Count); + CPPUNIT_ASSERT_EQUAL(227, nGray7Count); + CPPUNIT_ASSERT_EQUAL(165, nLightGrayCount); +} + void TiffFilterTest::testRoundtrip() { Bitmap aBitmap(Size(2, 2), vcl::PixelFormat::N24_BPP); diff --git a/vcl/source/filter/itiff/itiff.cxx b/vcl/source/filter/itiff/itiff.cxx index 7fa66b746c5d..f94864f429e0 100644 --- a/vcl/source/filter/itiff/itiff.cxx +++ b/vcl/source/filter/itiff/itiff.cxx @@ -978,156 +978,169 @@ bool TIFFReader::ConvertScanline(sal_Int32 nY) { if ( nMaxSampleValue > nMinSampleValue ) { - sal_uInt32 nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); sal_uInt8* pt = getMapData(0); sal_uInt8* ptend = pt + nBytesPerRow; - sal_uInt8 nShift; - switch ( nDstBitsPerPixel ) + if (nBitsPerSample > 8) { - case 8 : + sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue ); + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) { - if (pt + nImageWidth > ptend) - return false; + nVal = GetBits(pt, nx * nSamplesPerPixel * nBitsPerSample, nBitsPerSample); + SetPixel(nY, nx, static_cast<sal_uInt8>(nVal - nMinMax)); + } + } + else + { + sal_uInt32 nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); + sal_uInt8 nShift; - if ( bByteSwap ) + switch ( nDstBitsPerPixel ) + { + case 8 : { - if ( nPredictor == 2 ) + if (pt + nImageWidth > ptend) + return false; + + if ( bByteSwap ) { - sal_uInt8 nLast = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + if ( nPredictor == 2 ) { - nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++; - SetPixel(nY, nx, nLast); + sal_uInt8 nLast = 0; + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + { + nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++; + SetPixel(nY, nx, nLast); + } } - } - else - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + else { - sal_uInt8 nLast = *pt++; - SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax )); + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + { + sal_uInt8 nLast = *pt++; + SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax )); + } } } - } - else - { - if ( nPredictor == 2 ) + else { - sal_uInt8 nLast = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + if ( nPredictor == 2 ) { - nLast += *pt++; - SetPixel(nY, nx, nLast); + sal_uInt8 nLast = 0; + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + { + nLast += *pt++; + SetPixel(nY, nx, nLast); + } } - } - else - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + else { - SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax )); + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + { + SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax )); + } } } } - } - break; - - case 7 : - case 6 : - case 5 : - case 4 : - case 3 : - case 2 : - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + break; + + case 7 : + case 6 : + case 5 : + case 4 : + case 3 : + case 2 : { - nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax; - SetPixel(nY, nx, static_cast<sal_uInt8>(nVal)); + for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) + { + nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax; + SetPixel(nY, nx, static_cast<sal_uInt8>(nVal)); + } } - } - break; + break; - case 1 : - { - sal_uInt32 nByteCount = nImageWidth >> 3; + case 1 : + { + sal_uInt32 nByteCount = nImageWidth >> 3; - sal_uInt32 nBytesNeeded = nByteCount; - if (nImageWidth & 7) - ++nBytesNeeded; - if (pt + nBytesNeeded > ptend) - return false; + sal_uInt32 nBytesNeeded = nByteCount; + if (nImageWidth & 7) + ++nBytesNeeded; + if (pt + nBytesNeeded > ptend) + return false; - if ( bByteSwap ) - { - sal_Int32 nx = 0; - while (nByteCount--) + if ( bByteSwap ) { - nByteVal = *pt++; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal); - } - if ( nImageWidth & 7 ) - { - nByteVal = *pt++; - while ( nx < nImageWidth ) + sal_Int32 nx = 0; + while (nByteCount--) { + nByteVal = *pt++; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; SetPixel(nY, nx++, nByteVal & 1); nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, nx++, nByteVal); + } + if ( nImageWidth & 7 ) + { + nByteVal = *pt++; + while ( nx < nImageWidth ) + { + SetPixel(nY, nx++, nByteVal & 1); + nByteVal >>= 1; + } } } - } - else - { - sal_Int32 nx = 7; - while (nByteCount--) - { - nByteVal = *pt++; - SetPixel(nY, nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal); - nx += 15; - } - if ( nImageWidth & 7 ) + else { - nx -= 7; - nByteVal = *pt++; - nShift = 7; - while ( nx < nImageWidth ) + sal_Int32 nx = 7; + while (nByteCount--) { - SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1); + nByteVal = *pt++; + SetPixel(nY, nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal & 1); + nByteVal >>= 1; + SetPixel(nY, --nx, nByteVal); + nx += 15; + } + if ( nImageWidth & 7 ) + { + nx -= 7; + nByteVal = *pt++; + nShift = 7; + while ( nx < nImageWidth ) + { + SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1); + } } } } - } - break; + break; - default : - return false; + default : + return false; + } } } }