summaryrefslogtreecommitdiffstats
path: root/vcl/qa/cppunit/jpeg
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vcl/qa/cppunit/jpeg/JpegReaderTest.cxx202
-rw-r--r--vcl/qa/cppunit/jpeg/JpegWriterTest.cxx117
-rw-r--r--vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpgbin0 -> 1384 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gifbin0 -> 1875 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpegbin0 -> 405 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpegbin0 -> 196 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpegbin0 -> 619 bytes
-rw-r--r--vcl/qa/cppunit/jpeg/data/tdf138950.jpegbin0 -> 60662 bytes
8 files changed, 319 insertions, 0 deletions
diff --git a/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
new file mode 100644
index 000000000..0900c02d4
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <bitmap/BitmapWriteAccess.hxx>
+#include <tools/stream.hxx>
+
+constexpr OUStringLiteral gaDataUrl(u"/vcl/qa/cppunit/jpeg/data/");
+
+class JpegReaderTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+ Graphic loadJPG(const OUString& aURL);
+
+public:
+ void testReadRGB();
+ void testReadGray();
+ void testReadCMYK();
+ void testTdf138950();
+
+ CPPUNIT_TEST_SUITE(JpegReaderTest);
+ CPPUNIT_TEST(testReadRGB);
+ CPPUNIT_TEST(testReadGray);
+ CPPUNIT_TEST(testReadCMYK);
+ CPPUNIT_TEST(testTdf138950);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+static int deltaColor(BitmapColor aColor1, BitmapColor aColor2)
+{
+ int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed());
+ int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen());
+ int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue());
+
+ return std::max(std::max(deltaR, deltaG), deltaB);
+}
+
+static bool checkRect(Bitmap& rBitmap, int aLayerNumber, tools::Long nAreaHeight,
+ tools::Long nAreaWidth, Color aExpectedColor, int nMaxDelta)
+{
+ BitmapScopedWriteAccess pAccess(rBitmap);
+
+ tools::Long nWidth = std::min(nAreaWidth, pAccess->Width());
+ tools::Long nHeight = std::min(nAreaHeight, pAccess->Height());
+
+ tools::Long firstX = 0 + aLayerNumber;
+ tools::Long firstY = 0 + aLayerNumber;
+
+ tools::Long lastX = nWidth - 1 - aLayerNumber;
+ tools::Long lastY = nHeight - 1 - aLayerNumber;
+
+ int delta;
+
+ for (tools::Long y = firstY; y <= lastY; y++)
+ {
+ Color aColorFirst = pAccess->GetPixel(y, firstX);
+ delta = deltaColor(aColorFirst, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+
+ Color aColorLast = pAccess->GetPixel(y, lastX);
+ delta = deltaColor(aColorLast, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+ }
+ for (tools::Long x = firstX; x <= lastX; x++)
+ {
+ Color aColorFirst = pAccess->GetPixel(firstY, x);
+ delta = deltaColor(aColorFirst, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+
+ Color aColorLast = pAccess->GetPixel(lastY, x);
+ delta = deltaColor(aColorLast, aExpectedColor);
+ if (delta > nMaxDelta)
+ return false;
+ }
+ return true;
+}
+
+static int getNumberOfImageComponents(const Graphic& rGraphic)
+{
+ GfxLink aLink = rGraphic.GetGfxLink();
+ SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(aLink.GetData()), aLink.GetDataSize(),
+ StreamMode::READ | StreamMode::WRITE);
+ GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+ CPPUNIT_ASSERT(aDescriptor.Detect(true));
+ return aDescriptor.GetNumberOfImageComponents();
+}
+
+Graphic JpegReaderTest::loadJPG(const OUString& aURL)
+{
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aGraphic;
+}
+
+void JpegReaderTest::testReadRGB()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestRGB.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ int nMaxDelta = 1; // still acceptable color error
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), nMaxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(3, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testReadGray()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestGray.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ aBitmap.Convert(
+ BmpConversion::N24Bit); // convert to 24bit so we don't need to deal with palette
+
+ int nMaxDelta = 1;
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0x36, 0x36, 0x36), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0xb6, 0xb6, 0xb6), nMaxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x12, 0x12, 0x12), nMaxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(1, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testReadCMYK()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"JPEGTestCMYK.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(12), aSize.Height());
+
+ int maxDelta = 1;
+ CPPUNIT_ASSERT(checkRect(aBitmap, 0, 8, 8, Color(0xff, 0xff, 0xff), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), maxDelta));
+ CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), maxDelta));
+
+ CPPUNIT_ASSERT_EQUAL(4, getNumberOfImageComponents(aGraphic));
+}
+
+void JpegReaderTest::testTdf138950()
+{
+ Graphic aGraphic = loadJPG(getFullUrl(u"tdf138950.jpeg"));
+ Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
+ Size aSize = aBitmap.GetSizePixel();
+ CPPUNIT_ASSERT_EQUAL(tools::Long(720), aSize.Width());
+ CPPUNIT_ASSERT_EQUAL(tools::Long(1280), aSize.Height());
+
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ int nBlackCount = 0;
+ for (tools::Long nY = 0; nY < aSize.Height(); ++nY)
+ {
+ for (tools::Long nX = 0; nX < aSize.Width(); ++nX)
+ {
+ const Color aColor = pReadAccess->GetColor(nY, nX);
+ if ((aColor.GetRed() == 0x00) && (aColor.GetGreen() == 0x00)
+ && (aColor.GetBlue() == 0x00))
+ ++nBlackCount;
+ }
+ }
+
+ // Without the fix in place, this test would have failed with
+ // - Expected: 0
+ // - Actual : 921600
+ CPPUNIT_ASSERT_EQUAL(0, nBlackCount);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(JpegReaderTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
new file mode 100644
index 000000000..f9b58c308
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/JpegWriterTest.cxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <unotest/bootstrapfixturebase.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <tools/stream.hxx>
+#include <graphic/GraphicFormatDetector.hxx>
+
+constexpr OUStringLiteral gaDataUrl(u"/vcl/qa/cppunit/jpeg/data/");
+
+class JpegWriterTest : public test::BootstrapFixtureBase
+{
+ OUString getFullUrl(std::u16string_view sFileName)
+ {
+ return m_directories.getURLFromSrc(gaDataUrl) + sFileName;
+ }
+
+ BitmapEx load(const OUString& aURL);
+ BitmapEx roundtripJPG(const BitmapEx& bitmap);
+ BitmapEx roundtripJPG(const OUString& aURL);
+
+public:
+ void testWrite8BitGrayscale();
+ void testWrite8BitNonGrayscale();
+
+ CPPUNIT_TEST_SUITE(JpegWriterTest);
+ CPPUNIT_TEST(testWrite8BitGrayscale);
+ CPPUNIT_TEST(testWrite8BitNonGrayscale);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+BitmapEx JpegWriterTest::load(const OUString& aURL)
+{
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ Graphic aGraphic;
+ SvFileStream aFileStream(aURL, StreamMode::READ);
+ ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aGraphic.GetBitmapEx();
+}
+
+BitmapEx JpegWriterTest::roundtripJPG(const OUString& aURL) { return roundtripJPG(load(aURL)); }
+
+BitmapEx JpegWriterTest::roundtripJPG(const BitmapEx& bitmap)
+{
+ // EXPORT JPEG
+ SvMemoryStream aStream;
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ sal_uInt16 exportFormatJPG = rFilter.GetExportFormatNumberForShortName(JPG_SHORTNAME);
+ Graphic aExportGraphic(bitmap);
+ ErrCode bResult = rFilter.ExportGraphic(aExportGraphic, u"memory", aStream, exportFormatJPG);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ //Detect the magic bytes - we need to be sure the file is actually a JPEG
+ aStream.Seek(0);
+ vcl::GraphicFormatDetector aDetector(aStream, "");
+ CPPUNIT_ASSERT(aDetector.detect());
+ CPPUNIT_ASSERT(aDetector.checkJPG());
+ // IMPORT JPEG
+ aStream.Seek(0);
+ Graphic aImportGraphic;
+ sal_uInt16 importFormatJPG = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
+ bResult = rFilter.ImportGraphic(aImportGraphic, u"memory", aStream, importFormatJPG);
+ CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult);
+ return aImportGraphic.GetBitmapEx();
+}
+
+void JpegWriterTest::testWrite8BitGrayscale()
+{
+ Bitmap bitmap = roundtripJPG(getFullUrl(u"8BitGrayscale.jpg")).GetBitmap();
+ Bitmap::ScopedReadAccess access(bitmap);
+ const ScanlineFormat format = access->GetScanlineFormat();
+ // Check that it's still 8bit grayscale.
+ CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+ CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+ // Check that the content is valid.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+ access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+void JpegWriterTest::testWrite8BitNonGrayscale()
+{
+ Bitmap bitmap = roundtripJPG(getFullUrl(u"8BitNonGrayscale.gif")).GetBitmap();
+ Bitmap::ScopedReadAccess access(bitmap);
+ const ScanlineFormat format = access->GetScanlineFormat();
+ // Check that it's still 8bit grayscale.
+ CPPUNIT_ASSERT_EQUAL(ScanlineFormat::N8BitPal, format);
+ // The original image has grayscale palette, just with entries in a different order.
+ // Do not check for grayscale 8bit, the roundtrip apparently fixes that. What's important
+ // is the content.
+ CPPUNIT_ASSERT(bitmap.HasGreyPaletteAny());
+ // CPPUNIT_ASSERT(bitmap.HasGreyPalette8Bit());
+ // Check that the content is valid.
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(0, access->Width() - 1));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access->GetColor(access->Height() - 1, 0));
+ CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_BLACK),
+ access->GetColor(access->Height() - 1, access->Width() - 1));
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(JpegWriterTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg b/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg
new file mode 100644
index 000000000..91541e4a8
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/8BitGrayscale.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif b/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif
new file mode 100644
index 000000000..295310949
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/8BitNonGrayscale.gif
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg
new file mode 100644
index 000000000..81cca025e
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestCMYK.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg
new file mode 100644
index 000000000..014825f42
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestGray.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg b/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg
new file mode 100644
index 000000000..3cfe1dda2
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/JPEGTestRGB.jpeg
Binary files differ
diff --git a/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg b/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg
new file mode 100644
index 000000000..d0296077c
--- /dev/null
+++ b/vcl/qa/cppunit/jpeg/data/tdf138950.jpeg
Binary files differ