LibreOffice Module vcl (master)  1
pngwrite.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/pngwrite.hxx>
21 #include <vcl/bitmapex.hxx>
22 
23 #include <com/sun/star/beans/PropertyValue.hpp>
24 #include <com/sun/star/uno/Sequence.hxx>
25 
26 #include <limits>
27 #include <rtl/crc.h>
28 #include <tools/zcodec.hxx>
29 #include <tools/stream.hxx>
30 #include <vcl/BitmapReadAccess.hxx>
31 #include <vcl/alpha.hxx>
32 #include <osl/endian.h>
33 #include <memory>
34 #include <vcl/BitmapTools.hxx>
35 
36 #define PNG_DEF_COMPRESSION 6
37 
38 #define PNGCHUNK_IHDR 0x49484452
39 #define PNGCHUNK_PLTE 0x504c5445
40 #define PNGCHUNK_IDAT 0x49444154
41 #define PNGCHUNK_IEND 0x49454e44
42 #define PNGCHUNK_pHYs 0x70485973
43 
44 namespace vcl
45 {
47 {
48 public:
49  PNGWriterImpl(const BitmapEx& BmpEx,
50  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData);
51 
52  bool Write(SvStream& rOutStream);
53 
54  std::vector<vcl::PNGWriter::ChunkData>& GetChunks() { return maChunkSeq; }
55 
56 private:
57  std::vector<vcl::PNGWriter::ChunkData> maChunkSeq;
58 
59  sal_Int32 mnCompLevel;
60  sal_Int32 mnInterlaced;
61  sal_uInt32 mnMaxChunkSize;
62  bool mbStatus;
63 
67 
68  std::unique_ptr<sal_uInt8[]>
69  mpDeflateInBuf; // as big as the size of a scanline + alphachannel + 1
70  std::unique_ptr<sal_uInt8[]> mpPreviousScan; // as big as mpDeflateInBuf
71  std::unique_ptr<sal_uInt8[]> mpCurrentScan;
73 
77  sal_uInt8 mnFilterType; // 0 or 4;
78  sal_uLong mnBBP; // bytes per pixel ( needed for filtering )
80 
81  void ImplWritepHYs(const BitmapEx& rBitmapEx);
82  void ImplWriteIDAT();
83  sal_uLong ImplGetFilter(sal_uLong nY, sal_uLong nXStart = 0, sal_uLong nXAdd = 1);
85  bool ImplWriteHeader();
86  void ImplWritePalette();
87  void ImplOpenChunk(sal_uLong nChunkType);
88  void ImplWriteChunk(sal_uInt8 nNumb);
89  void ImplWriteChunk(sal_uInt32 nNumb);
90  void ImplWriteChunk(unsigned char const* pSource, sal_uInt32 nDatSize);
91 };
92 
94  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData)
95  : mnCompLevel(PNG_DEF_COMPRESSION)
96  , mnInterlaced(0)
97  , mnMaxChunkSize(0)
98  , mbStatus(true)
99  , mpMaskAccess(nullptr)
100  , mnDeflateInSize(0)
101  , mnWidth(0)
102  , mnHeight(0)
103  , mnBitsPerPixel(0)
104  , mnFilterType(0)
105  , mnBBP(0)
106  , mbTrueAlpha(false)
107 {
108  if (rBitmapEx.IsEmpty())
109  return;
110 
111  BitmapEx aBitmapEx;
112 
114  {
115  if (!vcl::bitmap::convertBitmap32To24Plus8(rBitmapEx, aBitmapEx))
116  return;
117  }
118  else
119  {
120  aBitmapEx = rBitmapEx;
121  }
122 
123  Bitmap aBmp(aBitmapEx.GetBitmap());
124 
125  mnMaxChunkSize = std::numeric_limits<sal_uInt32>::max();
126 
127  if (pFilterData)
128  {
129  for (const auto& rPropVal : *pFilterData)
130  {
131  if (rPropVal.Name == "Compression")
132  rPropVal.Value >>= mnCompLevel;
133  else if (rPropVal.Name == "Interlaced")
134  rPropVal.Value >>= mnInterlaced;
135  else if (rPropVal.Name == "MaxChunkSize")
136  {
137  sal_Int32 nVal = 0;
138  if (rPropVal.Value >>= nVal)
139  mnMaxChunkSize = static_cast<sal_uInt32>(nVal);
140  }
141  }
142  }
143  mnBitsPerPixel = sal_uInt8(vcl::pixelFormatBitCount(aBmp.getPixelFormat()));
144 
145  if (aBitmapEx.IsAlpha())
146  {
147  if (mnBitsPerPixel <= 8)
148  {
149  aBmp.Convert(BmpConversion::N24Bit);
150  mnBitsPerPixel = 24;
151  }
152 
153  mpAccess = Bitmap::ScopedReadAccess(aBmp); // true RGB with alphachannel
154  if (mpAccess)
155  {
156  mbTrueAlpha = true;
157  AlphaMask aMask(aBitmapEx.GetAlpha());
158  mpMaskAccess = aMask.AcquireReadAccess();
159  if (mpMaskAccess)
160  {
161  if (ImplWriteHeader())
162  {
163  ImplWritepHYs(aBitmapEx);
164  ImplWriteIDAT();
165  }
166  aMask.ReleaseAccess(mpMaskAccess);
167  mpMaskAccess = nullptr;
168  }
169  else
170  {
171  mbStatus = false;
172  }
173  mpAccess.reset();
174  }
175  else
176  {
177  mbStatus = false;
178  }
179  }
180  else
181  {
182  mpAccess = Bitmap::ScopedReadAccess(aBmp); // palette + RGB without alphachannel
183  if (mpAccess)
184  {
185  if (ImplWriteHeader())
186  {
187  ImplWritepHYs(aBitmapEx);
188  if (mpAccess->HasPalette())
190 
191  ImplWriteIDAT();
192  }
193  mpAccess.reset();
194  }
195  else
196  {
197  mbStatus = false;
198  }
199  }
200 
201  if (mbStatus)
202  {
203  ImplOpenChunk(PNGCHUNK_IEND); // create an IEND chunk
204  }
205 }
206 
208 {
209  /* png signature is always an array of 8 bytes */
210  SvStreamEndian nOldMode = rOStm.GetEndian();
211  rOStm.SetEndian(SvStreamEndian::BIG);
212  rOStm.WriteUInt32(0x89504e47);
213  rOStm.WriteUInt32(0x0d0a1a0a);
214 
215  for (auto const& chunk : maChunkSeq)
216  {
217  sal_uInt32 nType = chunk.nType;
218 #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
219  nType = OSL_SWAPDWORD(nType);
220 #endif
221  sal_uInt32 nCRC = rtl_crc32(0, &nType, 4);
222  sal_uInt32 nDataSize = chunk.aData.size();
223  if (nDataSize)
224  nCRC = rtl_crc32(nCRC, chunk.aData.data(), nDataSize);
225  rOStm.WriteUInt32(nDataSize);
226  rOStm.WriteUInt32(chunk.nType);
227  if (nDataSize)
228  rOStm.WriteBytes(chunk.aData.data(), nDataSize);
229  rOStm.WriteUInt32(nCRC);
230  }
231  rOStm.SetEndian(nOldMode);
232  return mbStatus;
233 }
234 
236 {
238  mnWidth = mpAccess->Width();
239  ImplWriteChunk(sal_uInt32(mnWidth));
240  mnHeight = mpAccess->Height();
241  ImplWriteChunk(sal_uInt32(mnHeight));
242 
244  {
245  sal_uInt8 nBitDepth = mnBitsPerPixel;
246  if (mnBitsPerPixel <= 8)
247  mnFilterType = 0;
248  else
249  mnFilterType = 4;
250 
251  sal_uInt8 nColorType = 2; // colortype:
252 
253  // bit 0 -> palette is used
254  if (mpAccess->HasPalette()) // bit 1 -> color is used
255  nColorType |= 1; // bit 2 -> alpha channel is used
256  else
257  nBitDepth /= 3;
258 
259  if (mpMaskAccess)
260  nColorType |= 4;
261 
262  ImplWriteChunk(nBitDepth);
263  ImplWriteChunk(nColorType); // colortype
264  ImplWriteChunk(static_cast<sal_uInt8>(0)); // compression type
265  ImplWriteChunk(static_cast<sal_uInt8>(0)); // filter type - is not supported in this version
266  ImplWriteChunk(static_cast<sal_uInt8>(mnInterlaced)); // interlace type
267  }
268  else
269  {
270  mbStatus = false;
271  }
272  return mbStatus;
273 }
274 
276 {
278  std::unique_ptr<sal_uInt8[]> pTempBuf(new sal_uInt8[nCount * 3]);
279  sal_uInt8* pTmp = pTempBuf.get();
280 
282 
283  for (sal_uLong i = 0; i < nCount; i++)
284  {
285  const BitmapColor& rColor = mpAccess->GetPaletteColor(i);
286  *pTmp++ = rColor.GetRed();
287  *pTmp++ = rColor.GetGreen();
288  *pTmp++ = rColor.GetBlue();
289  }
290  ImplWriteChunk(pTempBuf.get(), nCount * 3);
291 }
292 
294 {
295  if (rBmpEx.GetPrefMapMode().GetMapUnit() != MapUnit::Map100thMM)
296  return;
297 
298  Size aPrefSize(rBmpEx.GetPrefSize());
299 
300  if (aPrefSize.Width() && aPrefSize.Height() && mnWidth && mnHeight)
301  {
303  sal_uInt32 nPrefSizeX = static_cast<sal_uInt32>(
304  100000.0 / (static_cast<double>(aPrefSize.Width()) / mnWidth) + 0.5);
305  sal_uInt32 nPrefSizeY = static_cast<sal_uInt32>(
306  100000.0 / (static_cast<double>(aPrefSize.Height()) / mnHeight) + 0.5);
307  ImplWriteChunk(nPrefSizeX);
308  ImplWriteChunk(nPrefSizeY);
309  ImplWriteChunk(sal_uInt8(1)); // nMapUnit
310  }
311 }
312 
314 {
316 
317  if (mpMaskAccess)
318  mnDeflateInSize += 8;
319 
320  mnBBP = (mnDeflateInSize + 7) >> 3;
321 
322  mnDeflateInSize = mnBBP * mnWidth + 1;
323 
325 
326  if (mnFilterType) // using filter type 4 we need memory for the scanline 3 times
327  {
328  mpPreviousScan.reset(new sal_uInt8[mnDeflateInSize]);
329  mpCurrentScan.reset(new sal_uInt8[mnDeflateInSize]);
331  }
333  SvMemoryStream aOStm;
334  if (mnInterlaced == 0)
335  {
336  for (sal_uLong nY = 0; nY < mnHeight; nY++)
337  {
338  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY));
339  }
340  }
341  else
342  {
343  // interlace mode
344  sal_uLong nY;
345  for (nY = 0; nY < mnHeight; nY += 8) // pass 1
346  {
347  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 8));
348  }
350 
351  for (nY = 0; nY < mnHeight; nY += 8) // pass 2
352  {
353  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 4, 8));
354  }
356 
357  if (mnHeight >= 5) // pass 3
358  {
359  for (nY = 4; nY < mnHeight; nY += 8)
360  {
361  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 4));
362  }
364  }
365 
366  for (nY = 0; nY < mnHeight; nY += 4) // pass 4
367  {
368  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 2, 4));
369  }
371 
372  if (mnHeight >= 3) // pass 5
373  {
374  for (nY = 2; nY < mnHeight; nY += 4)
375  {
376  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 2));
377  }
379  }
380 
381  for (nY = 0; nY < mnHeight; nY += 2) // pass 6
382  {
383  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 1, 2));
384  }
386 
387  if (mnHeight >= 2) // pass 7
388  {
389  for (nY = 1; nY < mnHeight; nY += 2)
390  {
391  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY));
392  }
393  }
394  }
396 
397  if (mnFilterType) // using filter type 4 we need memory for the scanline 3 times
398  {
399  mpCurrentScan.reset();
400  mpPreviousScan.reset();
401  }
402  mpDeflateInBuf.reset();
403 
404  sal_uInt32 nIDATSize = aOStm.Tell();
405  sal_uInt32 nBytes, nBytesToWrite = nIDATSize;
406  while (nBytesToWrite)
407  {
408  nBytes = nBytesToWrite <= mnMaxChunkSize ? nBytesToWrite : mnMaxChunkSize;
411  const_cast<unsigned char*>(static_cast<unsigned char const*>(aOStm.GetData()))
412  + (nIDATSize - nBytesToWrite),
413  nBytes);
414  nBytesToWrite -= nBytes;
415  }
416 }
417 
418 // ImplGetFilter writes the complete Scanline (nY) - in interlace mode the parameter nXStart and nXAdd
419 // appends to the currently used pass
420 // the complete size of scanline will be returned - in interlace mode zero is possible!
421 
423 {
424  sal_uInt8* pDest;
425 
426  if (mnFilterType)
427  pDest = mpCurrentScan.get();
428  else
429  pDest = mpDeflateInBuf.get();
430 
431  if (nXStart < mnWidth)
432  {
433  *pDest++ = mnFilterType; // in this version the filter type is either 0 or 4
434 
435  if (mpAccess
436  ->HasPalette()) // alphachannel is not allowed by pictures including palette entries
437  {
438  switch (mnBitsPerPixel)
439  {
440  case 1:
441  {
442  Scanline pScanline = mpAccess->GetScanline(nY);
443  sal_uLong nX, nXIndex;
444  for (nX = nXStart, nXIndex = 0; nX < mnWidth; nX += nXAdd, nXIndex++)
445  {
446  sal_uLong nShift = (nXIndex & 7) ^ 7;
447  if (nShift == 7)
448  *pDest = mpAccess->GetIndexFromData(pScanline, nX) << nShift;
449  else if (nShift == 0)
450  *pDest++ |= mpAccess->GetIndexFromData(pScanline, nX) << nShift;
451  else
452  *pDest |= mpAccess->GetIndexFromData(pScanline, nX) << nShift;
453  }
454  if ((nXIndex & 7) != 0)
455  pDest++; // byte is not completely used, so the bufferpointer is to correct
456  }
457  break;
458 
459  case 4:
460  {
461  Scanline pScanline = mpAccess->GetScanline(nY);
462  sal_uLong nX, nXIndex;
463  for (nX = nXStart, nXIndex = 0; nX < mnWidth; nX += nXAdd, nXIndex++)
464  {
465  if (nXIndex & 1)
466  *pDest++ |= mpAccess->GetIndexFromData(pScanline, nX);
467  else
468  *pDest = mpAccess->GetIndexFromData(pScanline, nX) << 4;
469  }
470  if (nXIndex & 1)
471  pDest++;
472  }
473  break;
474 
475  case 8:
476  {
477  Scanline pScanline = mpAccess->GetScanline(nY);
478  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
479  {
480  *pDest++ = mpAccess->GetIndexFromData(pScanline, nX);
481  }
482  }
483  break;
484 
485  default:
486  mbStatus = false;
487  break;
488  }
489  }
490  else
491  {
492  if (mpMaskAccess) // mpMaskAccess != NULL -> alphachannel is to create
493  {
494  if (mbTrueAlpha)
495  {
496  Scanline pScanline = mpAccess->GetScanline(nY);
497  Scanline pScanlineMask = mpMaskAccess->GetScanline(nY);
498  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
499  {
500  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
501  *pDest++ = rColor.GetRed();
502  *pDest++ = rColor.GetGreen();
503  *pDest++ = rColor.GetBlue();
504  *pDest++ = 255 - mpMaskAccess->GetIndexFromData(pScanlineMask, nX);
505  }
506  }
507  else
508  {
510  Scanline pScanline = mpAccess->GetScanline(nY);
511  Scanline pScanlineMask = mpMaskAccess->GetScanline(nY);
512 
513  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
514  {
515  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
516  *pDest++ = rColor.GetRed();
517  *pDest++ = rColor.GetGreen();
518  *pDest++ = rColor.GetBlue();
519 
520  if (mpMaskAccess->GetPixelFromData(pScanlineMask, nX) == aTrans)
521  *pDest++ = 0;
522  else
523  *pDest++ = 0xff;
524  }
525  }
526  }
527  else
528  {
529  Scanline pScanline = mpAccess->GetScanline(nY);
530  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
531  {
532  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
533  *pDest++ = rColor.GetRed();
534  *pDest++ = rColor.GetGreen();
535  *pDest++ = rColor.GetBlue();
536  }
537  }
538  }
539  }
540  // filter type4 ( PAETH ) will be used only for 24bit graphics
541  if (mnFilterType)
542  {
543  mnDeflateInSize = pDest - mpCurrentScan.get();
544  pDest = mpDeflateInBuf.get();
545  *pDest++ = 4; // filter type
546 
547  sal_uInt8* p1 = mpCurrentScan.get() + 1; // Current Pixel
548  sal_uInt8* p2 = p1 - mnBBP; // left pixel
549  sal_uInt8* p3 = mpPreviousScan.get(); // upper pixel
550  sal_uInt8* p4 = p3 - mnBBP; // upperleft Pixel;
551 
552  while (pDest < mpDeflateInBuf.get() + mnDeflateInSize)
553  {
554  sal_uLong nb = *p3++;
555  sal_uLong na, nc;
556  if (p2 >= mpCurrentScan.get() + 1)
557  {
558  na = *p2;
559  nc = *p4;
560  }
561  else
562  {
563  na = nc = 0;
564  }
565 
566  tools::Long np = na + nb - nc;
567  tools::Long npa = np - na;
568  tools::Long npb = np - nb;
569  tools::Long npc = np - nc;
570 
571  if (npa < 0)
572  npa = -npa;
573  if (npb < 0)
574  npb = -npb;
575  if (npc < 0)
576  npc = -npc;
577 
578  if (npa <= npb && npa <= npc)
579  *pDest++ = *p1++ - static_cast<sal_uInt8>(na);
580  else if (npb <= npc)
581  *pDest++ = *p1++ - static_cast<sal_uInt8>(nb);
582  else
583  *pDest++ = *p1++ - static_cast<sal_uInt8>(nc);
584 
585  p4++;
586  p2++;
587  }
588  for (tools::Long i = 0; i < static_cast<tools::Long>(mnDeflateInSize - 1); i++)
589  {
591  }
592  }
593  else
594  {
595  mnDeflateInSize = pDest - mpDeflateInBuf.get();
596  }
597  return mnDeflateInSize;
598 }
599 
601 {
602  if (mnFilterType)
603  memset(mpPreviousScan.get(), 0, mnDeflateInSize);
604 }
605 
607 {
608  maChunkSeq.emplace_back();
609  maChunkSeq.back().nType = nChunkType;
610 }
611 
613 {
614  maChunkSeq.back().aData.push_back(nSource);
615 }
616 
617 void PNGWriterImpl::ImplWriteChunk(sal_uInt32 nSource)
618 {
619  vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
620  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 24));
621  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 16));
622  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 8));
623  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource));
624 }
625 
626 void PNGWriterImpl::ImplWriteChunk(unsigned char const* pSource, sal_uInt32 nDatSize)
627 {
628  if (nDatSize)
629  {
630  vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
631  sal_uInt32 nSize = rChunkData.aData.size();
632  rChunkData.aData.resize(nSize + nDatSize);
633  memcpy(&rChunkData.aData[nSize], pSource, nDatSize);
634  }
635 }
636 
638  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData)
639  : mpImpl(new vcl::PNGWriterImpl(rBmpEx, pFilterData))
640 {
641 }
642 
644 
645 bool PNGWriter::Write(SvStream& rStream) { return mpImpl->Write(rStream); }
646 
647 std::vector<vcl::PNGWriter::ChunkData>& PNGWriter::GetChunks() { return mpImpl->GetChunks(); }
648 
649 } // namespace vcl
650 
651 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mnHeight
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
Bitmap::ScopedReadAccess mpAccess
Definition: pngwrite.cxx:64
tools::Long Height() const
bool Write(SvStream &rOutStream)
Definition: pngwrite.cxx:207
sal_uInt8 GetRed() const
#define PNGCHUNK_IHDR
Definition: pngwrite.cxx:38
void ImplWritepHYs(const BitmapEx &rBitmapEx)
Definition: pngwrite.cxx:293
const MapMode & GetPrefMapMode() const
Definition: bitmapex.hxx:79
sal_uIntPtr sal_uLong
long Long
#define PNGCHUNK_PLTE
Definition: pngwrite.cxx:39
#define PNGCHUNK_pHYs
Definition: pngwrite.cxx:42
std::vector< vcl::PNGWriter::ChunkData > maChunkSeq
Definition: pngwrite.cxx:57
sal_Int32 mnCompLevel
Definition: pngwrite.cxx:59
sal_uLong mnHeight
Definition: pngwrite.cxx:75
void ImplWriteChunk(sal_uInt8 nNumb)
Definition: pngwrite.cxx:612
sal_uInt8 mnFilterType
Definition: pngwrite.cxx:77
const std::unique_ptr< PNGWriterImpl > mpImpl
Definition: pngwrite.hxx:39
bool IsAlpha() const
Definition: BitmapEx.cxx:193
std::unique_ptr< sal_uInt8[]> mpDeflateInBuf
Definition: pngwrite.cxx:69
sal_uLong ImplGetFilter(sal_uLong nY, sal_uLong nXStart=0, sal_uLong nXAdd=1)
Definition: pngwrite.cxx:422
Scanline GetScanline(tools::Long nY) const
const Size & GetPrefSize() const
Definition: bitmapex.hxx:76
int nCount
sal_uLong mnDeflateInSize
Definition: pngwrite.cxx:72
SvStream & WriteUInt32(sal_uInt32 nUInt32)
sal_uInt8 GetBlue() const
PNGWriter(const BitmapEx &, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
Definition: pngwrite.cxx:637
sal_Int32 mnInterlaced
Definition: pngwrite.cxx:60
vcl::ScopedBitmapAccess< BitmapReadAccess, Bitmap,&Bitmap::AcquireReadAccess > ScopedReadAccess
bool IsEmpty() const
Definition: BitmapEx.cxx:177
#define PNGCHUNK_IEND
Definition: pngwrite.cxx:41
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
vcl::PixelFormat getPixelFormat() const
int i
bool HasPalette() const
std::vector< vcl::PNGWriter::ChunkData > & GetChunks()
Definition: pngwrite.cxx:647
sal_uLong mnBBP
Definition: pngwrite.cxx:78
PNGWriterImpl(const BitmapEx &BmpEx, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData)
Definition: pngwrite.cxx:93
void ImplClearFirstScanline()
Definition: pngwrite.cxx:600
std::vector< vcl::PNGWriter::ChunkData > & GetChunks()
Definition: pngwrite.cxx:54
bool ImplWriteHeader()
Definition: pngwrite.cxx:235
tools::Long Width() const
std::size_t WriteBytes(const void *pData, std::size_t nSize)
void BeginCompression(int nCompressLevel=ZCODEC_DEFAULT_COMPRESSION, bool gzLib=false)
tools::Long EndCompression()
bool Write(SvStream &rStream)
Definition: pngwrite.cxx:645
MapUnit GetMapUnit() const
Definition: mapmod.cxx:138
sal_uInt32 mnMaxChunkSize
Definition: pngwrite.cxx:61
sal_uInt16 GetPaletteEntryCount() const
BitmapReadAccess * mpMaskAccess
Definition: pngwrite.cxx:65
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
sal_uInt8 GetGreen() const
SvStreamEndian GetEndian() const
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:215
#define PNGCHUNK_IDAT
Definition: pngwrite.cxx:40
unsigned char sal_uInt8
#define PNG_DEF_COMPRESSION
Definition: pngwrite.cxx:36
void SetEndian(SvStreamEndian SvStreamEndian)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
sal_uInt8 mnBitsPerPixel
Definition: pngwrite.cxx:76
double mnWidth
bool convertBitmap32To24Plus8(BitmapEx const &rInput, BitmapEx &rResult)
sal_uInt64 Tell() const
QPRO_FUNC_TYPE nType
constexpr sal_uInt16 pixelFormatBitCount(PixelFormat ePixelFormat)
Definition: BitmapTypes.hxx:35
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
void ImplWritePalette()
Definition: pngwrite.cxx:275
SvStreamEndian
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
std::unique_ptr< sal_uInt8[]> mpPreviousScan
Definition: pngwrite.cxx:70
void ImplOpenChunk(sal_uLong nChunkType)
Definition: pngwrite.cxx:606
std::unique_ptr< sal_uInt8[]> mpCurrentScan
Definition: pngwrite.cxx:71
std::vector< sal_uInt8 > aData
Definition: pngwrite.hxx:52
sal_uLong mnWidth
Definition: pngwrite.cxx:74
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
void Write(SvStream &rOStm, const sal_uInt8 *pData, sal_uInt32 nSize)
const void * GetData()