summaryrefslogtreecommitdiff
path: root/vcl/source/filter/png/PngImageReader.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/filter/png/PngImageReader.cxx')
-rw-r--r--vcl/source/filter/png/PngImageReader.cxx164
1 files changed, 107 insertions, 57 deletions
diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx
index b3a2265c23bf..898ef74d5836 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -21,6 +21,8 @@
#include <svdata.hxx>
#include <salinst.hxx>
+#include "png.hxx"
+
namespace
{
void lclReadStream(png_structp pPng, png_bytep pOutBytes, png_size_t nBytesToRead)
@@ -65,7 +67,10 @@ struct PngDestructor
png_infop pInfo;
};
-bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
+bool reader(SvStream& rStream, BitmapEx& rBitmapEx,
+ GraphicFilterImportFlags nImportFlags = GraphicFilterImportFlags::NONE,
+ BitmapScopedWriteAccess* pAccess = nullptr,
+ AlphaScopedWriteAccess* pAlphaAccess = nullptr)
{
if (!isPng(rStream))
return false;
@@ -89,24 +94,33 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
Bitmap aBitmap;
AlphaMask aBitmapAlpha;
Size prefSize;
- BitmapScopedWriteAccess pWriteAccess;
- AlphaScopedWriteAccess pWriteAccessAlpha;
+ BitmapScopedWriteAccess pWriteAccessInstance;
+ AlphaScopedWriteAccess pWriteAccessAlphaInstance;
std::vector<std::vector<png_byte>> aRows;
+ auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
+ const bool bSupportsBitmap32 = pBackendCapabilities->mbSupportsBitmap32;
+ const bool bOnlyCreateBitmap
+ = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::OnlyCreateBitmap);
+ const bool bUseExistingBitmap
+ = static_cast<bool>(nImportFlags & GraphicFilterImportFlags::UseExistingBitmap);
if (setjmp(png_jmpbuf(pPng)))
{
- // Set the bitmap if it contains something, even on failure. This allows
- // reading images that are only partially broken.
- pWriteAccess.reset();
- pWriteAccessAlpha.reset();
- if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
- rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
- else if (!aBitmap.IsEmpty())
- rBitmapEx = BitmapEx(aBitmap);
- if (!rBitmapEx.IsEmpty() && !prefSize.IsEmpty())
+ if (!bUseExistingBitmap)
{
- rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
- rBitmapEx.SetPrefSize(prefSize);
+ // Set the bitmap if it contains something, even on failure. This allows
+ // reading images that are only partially broken.
+ pWriteAccessInstance.reset();
+ pWriteAccessAlphaInstance.reset();
+ if (!aBitmap.IsEmpty() && !aBitmapAlpha.IsEmpty())
+ rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+ else if (!aBitmap.IsEmpty())
+ rBitmapEx = BitmapEx(aBitmap);
+ if (!rBitmapEx.IsEmpty() && !prefSize.IsEmpty())
+ {
+ rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ rBitmapEx.SetPrefSize(prefSize);
+ }
}
return false;
}
@@ -188,12 +202,60 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
static_cast<sal_Int32>((100000.0 * height) / res_y));
}
- if (colorType == PNG_COLOR_TYPE_RGB)
+ if (!bUseExistingBitmap)
{
- aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N24_BPP);
- pWriteAccess = BitmapScopedWriteAccess(aBitmap);
- if (!pWriteAccess)
+ switch (colorType)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N24_BPP);
+ break;
+ case PNG_COLOR_TYPE_RGBA:
+ if (bSupportsBitmap32)
+ aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N32_BPP);
+ else
+ {
+ aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N24_BPP);
+ aBitmapAlpha = AlphaMask(Size(width, height), nullptr);
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY:
+ aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N8_BPP,
+ &Bitmap::GetGreyPalette(256));
+ break;
+ default:
+ abort();
+ }
+
+ if (bOnlyCreateBitmap)
+ {
+ if (!aBitmapAlpha.IsEmpty())
+ rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+ else
+ rBitmapEx = BitmapEx(aBitmap);
+ if (!prefSize.IsEmpty())
+ {
+ rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ rBitmapEx.SetPrefSize(prefSize);
+ }
+ return true;
+ }
+
+ pWriteAccessInstance = BitmapScopedWriteAccess(aBitmap);
+ if (!pWriteAccessInstance)
return false;
+ if (!aBitmapAlpha.IsEmpty())
+ {
+ pWriteAccessAlphaInstance = AlphaScopedWriteAccess(aBitmapAlpha);
+ if (!pWriteAccessAlphaInstance)
+ return false;
+ }
+ }
+ BitmapScopedWriteAccess& pWriteAccess = pAccess ? *pAccess : pWriteAccessInstance;
+ AlphaScopedWriteAccess& pWriteAccessAlpha
+ = pAlphaAccess ? *pAlphaAccess : pWriteAccessAlphaInstance;
+
+ if (colorType == PNG_COLOR_TYPE_RGB)
+ {
ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
if (eFormat == ScanlineFormat::N24BitTcBgr)
png_set_bgr(pPng);
@@ -206,24 +268,16 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
png_read_row(pPng, pScanline, nullptr);
}
}
- pWriteAccess.reset();
- rBitmapEx = BitmapEx(aBitmap);
}
else if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
{
size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
- if (bUseBitmap32)
+ if (bSupportsBitmap32)
{
- aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N32_BPP);
- pWriteAccess = BitmapScopedWriteAccess(aBitmap);
- if (!pWriteAccess)
- return false;
ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
if (eFormat == ScanlineFormat::N32BitTcAbgr || eFormat == ScanlineFormat::N32BitTcBgra)
- {
png_set_bgr(pPng);
- }
for (int pass = 0; pass < nNumberOfPasses; pass++)
{
@@ -263,22 +317,13 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
}
}
}
- pWriteAccess.reset();
- rBitmapEx = BitmapEx(aBitmap);
}
else
{
- aBitmap = Bitmap(Size(width, height), vcl::PixelFormat::N24_BPP);
- aBitmapAlpha = AlphaMask(Size(width, height), nullptr);
- pWriteAccess = BitmapScopedWriteAccess(aBitmap);
- if (!pWriteAccess)
- return false;
ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
if (eFormat == ScanlineFormat::N24BitTcBgr)
png_set_bgr(pPng);
- pWriteAccessAlpha = AlphaScopedWriteAccess(aBitmapAlpha);
-
aRows = std::vector<std::vector<png_byte>>(height);
for (auto& rRow : aRows)
rRow.resize(aRowSizeBytes, 0);
@@ -302,20 +347,11 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
}
}
}
- pWriteAccess.reset();
- pWriteAccessAlpha.reset();
- rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
}
}
else if (colorType == PNG_COLOR_TYPE_GRAY)
{
- aBitmap
- = Bitmap(Size(width, height), vcl::PixelFormat::N8_BPP, &Bitmap::GetGreyPalette(256));
aBitmap.Erase(COL_WHITE);
- pWriteAccess = BitmapScopedWriteAccess(aBitmap);
- if (!pWriteAccess)
- return false;
-
for (int pass = 0; pass < nNumberOfPasses; pass++)
{
for (png_uint_32 y = 0; y < height; y++)
@@ -324,16 +360,23 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
png_read_row(pPng, pScanline, nullptr);
}
}
- pWriteAccess.reset();
- rBitmapEx = BitmapEx(aBitmap);
}
png_read_end(pPng, pInfo);
- if (!prefSize.IsEmpty())
+ if (!bUseExistingBitmap)
{
- rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
- rBitmapEx.SetPrefSize(prefSize);
+ pWriteAccess.reset();
+ pWriteAccessAlpha.reset();
+ if (!aBitmapAlpha.IsEmpty())
+ rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+ else
+ rBitmapEx = BitmapEx(aBitmap);
+ if (!prefSize.IsEmpty())
+ {
+ rBitmapEx.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ rBitmapEx.SetPrefSize(prefSize);
+ }
}
return true;
@@ -407,13 +450,7 @@ PngImageReader::PngImageReader(SvStream& rStream)
{
}
-bool PngImageReader::read(BitmapEx& rBitmapEx)
-{
- auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
- bool bSupportsBitmap32 = pBackendCapabilities->mbSupportsBitmap32;
-
- return reader(mrStream, rBitmapEx, bSupportsBitmap32);
-}
+bool PngImageReader::read(BitmapEx& rBitmapEx) { return reader(mrStream, rBitmapEx); }
BitmapEx PngImageReader::read()
{
@@ -434,6 +471,19 @@ std::unique_ptr<sal_uInt8[]> PngImageReader::getMicrosoftGifChunk(SvStream& rStr
return chunk;
}
+bool ImportPNG(SvStream& rInputStream, Graphic& rGraphic, GraphicFilterImportFlags nImportFlags,
+ BitmapScopedWriteAccess* pAccess, AlphaScopedWriteAccess* pAlphaAccess)
+{
+ // Creating empty bitmaps should be practically a no-op, and thus thread-safe.
+ BitmapEx bitmap;
+ if (reader(rInputStream, bitmap, nImportFlags, pAccess, pAlphaAccess))
+ {
+ rGraphic = bitmap;
+ return true;
+ }
+ return false;
+}
+
} // namespace vcl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */