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 #define PNGCHUNK_tRNS 0x74524e53
44 
45 namespace vcl
46 {
48 {
49 public:
50  PNGWriterImpl(const BitmapEx& BmpEx,
51  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData);
52 
53  bool Write(SvStream& rOutStream);
54 
55  std::vector<vcl::PNGWriter::ChunkData>& GetChunks() { return maChunkSeq; }
56 
57 private:
58  std::vector<vcl::PNGWriter::ChunkData> maChunkSeq;
59 
60  sal_Int32 mnCompLevel;
61  sal_Int32 mnInterlaced;
62  sal_uInt32 mnMaxChunkSize;
63  bool mbStatus;
64 
68 
69  std::unique_ptr<sal_uInt8[]>
70  mpDeflateInBuf; // as big as the size of a scanline + alphachannel + 1
71  std::unique_ptr<sal_uInt8[]> mpPreviousScan; // as big as mpDeflateInBuf
72  std::unique_ptr<sal_uInt8[]> mpCurrentScan;
74 
78  sal_uInt8 mnFilterType; // 0 or 4;
79  sal_uLong mnBBP; // bytes per pixel ( needed for filtering )
81 
82  void ImplWritepHYs(const BitmapEx& rBitmapEx);
83  void ImplWriteIDAT();
84  sal_uLong ImplGetFilter(sal_uLong nY, sal_uLong nXStart = 0, sal_uLong nXAdd = 1);
86  void ImplWriteTransparent();
87  bool ImplWriteHeader();
88  void ImplWritePalette();
89  void ImplOpenChunk(sal_uLong nChunkType);
90  void ImplWriteChunk(sal_uInt8 nNumb);
91  void ImplWriteChunk(sal_uInt32 nNumb);
92  void ImplWriteChunk(unsigned char const* pSource, sal_uInt32 nDatSize);
93 };
94 
96  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData)
97  : mnCompLevel(PNG_DEF_COMPRESSION)
98  , mnInterlaced(0)
99  , mnMaxChunkSize(0)
100  , mbStatus(true)
101  , mpMaskAccess(nullptr)
102  , mnDeflateInSize(0)
103  , mnWidth(0)
104  , mnHeight(0)
105  , mnBitsPerPixel(0)
106  , mnFilterType(0)
107  , mnBBP(0)
108  , mbTrueAlpha(false)
109 {
110  if (rBitmapEx.IsEmpty())
111  return;
112 
113  BitmapEx aBitmapEx;
114 
116  {
117  if (!vcl::bitmap::convertBitmap32To24Plus8(rBitmapEx, aBitmapEx))
118  return;
119  }
120  else
121  {
122  aBitmapEx = rBitmapEx;
123  }
124 
125  Bitmap aBmp(aBitmapEx.GetBitmap());
126 
127  mnMaxChunkSize = std::numeric_limits<sal_uInt32>::max();
128 
129  if (pFilterData)
130  {
131  for (const auto& rPropVal : *pFilterData)
132  {
133  if (rPropVal.Name == "Compression")
134  rPropVal.Value >>= mnCompLevel;
135  else if (rPropVal.Name == "Interlaced")
136  rPropVal.Value >>= mnInterlaced;
137  else if (rPropVal.Name == "MaxChunkSize")
138  {
139  sal_Int32 nVal = 0;
140  if (rPropVal.Value >>= nVal)
141  mnMaxChunkSize = static_cast<sal_uInt32>(nVal);
142  }
143  }
144  }
145  mnBitsPerPixel = sal_uInt8(vcl::pixelFormatBitCount(aBmp.getPixelFormat()));
146 
147  if (aBitmapEx.IsTransparent())
148  {
149  if (mnBitsPerPixel <= 8 && aBitmapEx.IsAlpha())
150  {
151  aBmp.Convert(BmpConversion::N24Bit);
152  mnBitsPerPixel = 24;
153  }
154 
155  if (mnBitsPerPixel <= 8) // transparent palette
156  {
157  aBmp.Convert(BmpConversion::N8BitTrans);
158  aBmp.Replace(aBitmapEx.GetMask(), BMP_COL_TRANS);
159  mnBitsPerPixel = 8;
161  if (mpAccess)
162  {
163  if (ImplWriteHeader())
164  {
165  ImplWritepHYs(aBitmapEx);
168  ImplWriteIDAT();
169  }
170  mpAccess.reset();
171  }
172  else
173  {
174  mbStatus = false;
175  }
176  }
177  else
178  {
179  mpAccess = Bitmap::ScopedReadAccess(aBmp); // true RGB with alphachannel
180  if (mpAccess)
181  {
182  mbTrueAlpha = aBitmapEx.IsAlpha();
183  if (mbTrueAlpha)
184  {
185  AlphaMask aMask(aBitmapEx.GetAlpha());
186  mpMaskAccess = aMask.AcquireReadAccess();
187  if (mpMaskAccess)
188  {
189  if (ImplWriteHeader())
190  {
191  ImplWritepHYs(aBitmapEx);
192  ImplWriteIDAT();
193  }
194  aMask.ReleaseAccess(mpMaskAccess);
195  mpMaskAccess = nullptr;
196  }
197  else
198  {
199  mbStatus = false;
200  }
201  }
202  else
203  {
204  Bitmap aMask(aBitmapEx.GetMask());
205  mpMaskAccess = aMask.AcquireReadAccess();
206  if (mpMaskAccess)
207  {
208  if (ImplWriteHeader())
209  {
210  ImplWritepHYs(aBitmapEx);
211  ImplWriteIDAT();
212  }
213  Bitmap::ReleaseAccess(mpMaskAccess);
214  mpMaskAccess = nullptr;
215  }
216  else
217  {
218  mbStatus = false;
219  }
220  }
221  mpAccess.reset();
222  }
223  else
224  {
225  mbStatus = false;
226  }
227  }
228  }
229  else
230  {
231  mpAccess = Bitmap::ScopedReadAccess(aBmp); // palette + RGB without alphachannel
232  if (mpAccess)
233  {
234  if (ImplWriteHeader())
235  {
236  ImplWritepHYs(aBitmapEx);
237  if (mpAccess->HasPalette())
239 
240  ImplWriteIDAT();
241  }
242  mpAccess.reset();
243  }
244  else
245  {
246  mbStatus = false;
247  }
248  }
249 
250  if (mbStatus)
251  {
252  ImplOpenChunk(PNGCHUNK_IEND); // create an IEND chunk
253  }
254 }
255 
257 {
258  /* png signature is always an array of 8 bytes */
259  SvStreamEndian nOldMode = rOStm.GetEndian();
260  rOStm.SetEndian(SvStreamEndian::BIG);
261  rOStm.WriteUInt32(0x89504e47);
262  rOStm.WriteUInt32(0x0d0a1a0a);
263 
264  for (auto const& chunk : maChunkSeq)
265  {
266  sal_uInt32 nType = chunk.nType;
267 #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
268  nType = OSL_SWAPDWORD(nType);
269 #endif
270  sal_uInt32 nCRC = rtl_crc32(0, &nType, 4);
271  sal_uInt32 nDataSize = chunk.aData.size();
272  if (nDataSize)
273  nCRC = rtl_crc32(nCRC, chunk.aData.data(), nDataSize);
274  rOStm.WriteUInt32(nDataSize);
275  rOStm.WriteUInt32(chunk.nType);
276  if (nDataSize)
277  rOStm.WriteBytes(chunk.aData.data(), nDataSize);
278  rOStm.WriteUInt32(nCRC);
279  }
280  rOStm.SetEndian(nOldMode);
281  return mbStatus;
282 }
283 
285 {
287  mnWidth = mpAccess->Width();
288  ImplWriteChunk(sal_uInt32(mnWidth));
289  mnHeight = mpAccess->Height();
290  ImplWriteChunk(sal_uInt32(mnHeight));
291 
293  {
294  sal_uInt8 nBitDepth = mnBitsPerPixel;
295  if (mnBitsPerPixel <= 8)
296  mnFilterType = 0;
297  else
298  mnFilterType = 4;
299 
300  sal_uInt8 nColorType = 2; // colortype:
301 
302  // bit 0 -> palette is used
303  if (mpAccess->HasPalette()) // bit 1 -> color is used
304  nColorType |= 1; // bit 2 -> alpha channel is used
305  else
306  nBitDepth /= 3;
307 
308  if (mpMaskAccess)
309  nColorType |= 4;
310 
311  ImplWriteChunk(nBitDepth);
312  ImplWriteChunk(nColorType); // colortype
313  ImplWriteChunk(static_cast<sal_uInt8>(0)); // compression type
314  ImplWriteChunk(static_cast<sal_uInt8>(0)); // filter type - is not supported in this version
315  ImplWriteChunk(static_cast<sal_uInt8>(mnInterlaced)); // interlace type
316  }
317  else
318  {
319  mbStatus = false;
320  }
321  return mbStatus;
322 }
323 
325 {
327  std::unique_ptr<sal_uInt8[]> pTempBuf(new sal_uInt8[nCount * 3]);
328  sal_uInt8* pTmp = pTempBuf.get();
329 
331 
332  for (sal_uLong i = 0; i < nCount; i++)
333  {
334  const BitmapColor& rColor = mpAccess->GetPaletteColor(i);
335  *pTmp++ = rColor.GetRed();
336  *pTmp++ = rColor.GetGreen();
337  *pTmp++ = rColor.GetBlue();
338  }
339  ImplWriteChunk(pTempBuf.get(), nCount * 3);
340 }
341 
343 {
344  const sal_uLong nTransIndex = mpAccess->GetBestPaletteIndex(BMP_COL_TRANS);
345 
347 
348  for (sal_uLong n = 0; n <= nTransIndex; n++)
349  {
350  ImplWriteChunk((nTransIndex == n) ? static_cast<sal_uInt8>(0x0)
351  : static_cast<sal_uInt8>(0xff));
352  }
353 }
354 
356 {
357  if (rBmpEx.GetPrefMapMode().GetMapUnit() != MapUnit::Map100thMM)
358  return;
359 
360  Size aPrefSize(rBmpEx.GetPrefSize());
361 
362  if (aPrefSize.Width() && aPrefSize.Height() && mnWidth && mnHeight)
363  {
365  sal_uInt32 nPrefSizeX = static_cast<sal_uInt32>(
366  100000.0 / (static_cast<double>(aPrefSize.Width()) / mnWidth) + 0.5);
367  sal_uInt32 nPrefSizeY = static_cast<sal_uInt32>(
368  100000.0 / (static_cast<double>(aPrefSize.Height()) / mnHeight) + 0.5);
369  ImplWriteChunk(nPrefSizeX);
370  ImplWriteChunk(nPrefSizeY);
371  ImplWriteChunk(sal_uInt8(1)); // nMapUnit
372  }
373 }
374 
376 {
378 
379  if (mpMaskAccess)
380  mnDeflateInSize += 8;
381 
382  mnBBP = (mnDeflateInSize + 7) >> 3;
383 
384  mnDeflateInSize = mnBBP * mnWidth + 1;
385 
387 
388  if (mnFilterType) // using filter type 4 we need memory for the scanline 3 times
389  {
390  mpPreviousScan.reset(new sal_uInt8[mnDeflateInSize]);
391  mpCurrentScan.reset(new sal_uInt8[mnDeflateInSize]);
393  }
395  SvMemoryStream aOStm;
396  if (mnInterlaced == 0)
397  {
398  for (sal_uLong nY = 0; nY < mnHeight; nY++)
399  {
400  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY));
401  }
402  }
403  else
404  {
405  // interlace mode
406  sal_uLong nY;
407  for (nY = 0; nY < mnHeight; nY += 8) // pass 1
408  {
409  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 8));
410  }
412 
413  for (nY = 0; nY < mnHeight; nY += 8) // pass 2
414  {
415  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 4, 8));
416  }
418 
419  if (mnHeight >= 5) // pass 3
420  {
421  for (nY = 4; nY < mnHeight; nY += 8)
422  {
423  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 4));
424  }
426  }
427 
428  for (nY = 0; nY < mnHeight; nY += 4) // pass 4
429  {
430  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 2, 4));
431  }
433 
434  if (mnHeight >= 3) // pass 5
435  {
436  for (nY = 2; nY < mnHeight; nY += 4)
437  {
438  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 0, 2));
439  }
441  }
442 
443  for (nY = 0; nY < mnHeight; nY += 2) // pass 6
444  {
445  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY, 1, 2));
446  }
448 
449  if (mnHeight >= 2) // pass 7
450  {
451  for (nY = 1; nY < mnHeight; nY += 2)
452  {
453  mpZCodec.Write(aOStm, mpDeflateInBuf.get(), ImplGetFilter(nY));
454  }
455  }
456  }
458 
459  if (mnFilterType) // using filter type 4 we need memory for the scanline 3 times
460  {
461  mpCurrentScan.reset();
462  mpPreviousScan.reset();
463  }
464  mpDeflateInBuf.reset();
465 
466  sal_uInt32 nIDATSize = aOStm.Tell();
467  sal_uInt32 nBytes, nBytesToWrite = nIDATSize;
468  while (nBytesToWrite)
469  {
470  nBytes = nBytesToWrite <= mnMaxChunkSize ? nBytesToWrite : mnMaxChunkSize;
473  const_cast<unsigned char*>(static_cast<unsigned char const*>(aOStm.GetData()))
474  + (nIDATSize - nBytesToWrite),
475  nBytes);
476  nBytesToWrite -= nBytes;
477  }
478 }
479 
480 // ImplGetFilter writes the complete Scanline (nY) - in interlace mode the parameter nXStart and nXAdd
481 // appends to the currently used pass
482 // the complete size of scanline will be returned - in interlace mode zero is possible!
483 
485 {
486  sal_uInt8* pDest;
487 
488  if (mnFilterType)
489  pDest = mpCurrentScan.get();
490  else
491  pDest = mpDeflateInBuf.get();
492 
493  if (nXStart < mnWidth)
494  {
495  *pDest++ = mnFilterType; // in this version the filter type is either 0 or 4
496 
497  if (mpAccess
498  ->HasPalette()) // alphachannel is not allowed by pictures including palette entries
499  {
500  switch (mnBitsPerPixel)
501  {
502  case 1:
503  {
504  Scanline pScanline = mpAccess->GetScanline(nY);
505  sal_uLong nX, nXIndex;
506  for (nX = nXStart, nXIndex = 0; nX < mnWidth; nX += nXAdd, nXIndex++)
507  {
508  sal_uLong nShift = (nXIndex & 7) ^ 7;
509  if (nShift == 7)
510  *pDest = mpAccess->GetIndexFromData(pScanline, nX) << nShift;
511  else if (nShift == 0)
512  *pDest++ |= mpAccess->GetIndexFromData(pScanline, nX) << nShift;
513  else
514  *pDest |= mpAccess->GetIndexFromData(pScanline, nX) << nShift;
515  }
516  if ((nXIndex & 7) != 0)
517  pDest++; // byte is not completely used, so the bufferpointer is to correct
518  }
519  break;
520 
521  case 4:
522  {
523  Scanline pScanline = mpAccess->GetScanline(nY);
524  sal_uLong nX, nXIndex;
525  for (nX = nXStart, nXIndex = 0; nX < mnWidth; nX += nXAdd, nXIndex++)
526  {
527  if (nXIndex & 1)
528  *pDest++ |= mpAccess->GetIndexFromData(pScanline, nX);
529  else
530  *pDest = mpAccess->GetIndexFromData(pScanline, nX) << 4;
531  }
532  if (nXIndex & 1)
533  pDest++;
534  }
535  break;
536 
537  case 8:
538  {
539  Scanline pScanline = mpAccess->GetScanline(nY);
540  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
541  {
542  *pDest++ = mpAccess->GetIndexFromData(pScanline, nX);
543  }
544  }
545  break;
546 
547  default:
548  mbStatus = false;
549  break;
550  }
551  }
552  else
553  {
554  if (mpMaskAccess) // mpMaskAccess != NULL -> alphachannel is to create
555  {
556  if (mbTrueAlpha)
557  {
558  Scanline pScanline = mpAccess->GetScanline(nY);
559  Scanline pScanlineMask = mpMaskAccess->GetScanline(nY);
560  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
561  {
562  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
563  *pDest++ = rColor.GetRed();
564  *pDest++ = rColor.GetGreen();
565  *pDest++ = rColor.GetBlue();
566  *pDest++ = 255 - mpMaskAccess->GetIndexFromData(pScanlineMask, nX);
567  }
568  }
569  else
570  {
572  Scanline pScanline = mpAccess->GetScanline(nY);
573  Scanline pScanlineMask = mpMaskAccess->GetScanline(nY);
574 
575  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
576  {
577  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
578  *pDest++ = rColor.GetRed();
579  *pDest++ = rColor.GetGreen();
580  *pDest++ = rColor.GetBlue();
581 
582  if (mpMaskAccess->GetPixelFromData(pScanlineMask, nX) == aTrans)
583  *pDest++ = 0;
584  else
585  *pDest++ = 0xff;
586  }
587  }
588  }
589  else
590  {
591  Scanline pScanline = mpAccess->GetScanline(nY);
592  for (sal_uLong nX = nXStart; nX < mnWidth; nX += nXAdd)
593  {
594  const BitmapColor& rColor = mpAccess->GetPixelFromData(pScanline, nX);
595  *pDest++ = rColor.GetRed();
596  *pDest++ = rColor.GetGreen();
597  *pDest++ = rColor.GetBlue();
598  }
599  }
600  }
601  }
602  // filter type4 ( PAETH ) will be used only for 24bit graphics
603  if (mnFilterType)
604  {
605  mnDeflateInSize = pDest - mpCurrentScan.get();
606  pDest = mpDeflateInBuf.get();
607  *pDest++ = 4; // filter type
608 
609  sal_uInt8* p1 = mpCurrentScan.get() + 1; // Current Pixel
610  sal_uInt8* p2 = p1 - mnBBP; // left pixel
611  sal_uInt8* p3 = mpPreviousScan.get(); // upper pixel
612  sal_uInt8* p4 = p3 - mnBBP; // upperleft Pixel;
613 
614  while (pDest < mpDeflateInBuf.get() + mnDeflateInSize)
615  {
616  sal_uLong nb = *p3++;
617  sal_uLong na, nc;
618  if (p2 >= mpCurrentScan.get() + 1)
619  {
620  na = *p2;
621  nc = *p4;
622  }
623  else
624  {
625  na = nc = 0;
626  }
627 
628  tools::Long np = na + nb - nc;
629  tools::Long npa = np - na;
630  tools::Long npb = np - nb;
631  tools::Long npc = np - nc;
632 
633  if (npa < 0)
634  npa = -npa;
635  if (npb < 0)
636  npb = -npb;
637  if (npc < 0)
638  npc = -npc;
639 
640  if (npa <= npb && npa <= npc)
641  *pDest++ = *p1++ - static_cast<sal_uInt8>(na);
642  else if (npb <= npc)
643  *pDest++ = *p1++ - static_cast<sal_uInt8>(nb);
644  else
645  *pDest++ = *p1++ - static_cast<sal_uInt8>(nc);
646 
647  p4++;
648  p2++;
649  }
650  for (tools::Long i = 0; i < static_cast<tools::Long>(mnDeflateInSize - 1); i++)
651  {
653  }
654  }
655  else
656  {
657  mnDeflateInSize = pDest - mpDeflateInBuf.get();
658  }
659  return mnDeflateInSize;
660 }
661 
663 {
664  if (mnFilterType)
665  memset(mpPreviousScan.get(), 0, mnDeflateInSize);
666 }
667 
669 {
670  maChunkSeq.emplace_back();
671  maChunkSeq.back().nType = nChunkType;
672 }
673 
675 {
676  maChunkSeq.back().aData.push_back(nSource);
677 }
678 
679 void PNGWriterImpl::ImplWriteChunk(sal_uInt32 nSource)
680 {
681  vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
682  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 24));
683  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 16));
684  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource >> 8));
685  rChunkData.aData.push_back(static_cast<sal_uInt8>(nSource));
686 }
687 
688 void PNGWriterImpl::ImplWriteChunk(unsigned char const* pSource, sal_uInt32 nDatSize)
689 {
690  if (nDatSize)
691  {
692  vcl::PNGWriter::ChunkData& rChunkData = maChunkSeq.back();
693  sal_uInt32 nSize = rChunkData.aData.size();
694  rChunkData.aData.resize(nSize + nDatSize);
695  memcpy(&rChunkData.aData[nSize], pSource, nDatSize);
696  }
697 }
698 
700  const css::uno::Sequence<css::beans::PropertyValue>* pFilterData)
701  : mpImpl(new vcl::PNGWriterImpl(rBmpEx, pFilterData))
702 {
703 }
704 
706 
707 bool PNGWriter::Write(SvStream& rStream) { return mpImpl->Write(rStream); }
708 
709 std::vector<vcl::PNGWriter::ChunkData>& PNGWriter::GetChunks() { return mpImpl->GetChunks(); }
710 
711 } // namespace vcl
712 
713 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mnHeight
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
Bitmap GetMask() const
Definition: BitmapEx.cxx:246
Bitmap::ScopedReadAccess mpAccess
Definition: pngwrite.cxx:65
#define BMP_COL_TRANS
Definition: bitmap.hxx:69
tools::Long Height() const
bool Write(SvStream &rOutStream)
Definition: pngwrite.cxx:256
sal_uInt8 GetRed() const
#define PNGCHUNK_IHDR
Definition: pngwrite.cxx:38
void ImplWritepHYs(const BitmapEx &rBitmapEx)
Definition: pngwrite.cxx:355
const MapMode & GetPrefMapMode() const
Definition: bitmapex.hxx:89
sal_uIntPtr sal_uLong
long Long
sal_Int64 n
#define PNGCHUNK_PLTE
Definition: pngwrite.cxx:39
#define PNGCHUNK_pHYs
Definition: pngwrite.cxx:42
std::vector< vcl::PNGWriter::ChunkData > maChunkSeq
Definition: pngwrite.cxx:58
sal_Int32 mnCompLevel
Definition: pngwrite.cxx:60
sal_uLong mnHeight
Definition: pngwrite.cxx:76
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
void ImplWriteChunk(sal_uInt8 nNumb)
Definition: pngwrite.cxx:674
sal_uInt8 mnFilterType
Definition: pngwrite.cxx:78
const std::unique_ptr< PNGWriterImpl > mpImpl
Definition: pngwrite.hxx:39
bool IsAlpha() const
Definition: BitmapEx.cxx:219
std::unique_ptr< sal_uInt8[]> mpDeflateInBuf
Definition: pngwrite.cxx:70
sal_uLong ImplGetFilter(sal_uLong nY, sal_uLong nXStart=0, sal_uLong nXAdd=1)
Definition: pngwrite.cxx:484
Scanline GetScanline(tools::Long nY) const
const Size & GetPrefSize() const
Definition: bitmapex.hxx:86
int nCount
sal_uLong mnDeflateInSize
Definition: pngwrite.cxx:73
SvStream & WriteUInt32(sal_uInt32 nUInt32)
sal_uInt8 GetBlue() const
PNGWriter(const BitmapEx &, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData=nullptr)
Definition: pngwrite.cxx:699
sal_Int32 mnInterlaced
Definition: pngwrite.cxx:61
vcl::ScopedBitmapAccess< BitmapReadAccess, Bitmap,&Bitmap::AcquireReadAccess > ScopedReadAccess
Definition: bitmap.hxx:534
bool IsEmpty() const
Definition: BitmapEx.cxx:196
#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:709
sal_uLong mnBBP
Definition: pngwrite.cxx:79
PNGWriterImpl(const BitmapEx &BmpEx, const css::uno::Sequence< css::beans::PropertyValue > *pFilterData)
Definition: pngwrite.cxx:95
void ImplClearFirstScanline()
Definition: pngwrite.cxx:662
std::vector< vcl::PNGWriter::ChunkData > & GetChunks()
Definition: pngwrite.cxx:55
bool ImplWriteHeader()
Definition: pngwrite.cxx:284
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:707
static void ReleaseAccess(BitmapInfoAccess *pAccess)
MapUnit GetMapUnit() const
Definition: mapmod.cxx:136
sal_uInt32 mnMaxChunkSize
Definition: pngwrite.cxx:62
bool IsTransparent() const
Definition: BitmapEx.cxx:214
sal_uInt16 GetPaletteEntryCount() const
BitmapReadAccess * mpMaskAccess
Definition: pngwrite.cxx:66
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:229
#define PNGCHUNK_tRNS
Definition: pngwrite.cxx:43
sal_uInt8 GetGreen() const
SvStreamEndian GetEndian() const
AlphaMask GetAlpha() const
Definition: BitmapEx.cxx:256
#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:77
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:324
SvStreamEndian
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
std::unique_ptr< sal_uInt8[]> mpPreviousScan
Definition: pngwrite.cxx:71
void ImplOpenChunk(sal_uLong nChunkType)
Definition: pngwrite.cxx:668
std::unique_ptr< sal_uInt8[]> mpCurrentScan
Definition: pngwrite.cxx:72
std::vector< sal_uInt8 > aData
Definition: pngwrite.hxx:52
sal_uLong mnWidth
Definition: pngwrite.cxx:75
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)
void Write(SvStream &rOStm, const sal_uInt8 *pData, sal_uInt32 nSize)
const void * GetData()
void ImplWriteTransparent()
Definition: pngwrite.cxx:342