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)
63 if (rBitmapEx.
IsAlpha() && !bTranslucent)
68 png_structp pPng = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
73 png_infop pInfo = png_create_info_struct(pPng);
76 png_destroy_write_struct(&pPng,
nullptr);
88 aBitmapEx = rBitmapEx;
96 if (setjmp(png_jmpbuf(pPng)))
100 png_destroy_read_struct(&pPng, &pInfo,
nullptr);
111 bool bCombineChannels =
false;
129 switch (eScanlineFormat)
134 colorType = PNG_COLOR_TYPE_PALETTE;
141 colorType = PNG_COLOR_TYPE_PALETTE;
144 colorType = PNG_COLOR_TYPE_GRAY;
147 colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
148 bCombineChannels =
true;
161 colorType = PNG_COLOR_TYPE_RGB;
165 colorType = PNG_COLOR_TYPE_RGBA;
166 bCombineChannels =
true;
177 colorType = PNG_COLOR_TYPE_RGBA;
194 png_set_pHYs(pPng, pInfo, nPrefSizeX, nPrefSizeY, 1);
198 png_set_compression_level(pPng, nCompressionLevel);
200 int interlaceType = bInterlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
201 int compressionType = PNG_COMPRESSION_TYPE_DEFAULT;
202 int filterMethod = PNG_FILTER_TYPE_DEFAULT;
205 if (colorType == PNG_COLOR_TYPE_PALETTE)
210 std::unique_ptr<png_color[]> aPngPaletteArray(
new png_color[nEntryCount * 3]);
211 for (sal_uInt16
i = 0;
i < nEntryCount;
i++)
213 aPngPaletteArray[
i].red = aBitmapPalette[
i].GetRed();
214 aPngPaletteArray[
i].green = aBitmapPalette[
i].GetGreen();
215 aPngPaletteArray[
i].blue = aBitmapPalette[
i].GetBlue();
218 png_set_PLTE(pPng, pInfo, aPngPaletteArray.get(), nEntryCount);
221 png_set_IHDR(pPng, pInfo, aSize.
Width(), aSize.
Height(), bitDepth, colorType, interlaceType,
222 compressionType, filterMethod);
224 png_write_info(pPng, pInfo);
226 int nNumberOfPasses = 1;
232 for (
int nPass = 0; nPass < nNumberOfPasses; nPass++)
237 Scanline pFinalPointer = pSourcePointer;
238 std::vector<std::remove_pointer_t<Scanline>> aCombinedChannels;
239 if (bCombineChannels)
243 aCombinedChannels.resize(
nBitmapWidth * png_get_channels(pPng, pInfo));
245 if (!pSourcePointer || !pAlphaPointer)
248 combineScanlineChannels(pSourcePointer, pAlphaPointer, aCombinedChannels,
250 pFinalPointer = aCombinedChannels.data();
252 png_set_invert_alpha(pPng);
254 png_write_row(pPng, pFinalPointer);
259 if (!aAdditionalChunks.empty())
261 for (
const auto& aChunk : aAdditionalChunks)
263 png_write_chunk(pPng, aChunk.name.data(), aChunk.data.data(), aChunk.size);
267 png_write_end(pPng, pInfo);
269 png_destroy_write_struct(&pPng, &pInfo);
276 for (
auto const& rValue : rParameters)
278 if (rValue.Name ==
"Compression")
280 else if (rValue.Name ==
"Interlaced")
282 else if (rValue.Name ==
"Translucent")
285 rValue.Value >>= nTmp;
289 else if (rValue.Name ==
"AdditionalChunks")
291 css::uno::Sequence<css::beans::PropertyValue> aAdditionalChunkSequence;
292 if (rValue.Value >>= aAdditionalChunkSequence)
294 for (
const auto& rAdditionalChunk : std::as_const(aAdditionalChunkSequence))
296 if (rAdditionalChunk.Name.getLength() == 4)
299 for (sal_Int32 k = 0; k < 4; k++)
301 aChunk.
name[k] =
static_cast<sal_uInt8>(rAdditionalChunk.Name[k]);
303 aChunk.
name[4] =
'\0';
305 css::uno::Sequence<sal_Int8> aByteSeq;
306 if (rAdditionalChunk.Value >>= aByteSeq)
308 sal_uInt32 nChunkSize = aByteSeq.getLength();
309 aChunk.
size = nChunkSize;
312 const sal_Int8* pSource = aByteSeq.getConstArray();
313 std::vector<sal_uInt8>
aData(pSource, pSource + nChunkSize);
327 , mnCompressionLevel(6)
328 , mbInterlaced(false)
329 , 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