18void combineScanlineChannels(
Scanline pColorScanline,
Scanline pAlphaScanline,
19 std::vector<std::remove_pointer_t<Scanline>>& pResult,
20 sal_uInt32 nBitmapWidth,
int colorType)
22 if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
26 pResult[
i * 2] = *pColorScanline++;
27 pResult[
i * 2 + 1] = *pAlphaScanline++;
34 pResult[
i * 4] = *pColorScanline++;
35 pResult[
i * 4 + 1] = *pColorScanline++;
36 pResult[
i * 4 + 2] = *pColorScanline++;
37 pResult[
i * 4 + 3] = *pAlphaScanline++;
44static void lclWriteStream(png_structp pPng, png_bytep pData, png_size_t pDataSize)
46 png_voidp pIO = png_get_io_ptr(pPng);
55 if (nBytesWritten != pDataSize)
56 png_error(pPng,
"Write Error");
60 bool bInterlaced,
bool bTranslucent,
61 const std::vector<PngChunk>& aAdditionalChunks)
66 png_structp pPng = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
71 png_infop pInfo = png_create_info_struct(pPng);
74 png_destroy_write_struct(&pPng,
nullptr);
86 aBitmapEx = rBitmapEx;
100 if (setjmp(png_jmpbuf(pPng)))
103 pAlphaAccess.
reset();
104 png_destroy_read_struct(&pPng, &pInfo,
nullptr);
116 bool bCombineChannels =
false;
135 switch (eScanlineFormat)
139 colorType = PNG_COLOR_TYPE_PALETTE;
146 colorType = PNG_COLOR_TYPE_PALETTE;
149 colorType = PNG_COLOR_TYPE_GRAY;
152 colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
153 bCombineChannels =
true;
166 colorType = PNG_COLOR_TYPE_RGB;
170 colorType = PNG_COLOR_TYPE_RGBA;
171 bCombineChannels =
true;
182 colorType = PNG_COLOR_TYPE_RGBA;
199 png_set_pHYs(pPng, pInfo, nPrefSizeX, nPrefSizeY, 1);
203 png_set_compression_level(pPng, nCompressionLevel);
205 int interlaceType = bInterlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
206 int compressionType = PNG_COMPRESSION_TYPE_DEFAULT;
207 int filterMethod = PNG_FILTER_TYPE_DEFAULT;
210 if (colorType == PNG_COLOR_TYPE_PALETTE)
215 std::unique_ptr<png_color[]> aPngPaletteArray(
new png_color[nEntryCount * 3]);
216 for (sal_uInt16
i = 0;
i < nEntryCount;
i++)
218 aPngPaletteArray[
i].red = aBitmapPalette[
i].GetRed();
219 aPngPaletteArray[
i].green = aBitmapPalette[
i].GetGreen();
220 aPngPaletteArray[
i].blue = aBitmapPalette[
i].GetBlue();
223 png_set_PLTE(pPng, pInfo, aPngPaletteArray.get(), nEntryCount);
226 png_set_IHDR(pPng, pInfo, aSize.
Width(), aSize.
Height(), bitDepth, colorType, interlaceType,
227 compressionType, filterMethod);
229 png_write_info(pPng, pInfo);
231 int nNumberOfPasses = 1;
237 for (
int nPass = 0; nPass < nNumberOfPasses; nPass++)
242 Scanline pFinalPointer = pSourcePointer;
243 std::vector<std::remove_pointer_t<Scanline>> aCombinedChannels;
244 if (bCombineChannels)
248 aCombinedChannels.resize(
nBitmapWidth * png_get_channels(pPng, pInfo));
250 if (!pSourcePointer || !pAlphaPointer)
253 combineScanlineChannels(pSourcePointer, pAlphaPointer, aCombinedChannels,
255 pFinalPointer = aCombinedChannels.data();
257 png_write_row(pPng, pFinalPointer);
262 if (!aAdditionalChunks.empty())
264 for (
const auto& aChunk : aAdditionalChunks)
266 png_write_chunk(pPng, aChunk.name.data(), aChunk.data.data(), aChunk.size);
270 png_write_end(pPng, pInfo);
272 png_destroy_write_struct(&pPng, &pInfo);
279 for (
auto const& rValue : rParameters)
281 if (rValue.Name ==
"Compression")
283 else if (rValue.Name ==
"Interlaced")
285 else if (rValue.Name ==
"Translucent")
288 rValue.Value >>= nTmp;
292 else if (rValue.Name ==
"AdditionalChunks")
294 css::uno::Sequence<css::beans::PropertyValue> aAdditionalChunkSequence;
295 if (rValue.Value >>= aAdditionalChunkSequence)
297 for (
const auto& rAdditionalChunk : std::as_const(aAdditionalChunkSequence))
299 if (rAdditionalChunk.Name.getLength() == 4)
302 for (sal_Int32 k = 0; k < 4; k++)
304 aChunk.
name[k] =
static_cast<sal_uInt8>(rAdditionalChunk.Name[k]);
306 aChunk.
name[4] =
'\0';
308 css::uno::Sequence<sal_Int8> aByteSeq;
309 if (rAdditionalChunk.Value >>= aByteSeq)
311 sal_uInt32 nChunkSize = aByteSeq.getLength();
312 aChunk.
size = nChunkSize;
315 const sal_Int8* pSource = aByteSeq.getConstArray();
316 std::vector<sal_uInt8>
aData(pSource, pSource + nChunkSize);
330 , mnCompressionLevel(6)
331 , mbInterlaced(false)
332 , mbTranslucent(true)
const AlphaMask & GetAlphaMask() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const MapMode & GetPrefMapMode() const
const Size & GetPrefSize() const
const Size & GetSizePixel() const
tools::Long Height() const
tools::Long Width() const
const BitmapPalette & GetPalette() const
ScanlineFormat GetScanlineFormat() const
sal_uInt16 GetEntryCount() const
Scanline GetScanline(tools::Long nY) const
bool HasGreyPalette8Bit() const
vcl::ScopedBitmapAccess< BitmapReadAccess, Bitmap, &Bitmap::AcquireReadAccess > ScopedReadAccess
vcl::PixelFormat getPixelFormat() const
MapUnit GetMapUnit() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
std::vector< PngChunk > maAdditionalChunks
void setParameters(css::uno::Sequence< css::beans::PropertyValue > const &rParameters)
bool write(const BitmapEx &rBitmap)
sal_Int32 mnCompressionLevel
PngImageWriter(SvStream &rStream)
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
const sal_Int32 nBitmapWidth
bool convertBitmap32To24Plus8(BitmapEx const &rInput, BitmapEx &rResult)
static bool pngWrite(SvStream &rStream, const BitmapEx &rBitmapEx, int nCompressionLevel, bool bInterlaced, bool bTranslucent, const std::vector< PngChunk > &aAdditionalChunks)
static void lclWriteStream(png_structp pPng, png_bytep pData, png_size_t pDataSize)
std::array< uint8_t, 5 > name
std::vector< sal_uInt8 > data