19 std::vector<std::remove_pointer_t<Scanline>>& pResult,
20 sal_uInt32 nBitmapWidth)
24 pResult[
i * 4] = *pRGBScanline++;
25 pResult[
i * 4 + 1] = *pRGBScanline++;
26 pResult[
i * 4 + 2] = *pRGBScanline++;
27 pResult[
i * 4 + 3] = *pAlphaScanline++;
34static void lclWriteStream(png_structp pPng, png_bytep pData, png_size_t pDataSize)
36 png_voidp pIO = png_get_io_ptr(pPng);
45 if (nBytesWritten != pDataSize)
46 png_error(pPng,
"Write Error");
50 bool bInterlaced,
bool bTranslucent,
51 const std::vector<PngChunk>& aAdditionalChunks)
53 if (rBitmapEx.
IsAlpha() && !bTranslucent)
58 png_structp pPng = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
63 png_infop pInfo = png_create_info_struct(pPng);
66 png_destroy_write_struct(&pPng,
nullptr);
78 aBitmapEx = rBitmapEx;
86 if (setjmp(png_jmpbuf(pPng)))
90 png_destroy_read_struct(&pPng, &pInfo,
nullptr);
101 bool bCombineChannels =
false;
119 switch (eScanlineFormat)
124 colorType = PNG_COLOR_TYPE_PALETTE;
131 colorType = PNG_COLOR_TYPE_PALETTE;
133 colorType = PNG_COLOR_TYPE_GRAY;
144 colorType = PNG_COLOR_TYPE_RGB;
148 colorType = PNG_COLOR_TYPE_RGBA;
149 bCombineChannels =
true;
160 colorType = PNG_COLOR_TYPE_RGBA;
175 png_set_pHYs(pPng, pInfo, nPrefSizeX, nPrefSizeY, 1);
178 png_set_compression_level(pPng, nCompressionLevel);
180 int interlaceType = bInterlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
181 int compressionType = PNG_COMPRESSION_TYPE_DEFAULT;
182 int filterMethod = PNG_FILTER_TYPE_DEFAULT;
185 if (colorType == PNG_COLOR_TYPE_PALETTE)
190 std::unique_ptr<png_color[]> aPngPaletteArray(
new png_color[nEntryCount * 3]);
191 for (sal_uInt16
i = 0;
i < nEntryCount;
i++)
193 aPngPaletteArray[
i].red = aBitmapPalette[
i].GetRed();
194 aPngPaletteArray[
i].green = aBitmapPalette[
i].GetGreen();
195 aPngPaletteArray[
i].blue = aBitmapPalette[
i].GetBlue();
198 png_set_PLTE(pPng, pInfo, aPngPaletteArray.get(), nEntryCount);
201 png_set_IHDR(pPng, pInfo, aSize.
Width(), aSize.
Height(), bitDepth, colorType, interlaceType,
202 compressionType, filterMethod);
204 png_write_info(pPng, pInfo);
206 int nNumberOfPasses = 1;
212 for (
int nPass = 0; nPass < nNumberOfPasses; nPass++)
217 Scanline pFinalPointer = pSourcePointer;
218 std::vector<std::remove_pointer_t<Scanline>> aCombinedChannels;
219 if (bCombineChannels)
225 if (!pSourcePointer || !pAlphaPointer)
228 combineScanlineChannels(pSourcePointer, pAlphaPointer, aCombinedChannels,
230 pFinalPointer = aCombinedChannels.data();
232 png_set_invert_alpha(pPng);
234 png_write_row(pPng, pFinalPointer);
239 if (!aAdditionalChunks.empty())
241 for (
const auto& aChunk : aAdditionalChunks)
243 png_write_chunk(pPng, aChunk.name.data(), aChunk.data.data(), aChunk.size);
247 png_write_end(pPng, pInfo);
249 png_destroy_write_struct(&pPng, &pInfo);
256 for (
auto const& rValue : rParameters)
258 if (rValue.Name ==
"Compression")
260 else if (rValue.Name ==
"Interlaced")
262 else if (rValue.Name ==
"Translucent")
265 rValue.Value >>= nTmp;
269 else if (rValue.Name ==
"AdditionalChunks")
271 css::uno::Sequence<css::beans::PropertyValue> aAdditionalChunkSequence;
272 if (rValue.Value >>= aAdditionalChunkSequence)
274 for (
const auto& rAdditionalChunk : std::as_const(aAdditionalChunkSequence))
276 if (rAdditionalChunk.Name.getLength() == 4)
279 for (sal_Int32 k = 0; k < 4; k++)
281 aChunk.
name[k] =
static_cast<sal_uInt8>(rAdditionalChunk.Name[k]);
283 aChunk.
name[4] =
'\0';
285 css::uno::Sequence<sal_Int8> aByteSeq;
286 if (rAdditionalChunk.Value >>= aByteSeq)
288 sal_uInt32 nChunkSize = aByteSeq.getLength();
289 aChunk.
size = nChunkSize;
292 const sal_Int8* pSource = aByteSeq.getConstArray();
293 std::vector<sal_uInt8>
aData(pSource, pSource + nChunkSize);
307 , mnCompressionLevel(6)
308 , mbInterlaced(false)
309 , 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