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