LibreOffice Module vcl (master)  1
bitmap/bitmap.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 <config_features.h>
21 
22 #include <sal/log.hxx>
23 #include <osl/diagnose.h>
24 #include <tools/helpers.hxx>
25 
26 #include <vcl/bitmap.hxx>
27 #include <vcl/bitmapex.hxx>
28 #include <vcl/outdev.hxx>
29 
30 #include <svdata.hxx>
31 #include <salinst.hxx>
32 #include <salbmp.hxx>
33 #if HAVE_FEATURE_SKIA
34 #include <vcl/skia/SkiaHelper.hxx>
35 #endif
37 
43 #include <bitmap/impoctree.hxx>
44 #include <bitmap/Octree.hxx>
45 
46 #include "impvect.hxx"
47 #include "floyd.hxx"
48 
49 #include <math.h>
50 #include <algorithm>
51 #include <memory>
52 
53 #ifdef DBG_UTIL
54 #include <cstdlib>
55 #include <tools/stream.hxx>
56 #include <vcl/graphicfilter.hxx>
57 #endif
58 
60 {
61 }
62 
63 Bitmap::Bitmap(const Bitmap& rBitmap)
64  : mxSalBmp(rBitmap.mxSalBmp)
65  , maPrefMapMode(rBitmap.maPrefMapMode)
66  , maPrefSize(rBitmap.maPrefSize)
67 {
68 }
69 
70 Bitmap::Bitmap(std::shared_ptr<SalBitmap> const & pSalBitmap)
71  : mxSalBmp(pSalBitmap)
72  , maPrefMapMode(MapMode(MapUnit::MapPixel))
73  , maPrefSize(mxSalBmp->GetSize())
74 {
75 }
76 
77 Bitmap::Bitmap( const Size& rSizePixel, vcl::PixelFormat ePixelFormat, const BitmapPalette* pPal )
78 {
79  if (!(rSizePixel.Width() && rSizePixel.Height()))
80  return;
81 
82  BitmapPalette aPal;
83  BitmapPalette* pRealPal = nullptr;
84 
85  if (vcl::isPalettePixelFormat(ePixelFormat))
86  {
87  if( !pPal )
88  {
89  if (ePixelFormat == vcl::PixelFormat::N1_BPP)
90  {
91  aPal.SetEntryCount( 2 );
92  aPal[ 0 ] = COL_BLACK;
93  aPal[ 1 ] = COL_WHITE;
94  }
95  else if (ePixelFormat == vcl::PixelFormat::N8_BPP)
96  {
97  aPal.SetEntryCount(1 << sal_uInt16(ePixelFormat));
98  aPal[ 0 ] = COL_BLACK;
99  aPal[ 1 ] = COL_BLUE;
100  aPal[ 2 ] = COL_GREEN;
101  aPal[ 3 ] = COL_CYAN;
102  aPal[ 4 ] = COL_RED;
103  aPal[ 5 ] = COL_MAGENTA;
104  aPal[ 6 ] = COL_BROWN;
105  aPal[ 7 ] = COL_GRAY;
106  aPal[ 8 ] = COL_LIGHTGRAY;
107  aPal[ 9 ] = COL_LIGHTBLUE;
108  aPal[ 10 ] = COL_LIGHTGREEN;
109  aPal[ 11 ] = COL_LIGHTCYAN;
110  aPal[ 12 ] = COL_LIGHTRED;
111  aPal[ 13 ] = COL_LIGHTMAGENTA;
112  aPal[ 14 ] = COL_YELLOW;
113  aPal[ 15 ] = COL_WHITE;
114 
115  // Create dither palette
116  if (ePixelFormat == vcl::PixelFormat::N8_BPP)
117  {
118  sal_uInt16 nActCol = 16;
119 
120  for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
121  for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
122  for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
123  aPal[ nActCol++ ] = BitmapColor( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
124 
125  // Set standard Office colors
126  aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
127  }
128  }
129  }
130  else
131  pRealPal = const_cast<BitmapPalette*>(pPal);
132  }
133 
135  mxSalBmp->Create(rSizePixel, ePixelFormat, pRealPal ? *pRealPal : aPal);
136 }
137 
138 #ifdef DBG_UTIL
139 
140 namespace
141 {
142 void savePNG(const OUString& sWhere, const Bitmap& rBmp)
143 {
144  SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
146  rFilter.compressAsPNG(BitmapEx(rBmp), aStream);
147 }
148 }
149 
150 #endif
151 
153 {
154 #ifdef DBG_UTIL
155  // VCL_DUMP_BMP_PATH should be like C:/bmpDump.png or ~/bmpDump.png
156  static const OUString sDumpPath(OUString::createFromAscii(std::getenv("VCL_DUMP_BMP_PATH")));
157  // Stepping into the dtor of a bitmap you need, and setting the volatile variable to true in
158  // debugger, would dump the bitmap in question
159  static volatile bool save(false);
160  if (!sDumpPath.isEmpty() && save)
161  {
162  save = false;
163  savePNG(sDumpPath, *this);
164  }
165 #endif
166 }
167 
168 const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
169 {
170  // Create greyscale palette with 2, 4, 16 or 256 entries
171  switch (nEntries)
172  {
173  case 2:
174  {
175  static const BitmapPalette aGreyPalette2 = [] {
176  BitmapPalette aPalette(2);
177  aPalette[0] = BitmapColor(0, 0, 0);
178  aPalette[1] = BitmapColor(255, 255, 255);
179  return aPalette;
180  }();
181 
182  return aGreyPalette2;
183  }
184  case 4:
185  {
186  static const BitmapPalette aGreyPalette4 = [] {
187  BitmapPalette aPalette(4);
188  aPalette[0] = BitmapColor(0, 0, 0);
189  aPalette[1] = BitmapColor(85, 85, 85);
190  aPalette[2] = BitmapColor(170, 170, 170);
191  aPalette[3] = BitmapColor(255, 255, 255);
192  return aPalette;
193  }();
194 
195  return aGreyPalette4;
196  }
197  case 16:
198  {
199  static const BitmapPalette aGreyPalette16 = [] {
200  sal_uInt8 cGrey = 0;
201  sal_uInt8 const cGreyInc = 17;
202 
203  BitmapPalette aPalette(16);
204 
205  for (sal_uInt16 i = 0; i < 16; ++i, cGrey += cGreyInc)
206  aPalette[i] = BitmapColor(cGrey, cGrey, cGrey);
207 
208  return aPalette;
209  }();
210 
211  return aGreyPalette16;
212  }
213  case 256:
214  {
215  static const BitmapPalette aGreyPalette256 = [] {
216  BitmapPalette aPalette(256);
217 
218  for (sal_uInt16 i = 0; i < 256; ++i)
219  aPalette[i] = BitmapColor(static_cast<sal_uInt8>(i), static_cast<sal_uInt8>(i),
220  static_cast<sal_uInt8>(i));
221 
222  return aPalette;
223  }();
224 
225  return aGreyPalette256;
226  }
227  }
228  OSL_FAIL("Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)");
229  return GetGreyPalette(2);
230 }
231 
232 Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
233 {
234  if (this == &rBitmap)
235  return *this;
236 
237  maPrefSize = rBitmap.maPrefSize;
238  maPrefMapMode = rBitmap.maPrefMapMode;
239  mxSalBmp = rBitmap.mxSalBmp;
240 
241  return *this;
242 }
243 
244 Bitmap& Bitmap::operator=( Bitmap&& rBitmap ) noexcept
245 {
246  maPrefSize = std::move(rBitmap.maPrefSize);
247  maPrefMapMode = std::move(rBitmap.maPrefMapMode);
248  mxSalBmp = std::move(rBitmap.mxSalBmp);
249 
250  return *this;
251 }
252 
253 bool Bitmap::operator==( const Bitmap& rBmp ) const
254 {
255  if (rBmp.mxSalBmp == mxSalBmp) // Includes both are nullptr
256  return true;
257  if (!rBmp.mxSalBmp || !mxSalBmp)
258  return false;
259  if (rBmp.mxSalBmp->GetSize() != mxSalBmp->GetSize() ||
260  rBmp.mxSalBmp->GetBitCount() != mxSalBmp->GetBitCount())
261  return false;
262  BitmapChecksum aChecksum1 = rBmp.mxSalBmp->GetChecksum();
263  BitmapChecksum aChecksum2 = mxSalBmp->GetChecksum();
264  // If the bitmaps can't calculate a checksum, best to regard them as different.
265  if (aChecksum1 == 0 || aChecksum2 == 0)
266  return false;
267  return aChecksum1 == aChecksum2;
268 }
269 
271 {
273  maPrefSize = Size();
274  mxSalBmp.reset();
275 }
276 
278 {
279  return( mxSalBmp ? mxSalBmp->GetSize() : Size() );
280 }
281 
283 {
284  if (!mxSalBmp)
286 
287  sal_uInt16 nBitCount = mxSalBmp->GetBitCount();
288  if (nBitCount <= 1)
290  if (nBitCount <= 8)
292  if (nBitCount <= 24)
294  if (nBitCount <= 32)
296 
298 }
299 
301 {
302  bool bRet = getPixelFormat() == vcl::PixelFormat::N1_BPP;
303 
304  ScopedInfoAccess pIAcc(const_cast<Bitmap&>(*this));
305 
306  if( pIAcc )
307  {
308  bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPaletteAny();
309  }
310 
311  return bRet;
312 }
313 
315 {
316  bool bRet = false;
317  ScopedInfoAccess pIAcc(const_cast<Bitmap&>(*this));
318 
319  if( pIAcc )
320  {
321  bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPalette8Bit();
322  }
323 
324  return bRet;
325 }
326 
328 {
329  BitmapChecksum nRet = 0;
330 
331  if( mxSalBmp )
332  {
333  nRet = mxSalBmp->GetChecksum();
334 
335  if (!nRet)
336  {
337  // nRet == 0 => probably, we were not able to acquire
338  // the buffer in SalBitmap::updateChecksum;
339  // so, we need to update the imp bitmap for this bitmap instance
340  // as we do in BitmapInfoAccess::ImplCreate
341  std::shared_ptr<SalBitmap> xNewImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
342  if (xNewImpBmp->Create(*mxSalBmp, getPixelFormat()))
343  {
344  Bitmap* pThis = const_cast<Bitmap*>(this);
345  pThis->mxSalBmp = xNewImpBmp;
346  nRet = mxSalBmp->GetChecksum();
347  }
348  }
349  }
350 
351  return nRet;
352 }
353 
355 {
356  if (mxSalBmp && mxSalBmp.use_count() > 1)
357  {
358  std::shared_ptr<SalBitmap> xOldImpBmp = mxSalBmp;
360  (void)mxSalBmp->Create(*xOldImpBmp);
361  }
362 }
363 
364 void Bitmap::ReassignWithSize(const Bitmap& rBitmap)
365 {
366  const Size aOldSizePix(GetSizePixel());
367  const Size aNewSizePix(rBitmap.GetSizePixel());
368  const MapMode aOldMapMode(maPrefMapMode);
369  Size aNewPrefSize;
370 
371  if ((aOldSizePix != aNewSizePix) && aOldSizePix.Width() && aOldSizePix.Height())
372  {
373  aNewPrefSize.setWidth(FRound(maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width()));
374  aNewPrefSize.setHeight(FRound(maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height()));
375  }
376  else
377  {
378  aNewPrefSize = maPrefSize;
379  }
380 
381  *this = rBitmap;
382 
383  maPrefSize = aNewPrefSize;
384  maPrefMapMode = aOldMapMode;
385 }
386 
387 void Bitmap::ImplSetSalBitmap(const std::shared_ptr<SalBitmap>& xImpBmp)
388 {
389  mxSalBmp = xImpBmp;
390 }
391 
393 {
394  std::unique_ptr<BitmapInfoAccess> pInfoAccess(new BitmapInfoAccess( *this ));
395 
396  if( !*pInfoAccess )
397  {
398  return nullptr;
399  }
400 
401  return pInfoAccess.release();
402 }
403 
405 {
406  std::unique_ptr<BitmapReadAccess> pReadAccess(new BitmapReadAccess( *this ));
407 
408  if( !*pReadAccess )
409  {
410  return nullptr;
411  }
412 
413  return pReadAccess.release();
414 }
415 
417 {
418  std::unique_ptr<BitmapWriteAccess> pWriteAccess(new BitmapWriteAccess( *this ));
419 
420  if( !*pWriteAccess )
421  {
422  return nullptr;
423  }
424 
425  return pWriteAccess.release();
426 }
427 
429 {
430  delete pBitmapAccess;
431 }
432 
433 bool Bitmap::Crop( const tools::Rectangle& rRectPixel )
434 {
435  const Size aSizePix( GetSizePixel() );
436  tools::Rectangle aRect( rRectPixel );
437  bool bRet = false;
438 
439  aRect.Intersection( tools::Rectangle( Point(), aSizePix ) );
440 
441  if( !aRect.IsEmpty() && aSizePix != aRect.GetSize())
442  {
443  ScopedReadAccess pReadAcc(*this);
444 
445  if( pReadAcc )
446  {
447  const tools::Rectangle aNewRect( Point(), aRect.GetSize() );
448  Bitmap aNewBmp(aNewRect.GetSize(), getPixelFormat(), &pReadAcc->GetPalette());
449  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
450 
451  if( pWriteAcc )
452  {
453  const tools::Long nOldX = aRect.Left();
454  const tools::Long nOldY = aRect.Top();
455  const tools::Long nNewWidth = aNewRect.GetWidth();
456  const tools::Long nNewHeight = aNewRect.GetHeight();
457 
458  for( tools::Long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
459  {
460  Scanline pScanline = pWriteAcc->GetScanline(nY);
461  Scanline pScanlineRead = pReadAcc->GetScanline(nY2);
462  for( tools::Long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
463  pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixelFromData( pScanlineRead, nX2 ) );
464  }
465 
466  pWriteAcc.reset();
467  bRet = true;
468  }
469 
470  pReadAcc.reset();
471 
472  if( bRet )
473  ReassignWithSize( aNewBmp );
474  }
475  }
476 
477  return bRet;
478 };
479 
480 bool Bitmap::CopyPixel( const tools::Rectangle& rRectDst,
481  const tools::Rectangle& rRectSrc, const Bitmap* pBmpSrc )
482 {
483  const Size aSizePix( GetSizePixel() );
484  tools::Rectangle aRectDst( rRectDst );
485  bool bRet = false;
486 
487  aRectDst.Intersection( tools::Rectangle( Point(), aSizePix ) );
488 
489  if( !aRectDst.IsEmpty() )
490  {
491  if( pBmpSrc && ( pBmpSrc->mxSalBmp != mxSalBmp ) )
492  {
493  Bitmap* pSrc = const_cast<Bitmap*>(pBmpSrc);
494  const Size aCopySizePix( pSrc->GetSizePixel() );
495  tools::Rectangle aRectSrc( rRectSrc );
496  const sal_uInt16 nSrcBitCount = vcl::pixelFormatBitCount(pBmpSrc->getPixelFormat());
497  const sal_uInt16 nDstBitCount = vcl::pixelFormatBitCount(getPixelFormat());
498 
499  if( nSrcBitCount > nDstBitCount )
500  {
501  int nNextIndex = 0;
502 
503  if (nSrcBitCount == 24)
505  else if (nSrcBitCount == 8)
506  {
508  nNextIndex = 16;
509  }
510  else if (nSrcBitCount == 4)
511  {
512  assert(false);
513  }
514 
515  if( nNextIndex )
516  {
517  ScopedReadAccess pSrcAcc(*pSrc);
518  BitmapScopedWriteAccess pDstAcc(*this);
519 
520  if( pSrcAcc && pDstAcc )
521  {
522  const int nSrcCount = pSrcAcc->GetPaletteEntryCount();
523  const int nDstCount = 1 << nDstBitCount;
524 
525  for (int i = 0; ( i < nSrcCount ) && ( nNextIndex < nDstCount ); ++i)
526  {
527  const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( static_cast<sal_uInt16>(i) );
528 
529  bool bFound = false;
530 
531  for (int j = 0; j < nDstCount; ++j)
532  {
533  if( rSrcCol == pDstAcc->GetPaletteColor( static_cast<sal_uInt16>(j) ) )
534  {
535  bFound = true;
536  break;
537  }
538  }
539 
540  if( !bFound )
541  pDstAcc->SetPaletteColor( static_cast<sal_uInt16>(nNextIndex++), rSrcCol );
542  }
543  }
544  }
545  }
546 
547  aRectSrc.Intersection( tools::Rectangle( Point(), aCopySizePix ) );
548 
549  if( !aRectSrc.IsEmpty() )
550  {
551  ScopedReadAccess pReadAcc(*pSrc);
552 
553  if( pReadAcc )
554  {
555  BitmapScopedWriteAccess pWriteAcc(*this);
556 
557  if( pWriteAcc )
558  {
559  const tools::Long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
560  const tools::Long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
561  const tools::Long nSrcEndX = aRectSrc.Left() + nWidth;
562  const tools::Long nSrcEndY = aRectSrc.Top() + nHeight;
563  tools::Long nDstY = aRectDst.Top();
564 
565  if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
566  {
567  const sal_uInt16 nCount = pReadAcc->GetPaletteEntryCount();
568  std::unique_ptr<sal_uInt8[]> pMap(new sal_uInt8[ nCount ]);
569 
570  // Create index map for the color table, as the bitmap should be copied
571  // retaining it's color information relatively well
572  for( sal_uInt16 i = 0; i < nCount; i++ )
573  pMap[ i ] = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) ));
574 
575  for( tools::Long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
576  {
577  Scanline pScanline = pWriteAcc->GetScanline(nDstY);
578  Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
579  for( tools::Long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
580  pWriteAcc->SetPixelOnData( pScanline, nDstX, BitmapColor( pMap[ pReadAcc->GetIndexFromData( pScanlineRead, nSrcX ) ] ));
581  }
582  }
583  else if( pReadAcc->HasPalette() )
584  {
585  for( tools::Long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
586  {
587  Scanline pScanline = pWriteAcc->GetScanline(nDstY);
588  Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
589  for( tools::Long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
590  pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nSrcX ) ) );
591  }
592  }
593  else
594  for( tools::Long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
595  {
596  Scanline pScanline = pWriteAcc->GetScanline(nDstY);
597  Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
598  for( tools::Long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
599  pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPixelFromData( pScanlineRead, nSrcX ) );
600  }
601 
602  pWriteAcc.reset();
603  bRet = ( nWidth > 0 ) && ( nHeight > 0 );
604  }
605 
606  pReadAcc.reset();
607  }
608  }
609  }
610  else
611  {
612  tools::Rectangle aRectSrc( rRectSrc );
613 
614  aRectSrc.Intersection( tools::Rectangle( Point(), aSizePix ) );
615 
616  if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
617  {
618  BitmapScopedWriteAccess pWriteAcc(*this);
619 
620  if( pWriteAcc )
621  {
622  const tools::Long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
623  const tools::Long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
624  const tools::Long nSrcX = aRectSrc.Left();
625  const tools::Long nSrcY = aRectSrc.Top();
626  const tools::Long nSrcEndX1 = nSrcX + nWidth - 1;
627  const tools::Long nSrcEndY1 = nSrcY + nHeight - 1;
628  const tools::Long nDstX = aRectDst.Left();
629  const tools::Long nDstY = aRectDst.Top();
630  const tools::Long nDstEndX1 = nDstX + nWidth - 1;
631  const tools::Long nDstEndY1 = nDstY + nHeight - 1;
632 
633  if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
634  {
635  for( tools::Long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
636  {
637  Scanline pScanline = pWriteAcc->GetScanline(nYN);
638  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
639  for( tools::Long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
640  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
641  }
642  }
643  else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
644  {
645  for( tools::Long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
646  {
647  Scanline pScanline = pWriteAcc->GetScanline(nYN);
648  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
649  for( tools::Long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
650  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
651  }
652  }
653  else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
654  {
655  for( tools::Long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
656  {
657  Scanline pScanline = pWriteAcc->GetScanline(nYN);
658  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
659  for( tools::Long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
660  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
661  }
662  }
663  else
664  {
665  for( tools::Long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
666  {
667  Scanline pScanline = pWriteAcc->GetScanline(nYN);
668  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
669  for( tools::Long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
670  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
671  }
672  }
673 
674  pWriteAcc.reset();
675  bRet = true;
676  }
677  }
678  }
679  }
680 
681  return bRet;
682 }
683 
685  const Bitmap* pBmpSrc )
686 {
687  // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
688  // This optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
689  const Size aSizePix( GetSizePixel() );
690  tools::Rectangle aRectDst( rRectDst );
691  bool bRet = false;
692 
693  aRectDst.Intersection( tools::Rectangle( Point(), aSizePix ) );
694 
695  if( !aRectDst.IsEmpty() )
696  {
697  if( pBmpSrc && ( pBmpSrc->mxSalBmp != mxSalBmp ) )
698  {
699  Bitmap* pSrc = const_cast<Bitmap*>(pBmpSrc);
700  const Size aCopySizePix( pSrc->GetSizePixel() );
701  tools::Rectangle aRectSrc( rRectSrc );
702 
703  aRectSrc.Intersection( tools::Rectangle( Point(), aCopySizePix ) );
704 
705  if( !aRectSrc.IsEmpty() )
706  {
707  ScopedReadAccess pReadAcc(*pSrc);
708 
709  if( pReadAcc )
710  {
711  BitmapScopedWriteAccess pWriteAcc(*this);
712 
713  if( pWriteAcc )
714  {
715  const tools::Long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
716  const tools::Long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
717  const tools::Long nSrcEndX = aRectSrc.Left() + nWidth;
718  const tools::Long nSrcEndY = aRectSrc.Top() + nHeight;
719  tools::Long nDstY = aRectDst.Top();
720 
721  for( tools::Long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++)
722  {
723  Scanline pScanline = pWriteAcc->GetScanline(nDstY);
724  Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
725  for( tools::Long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
726  pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPixelFromData( pScanlineRead, nSrcX ) );
727  }
728 
729  pWriteAcc.reset();
730  bRet = ( nWidth > 0 ) && ( nHeight > 0 );
731  }
732 
733  pReadAcc.reset();
734  }
735  }
736  }
737  else
738  {
739  tools::Rectangle aRectSrc( rRectSrc );
740 
741  aRectSrc.Intersection( tools::Rectangle( Point(), aSizePix ) );
742 
743  if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
744  {
745  BitmapScopedWriteAccess pWriteAcc(*this);
746 
747  if( pWriteAcc )
748  {
749  const tools::Long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
750  const tools::Long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
751  const tools::Long nSrcX = aRectSrc.Left();
752  const tools::Long nSrcY = aRectSrc.Top();
753  const tools::Long nSrcEndX1 = nSrcX + nWidth - 1;
754  const tools::Long nSrcEndY1 = nSrcY + nHeight - 1;
755  const tools::Long nDstX = aRectDst.Left();
756  const tools::Long nDstY = aRectDst.Top();
757  const tools::Long nDstEndX1 = nDstX + nWidth - 1;
758  const tools::Long nDstEndY1 = nDstY + nHeight - 1;
759 
760  if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
761  {
762  for( tools::Long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
763  {
764  Scanline pScanline = pWriteAcc->GetScanline(nYN);
765  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
766  for( tools::Long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
767  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
768  }
769  }
770  else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
771  {
772  for( tools::Long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
773  {
774  Scanline pScanline = pWriteAcc->GetScanline(nYN);
775  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
776  for( tools::Long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
777  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
778  }
779  }
780  else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
781  {
782  for( tools::Long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
783  {
784  Scanline pScanline = pWriteAcc->GetScanline(nYN);
785  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
786  for( tools::Long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
787  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
788  }
789  }
790  else
791  {
792  for( tools::Long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
793  {
794  Scanline pScanline = pWriteAcc->GetScanline(nYN);
795  Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
796  for( tools::Long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
797  pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
798  }
799  }
800 
801  pWriteAcc.reset();
802  bRet = true;
803  }
804  }
805  }
806  }
807 
808  return bRet;
809 
810 }
811 
812 bool Bitmap::Expand( sal_Int32 nDX, sal_Int32 nDY, const Color* pInitColor )
813 {
814  bool bRet = false;
815 
816  if( nDX || nDY )
817  {
818  const Size aSizePixel( GetSizePixel() );
819  const tools::Long nWidth = aSizePixel.Width();
820  const tools::Long nHeight = aSizePixel.Height();
821  const Size aNewSize( nWidth + nDX, nHeight + nDY );
822  ScopedReadAccess pReadAcc(*this);
823 
824  if( pReadAcc )
825  {
826  BitmapPalette aBmpPal( pReadAcc->GetPalette() );
827  Bitmap aNewBmp(aNewSize, getPixelFormat(), &aBmpPal);
828  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
829 
830  if( pWriteAcc )
831  {
832  BitmapColor aColor;
833  const tools::Long nNewX = nWidth;
834  const tools::Long nNewY = nHeight;
835  const tools::Long nNewWidth = pWriteAcc->Width();
836  const tools::Long nNewHeight = pWriteAcc->Height();
837  tools::Long nX;
838  tools::Long nY;
839 
840  if( pInitColor )
841  aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
842 
843  for( nY = 0; nY < nHeight; nY++ )
844  {
845  pWriteAcc->CopyScanline( nY, *pReadAcc );
846 
847  if( pInitColor && nDX )
848  {
849  Scanline pScanline = pWriteAcc->GetScanline(nY);
850  for( nX = nNewX; nX < nNewWidth; nX++ )
851  pWriteAcc->SetPixelOnData( pScanline, nX, aColor );
852  }
853  }
854 
855  if( pInitColor && nDY )
856  for( nY = nNewY; nY < nNewHeight; nY++ )
857  {
858  Scanline pScanline = pWriteAcc->GetScanline(nY);
859  for( nX = 0; nX < nNewWidth; nX++ )
860  pWriteAcc->SetPixelOnData( pScanline, nX, aColor );
861  }
862 
863  pWriteAcc.reset();
864  bRet = true;
865  }
866 
867  pReadAcc.reset();
868 
869  if (bRet)
870  ReassignWithSize(aNewBmp);
871  }
872  }
873 
874  return bRet;
875 }
876 
878 {
879  Bitmap aDispBmp( *this );
880 
881  SalGraphics* pDispGraphics = pDisplay->GetGraphics();
882 
883  if( mxSalBmp && pDispGraphics )
884  {
885  std::shared_ptr<SalBitmap> xImpDispBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
886  if (xImpDispBmp->Create(*mxSalBmp, pDispGraphics))
887  aDispBmp.ImplSetSalBitmap(xImpDispBmp);
888  }
889 
890  return aDispBmp;
891 }
892 
894 {
895  return mxSalBmp && mxSalBmp->GetSystemData(rData);
896 }
897 
898 
899 bool Bitmap::Convert( BmpConversion eConversion )
900 {
901  // try to convert in backend
902  if (mxSalBmp)
903  {
904  // avoid large chunk of obsolete and hopefully rarely used conversions.
905  if (eConversion == BmpConversion::N8BitNoConversion)
906  {
907  if (mxSalBmp->GetBitCount() == 8 && HasGreyPalette8Bit())
908  return true;
909  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
910  // frequently used conversion for creating alpha masks
911  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->InterpretAs8Bit())
912  {
913  ImplSetSalBitmap(xImpBmp);
914  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
915  return true;
916  }
917  }
918  if (eConversion == BmpConversion::N8BitGreys)
919  {
920  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
921  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->ConvertToGreyscale())
922  {
923  ImplSetSalBitmap(xImpBmp);
924  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
925  return true;
926  }
927  }
928  }
929 
930  const sal_uInt16 nBitCount = vcl::pixelFormatBitCount(getPixelFormat());
931  bool bRet = false;
932 
933  switch( eConversion )
934  {
936  {
937  BitmapEx aBmpEx(*this);
938  bRet = BitmapFilter::Filter(aBmpEx, BitmapMonochromeFilter(128));
939  *this = aBmpEx.GetBitmap();
940  }
941  break;
942 
945  bRet = ImplMakeGreyscales();
946  break;
947 
949  {
950  if( nBitCount < 8 )
952  else if( nBitCount > 8 )
953  bRet = ImplConvertDown8BPP();
954  else
955  bRet = true;
956  }
957  break;
958 
960  {
961  Color aTrans( BMP_COL_TRANS );
962 
963  if( nBitCount < 8 )
964  bRet = ImplConvertUp(vcl::PixelFormat::N8_BPP, &aTrans );
965  else
966  bRet = ImplConvertDown8BPP(&aTrans );
967  }
968  break;
969 
971  {
972  if( nBitCount < 24 )
974  else
975  bRet = true;
976  }
977  break;
978 
980  {
981  if( nBitCount < 32 )
983  else
984  bRet = true;
985  }
986  break;
987 
988  default:
989  OSL_FAIL( "Bitmap::Convert(): Unsupported conversion" );
990  break;
991  }
992 
993  return bRet;
994 }
995 
997 {
998  ScopedReadAccess pReadAcc(*this);
999  bool bRet = false;
1000 
1001  if( pReadAcc )
1002  {
1003  const BitmapPalette& rPal = GetGreyPalette(256);
1004  sal_uLong nShift = 0;
1005  bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
1006 
1007  if( !bPalDiffers )
1008  bPalDiffers = ( rPal != pReadAcc->GetPalette() );
1009 
1010  if( bPalDiffers )
1011  {
1012  const auto ePixelFormat = vcl::PixelFormat::N8_BPP;
1013  Bitmap aNewBmp(GetSizePixel(), ePixelFormat, &rPal );
1014  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
1015 
1016  if( pWriteAcc )
1017  {
1018  const tools::Long nWidth = pWriteAcc->Width();
1019  const tools::Long nHeight = pWriteAcc->Height();
1020 
1021  if( pReadAcc->HasPalette() )
1022  {
1023  for( tools::Long nY = 0; nY < nHeight; nY++ )
1024  {
1025  Scanline pScanline = pWriteAcc->GetScanline(nY);
1026  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
1027  for( tools::Long nX = 0; nX < nWidth; nX++ )
1028  {
1029  const sal_uInt8 cIndex = pReadAcc->GetIndexFromData( pScanlineRead, nX );
1030  pWriteAcc->SetPixelOnData( pScanline, nX,
1031  BitmapColor(pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
1032  }
1033  }
1034  }
1035  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr &&
1036  pWriteAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal )
1037  {
1038  nShift += 8;
1039 
1040  for( tools::Long nY = 0; nY < nHeight; nY++ )
1041  {
1042  Scanline pReadScan = pReadAcc->GetScanline( nY );
1043  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
1044 
1045  for( tools::Long nX = 0; nX < nWidth; nX++ )
1046  {
1047  const sal_uLong nB = *pReadScan++;
1048  const sal_uLong nG = *pReadScan++;
1049  const sal_uLong nR = *pReadScan++;
1050 
1051  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
1052  }
1053  }
1054  }
1055  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb &&
1056  pWriteAcc->GetScanlineFormat() == ScanlineFormat::N8BitPal )
1057  {
1058  nShift += 8;
1059 
1060  for( tools::Long nY = 0; nY < nHeight; nY++ )
1061  {
1062  Scanline pReadScan = pReadAcc->GetScanline( nY );
1063  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
1064 
1065  for( tools::Long nX = 0; nX < nWidth; nX++ )
1066  {
1067  const sal_uLong nR = *pReadScan++;
1068  const sal_uLong nG = *pReadScan++;
1069  const sal_uLong nB = *pReadScan++;
1070 
1071  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
1072  }
1073  }
1074  }
1075  else
1076  {
1077  for( tools::Long nY = 0; nY < nHeight; nY++ )
1078  {
1079  Scanline pScanline = pWriteAcc->GetScanline(nY);
1080  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
1081  for( tools::Long nX = 0; nX < nWidth; nX++ )
1082  pWriteAcc->SetPixelOnData( pScanline, nX, BitmapColor(pReadAcc->GetPixelFromData( pScanlineRead, nX ).GetLuminance() >> nShift) );
1083  }
1084  }
1085 
1086  pWriteAcc.reset();
1087  bRet = true;
1088  }
1089 
1090  pReadAcc.reset();
1091 
1092  if( bRet )
1093  {
1094  const MapMode aMap( maPrefMapMode );
1095  const Size aSize( maPrefSize );
1096 
1097  *this = aNewBmp;
1098 
1099  maPrefMapMode = aMap;
1100  maPrefSize = aSize;
1101  }
1102  }
1103  else
1104  {
1105  pReadAcc.reset();
1106  bRet = true;
1107  }
1108  }
1109 
1110  return bRet;
1111 }
1112 
1113 bool Bitmap::ImplConvertUp(vcl::PixelFormat ePixelFormat, Color const * pExtColor)
1114 {
1115  SAL_WARN_IF(ePixelFormat <= getPixelFormat(), "vcl", "New pixel format must be greater!" );
1116 
1117  Bitmap::ScopedReadAccess pReadAcc(*this);
1118  bool bRet = false;
1119 
1120  if (pReadAcc)
1121  {
1122  BitmapPalette aPalette;
1123  Bitmap aNewBmp(GetSizePixel(), ePixelFormat, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPalette);
1124  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
1125 
1126  if (pWriteAcc)
1127  {
1128  const tools::Long nWidth = pWriteAcc->Width();
1129  const tools::Long nHeight = pWriteAcc->Height();
1130 
1131  if (pWriteAcc->HasPalette())
1132  {
1133  const BitmapPalette& rOldPalette = pReadAcc->GetPalette();
1134  const sal_uInt16 nOldCount = rOldPalette.GetEntryCount();
1135  assert(nOldCount <= (1 << vcl::pixelFormatBitCount(getPixelFormat())));
1136 
1137  aPalette.SetEntryCount(1 << vcl::pixelFormatBitCount(ePixelFormat));
1138 
1139  for (sal_uInt16 i = 0; i < nOldCount; i++)
1140  aPalette[i] = rOldPalette[i];
1141 
1142  if (pExtColor)
1143  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
1144 
1145  pWriteAcc->SetPalette(aPalette);
1146 
1147  for (tools::Long nY = 0; nY < nHeight; nY++)
1148  {
1149  Scanline pScanline = pWriteAcc->GetScanline(nY);
1150  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
1151  for (tools::Long nX = 0; nX < nWidth; nX++)
1152  {
1153  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
1154  }
1155  }
1156  }
1157  else
1158  {
1159  if (pReadAcc->HasPalette())
1160  {
1161  for (tools::Long nY = 0; nY < nHeight; nY++)
1162  {
1163  Scanline pScanline = pWriteAcc->GetScanline(nY);
1164  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
1165  for (tools::Long nX = 0; nX < nWidth; nX++)
1166  {
1167  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX)));
1168  }
1169  }
1170  }
1171  else
1172  {
1173  for (tools::Long nY = 0; nY < nHeight; nY++)
1174  {
1175  Scanline pScanline = pWriteAcc->GetScanline(nY);
1176  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
1177  for (tools::Long nX = 0; nX < nWidth; nX++)
1178  {
1179  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
1180  }
1181  }
1182  }
1183  }
1184  bRet = true;
1185  }
1186 
1187  if (bRet)
1188  {
1189  const MapMode aMap(maPrefMapMode);
1190  const Size aSize(maPrefSize);
1191 
1192  *this = aNewBmp;
1193 
1194  maPrefMapMode = aMap;
1195  maPrefSize = aSize;
1196  }
1197  }
1198 
1199  return bRet;
1200 }
1201 
1202 bool Bitmap::ImplConvertDown8BPP(Color const * pExtColor)
1203 {
1204  SAL_WARN_IF(vcl::PixelFormat::N8_BPP > getPixelFormat(), "vcl", "New pixelformat must be lower ( or equal when pExtColor is set )!");
1205 
1206  Bitmap::ScopedReadAccess pReadAcc(*this);
1207  bool bRet = false;
1208 
1209  if (pReadAcc)
1210  {
1211  BitmapPalette aPalette;
1212  Bitmap aNewBmp(GetSizePixel(), vcl::PixelFormat::N8_BPP, &aPalette);
1213  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
1214 
1215  if (pWriteAcc)
1216  {
1217  sal_Int16 nNewBitCount = sal_Int16(vcl::PixelFormat::N8_BPP);
1218  const sal_uInt16 nCount = 1 << nNewBitCount;
1219  const tools::Long nWidth = pWriteAcc->Width();
1220  const tools::Long nWidth1 = nWidth - 1;
1221  const tools::Long nHeight = pWriteAcc->Height();
1222  Octree aOctree(*pReadAcc, pExtColor ? (nCount - 1) : nCount);
1223  aPalette = aOctree.GetPalette();
1224  InverseColorMap aColorMap(aPalette);
1225  BitmapColor aColor;
1226  ImpErrorQuad aErrQuad;
1227  std::vector<ImpErrorQuad> aErrQuad1(nWidth);
1228  std::vector<ImpErrorQuad> aErrQuad2(nWidth);
1229  ImpErrorQuad* pQLine1 = aErrQuad1.data();
1230  ImpErrorQuad* pQLine2 = nullptr;
1231  tools::Long nYTmp = 0;
1232  sal_uInt8 cIndex;
1233  bool bQ1 = true;
1234 
1235  if (pExtColor)
1236  {
1237  aPalette.SetEntryCount(aPalette.GetEntryCount() + 1);
1238  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
1239  }
1240 
1241  // set Black/White always, if we have enough space
1242  if (aPalette.GetEntryCount() < (nCount - 1))
1243  {
1244  aPalette.SetEntryCount(aPalette.GetEntryCount() + 2);
1245  aPalette[aPalette.GetEntryCount() - 2] = COL_BLACK;
1246  aPalette[aPalette.GetEntryCount() - 1] = COL_WHITE;
1247  }
1248 
1249  pWriteAcc->SetPalette(aPalette);
1250 
1251  for (tools::Long nY = 0; nY < std::min(nHeight, tools::Long(2)); nY++, nYTmp++)
1252  {
1253  pQLine2 = !nY ? aErrQuad1.data() : aErrQuad2.data();
1254  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
1255  for (tools::Long nX = 0; nX < nWidth; nX++)
1256  {
1257  if (pReadAcc->HasPalette())
1258  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
1259  else
1260  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
1261  }
1262  }
1263 
1264  assert(pQLine2 || nHeight == 0);
1265 
1266  for (tools::Long nY = 0; nY < nHeight; nY++, nYTmp++)
1267  {
1268  // first pixel in the line
1269  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[0].ImplGetColor()));
1270  Scanline pScanline = pWriteAcc->GetScanline(nY);
1271  pWriteAcc->SetPixelOnData(pScanline, 0, BitmapColor(cIndex));
1272 
1273  tools::Long nX;
1274  for (nX = 1; nX < nWidth1; nX++)
1275  {
1276  aColor = pQLine1[nX].ImplGetColor();
1277  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(aColor));
1278  aErrQuad = (ImpErrorQuad(aColor) -= pWriteAcc->GetPaletteColor(cIndex));
1279  pQLine1[++nX].ImplAddColorError7(aErrQuad);
1280  pQLine2[nX--].ImplAddColorError1(aErrQuad);
1281  pQLine2[nX--].ImplAddColorError5(aErrQuad);
1282  pQLine2[nX++].ImplAddColorError3(aErrQuad);
1283  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
1284  }
1285 
1286  // Last RowPixel
1287  if (nX < nWidth)
1288  {
1289  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[nWidth1].ImplGetColor()));
1290  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
1291  }
1292 
1293  // Refill/copy row buffer
1294  pQLine1 = pQLine2;
1295  bQ1 = !bQ1;
1296  pQLine2 = bQ1 ? aErrQuad2.data() : aErrQuad1.data();
1297 
1298  if (nYTmp < nHeight)
1299  {
1300  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
1301  for (nX = 0; nX < nWidth; nX++)
1302  {
1303  if (pReadAcc->HasPalette())
1304  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
1305  else
1306  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
1307  }
1308  }
1309  }
1310 
1311  bRet = true;
1312  }
1313  pWriteAcc.reset();
1314 
1315  if(bRet)
1316  {
1317  const MapMode aMap(maPrefMapMode);
1318  const Size aSize(maPrefSize);
1319 
1320  *this = aNewBmp;
1321 
1322  maPrefMapMode = aMap;
1323  maPrefSize = aSize;
1324  }
1325  }
1326 
1327  return bRet;
1328 }
1329 
1330 bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
1331 {
1333  {
1334  // no scale
1335  return true;
1336  }
1337 
1338  if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
1339  {
1340  // no scale
1341  return true;
1342  }
1343 
1344  const auto eStartPixelFormat = getPixelFormat();
1345 
1346  if (mxSalBmp && mxSalBmp->ScalingSupported())
1347  {
1348  // implementation specific scaling
1349  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
1350  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->Scale(rScaleX, rScaleY, nScaleFlag))
1351  {
1352  ImplSetSalBitmap(xImpBmp);
1353  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
1354  maPrefMapMode = MapMode( MapUnit::MapPixel );
1355  maPrefSize = xImpBmp->GetSize();
1356  return true;
1357  }
1358  }
1359 
1360  // fdo#33455
1361  //
1362  // If we start with a 1 bit image, then after scaling it in any mode except
1363  // BmpScaleFlag::Fast we have a 24bit image which is perfectly correct, but we
1364  // are going to down-shift it to mono again and Bitmap::MakeMonochrome just
1365  // has "Bitmap aNewBmp( GetSizePixel(), 1 );" to create a 1 bit bitmap which
1366  // will default to black/white and the colors mapped to which ever is closer
1367  // to black/white
1368  //
1369  // So the easiest thing to do to retain the colors of 1 bit bitmaps is to
1370  // just use the fast scale rather than attempting to count unique colors in
1371  // the other converters and pass all the info down through
1372  // Bitmap::MakeMonochrome
1373  if (eStartPixelFormat == vcl::PixelFormat::N1_BPP)
1374  nScaleFlag = BmpScaleFlag::Fast;
1375 
1376  BitmapEx aBmpEx(*this);
1377  bool bRetval(false);
1378 
1379  switch(nScaleFlag)
1380  {
1381  case BmpScaleFlag::Default:
1382  if (GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
1383  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
1384  else
1385  bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
1386  break;
1387 
1388  case BmpScaleFlag::Fast:
1390  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
1391  break;
1392 
1394  bRetval = BitmapFilter::Filter(aBmpEx, BitmapInterpolateScaleFilter(rScaleX, rScaleY));
1395  break;
1396 
1398  case BmpScaleFlag::Lanczos:
1399  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleLanczos3Filter(rScaleX, rScaleY));
1400  break;
1401 
1402  case BmpScaleFlag::BiCubic:
1403  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBicubicFilter(rScaleX, rScaleY));
1404  break;
1405 
1407  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBilinearFilter(rScaleX, rScaleY));
1408  break;
1409  }
1410 
1411  if (bRetval)
1412  *this = aBmpEx.GetBitmap();
1413 
1414  OSL_ENSURE(!bRetval || eStartPixelFormat == getPixelFormat(), "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
1415  return bRetval;
1416 }
1417 
1418 bool Bitmap::Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag )
1419 {
1420  const Size aSize( GetSizePixel() );
1421  bool bRet;
1422 
1423  if( aSize.Width() && aSize.Height() )
1424  {
1425  bRet = Scale( static_cast<double>(rNewSize.Width()) / aSize.Width(),
1426  static_cast<double>(rNewSize.Height()) / aSize.Height(),
1427  nScaleFlag );
1428  }
1429  else
1430  bRet = true;
1431 
1432  return bRet;
1433 }
1434 
1436 {
1437 #if HAVE_FEATURE_SKIA
1438  if( SkiaHelper::isVCLSkiaEnabled() && SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster)
1439  return true;
1440 #endif
1441  return false;
1442 }
1443 
1445 {
1446  // aNew is the result of some operation; adapt it's BitCount to the original (this)
1447  if (getPixelFormat() == rNew.getPixelFormat())
1448  return;
1449 
1450  switch (getPixelFormat())
1451  {
1453  {
1455  break;
1456  }
1458  {
1459  if(HasGreyPaletteAny())
1460  {
1462  }
1463  else
1464  {
1466  }
1467  break;
1468  }
1470  {
1472  break;
1473  }
1475  {
1477  break;
1478  }
1480  {
1481  SAL_WARN("vcl", "Can't adapt the pixelformat as it is invalid.");
1482  break;
1483  }
1484  }
1485 }
1486 
1487 static sal_Int32* shiftColor(sal_Int32* pColorArray, BitmapColor const& rColor)
1488 {
1489  *pColorArray++ = static_cast<sal_Int32>(rColor.GetBlue()) << 12;
1490  *pColorArray++ = static_cast<sal_Int32>(rColor.GetGreen()) << 12;
1491  *pColorArray++ = static_cast<sal_Int32>(rColor.GetRed()) << 12;
1492  return pColorArray;
1493 }
1495 {
1496  Scanline pScanlineRead = pReadAcc->GetScanline(0);
1497  if (pReadAcc->HasPalette())
1498  return pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nZ));
1499  else
1500  return pReadAcc->GetPixelFromData(pScanlineRead, nZ);
1501 }
1502 
1504 {
1505  const Size aSize( GetSizePixel() );
1506  if( aSize.Width() == 1 || aSize.Height() == 1 )
1507  return true;
1508  if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
1509  {
1510  ScopedReadAccess pReadAcc(*this);
1512  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
1513  if( pReadAcc && pWriteAcc )
1514  {
1515  BitmapColor aColor;
1516  tools::Long nWidth = pReadAcc->Width();
1517  tools::Long nWidth1 = nWidth - 1;
1518  tools::Long nHeight = pReadAcc->Height();
1519  tools::Long nW = nWidth * 3;
1520  tools::Long nW2 = nW - 3;
1521  std::unique_ptr<sal_Int32[]> p1(new sal_Int32[ nW ]);
1522  std::unique_ptr<sal_Int32[]> p2(new sal_Int32[ nW ]);
1523  sal_Int32* p1T = p1.get();
1524  sal_Int32* p2T = p2.get();
1525  sal_Int32* pTmp = p2T;
1526  for (tools::Long nZ = 0; nZ < nWidth; nZ++)
1527  {
1528  pTmp = shiftColor(pTmp, getColor(pReadAcc.get(), nZ));
1529  }
1530  tools::Long nRErr, nGErr, nBErr;
1531  tools::Long nRC, nGC, nBC;
1532  for( tools::Long nY = 1, nYAcc = 0; nY <= nHeight; nY++, nYAcc++ )
1533  {
1534  pTmp = p1T;
1535  p1T = p2T;
1536  p2T = pTmp;
1537  if (nY < nHeight)
1538  {
1539  for (tools::Long nZ = 0; nZ < nWidth; nZ++)
1540  {
1541  pTmp = shiftColor(pTmp, getColor(pReadAcc.get(), nZ));
1542  }
1543  }
1544  // Examine first Pixel separately
1545  tools::Long nX = 0;
1546  tools::Long nTemp;
1547  CALC_ERRORS;
1548  CALC_TABLES7;
1549  nX -= 5;
1550  CALC_TABLES5;
1551  Scanline pScanline = pWriteAcc->GetScanline(nYAcc);
1552  pWriteAcc->SetPixelOnData( pScanline, 0, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1553  // Get middle Pixels using a loop
1554  tools::Long nXAcc;
1555  for ( nX = 3, nXAcc = 1; nX < nW2; nXAcc++ )
1556  {
1557  CALC_ERRORS;
1558  CALC_TABLES7;
1559  nX -= 8;
1560  CALC_TABLES3;
1561  CALC_TABLES5;
1562  pWriteAcc->SetPixelOnData( pScanline, nXAcc, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1563  }
1564  // Treat last Pixel separately
1565  CALC_ERRORS;
1566  nX -= 5;
1567  CALC_TABLES3;
1568  CALC_TABLES5;
1569  pWriteAcc->SetPixelOnData( pScanline, nWidth1, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1570  }
1571  pReadAcc.reset();
1572  pWriteAcc.reset();
1573  const MapMode aMap( maPrefMapMode );
1574  const Size aPrefSize( maPrefSize );
1575  *this = aNewBmp;
1576  maPrefMapMode = aMap;
1577  maPrefSize = aPrefSize;
1578  return true;
1579  }
1580  pReadAcc.reset();
1581  pWriteAcc.reset();
1582  }
1583  return false;
1584 }
1585 
1586 void Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, const Link<tools::Long,void>* pProgress )
1587 {
1588  ImplVectorizer::ImplVectorize( *this, rMtf, cReduce, pProgress );
1589 }
1590 
1591 bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
1592  short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
1593  double fGamma, bool bInvert, bool msoBrightness )
1594 {
1595  bool bRet = false;
1596 
1597  // nothing to do => return quickly
1598  if( !nLuminancePercent && !nContrastPercent &&
1599  !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
1600  ( fGamma == 1.0 ) && !bInvert )
1601  {
1602  bRet = true;
1603  }
1604  else
1605  {
1606  BitmapScopedWriteAccess pAcc(*this);
1607 
1608  if( pAcc )
1609  {
1610  BitmapColor aCol;
1611  const tools::Long nW = pAcc->Width();
1612  const tools::Long nH = pAcc->Height();
1613  std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]);
1614  std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]);
1615  std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]);
1616  double fM, fROff, fGOff, fBOff, fOff;
1617 
1618  // calculate slope
1619  if( nContrastPercent >= 0 )
1620  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
1621  else
1622  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
1623 
1624  if(!msoBrightness)
1625  // total offset = luminance offset + contrast offset
1626  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
1627  else
1628  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
1629 
1630  // channel offset = channel offset + total offset
1631  fROff = nChannelRPercent * 2.55 + fOff;
1632  fGOff = nChannelGPercent * 2.55 + fOff;
1633  fBOff = nChannelBPercent * 2.55 + fOff;
1634 
1635  // calculate gamma value
1636  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
1637  const bool bGamma = ( fGamma != 1.0 );
1638 
1639  // create mapping table
1640  for( tools::Long nX = 0; nX < 256; nX++ )
1641  {
1642  if(!msoBrightness)
1643  {
1644  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
1645  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
1646  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
1647  }
1648  else
1649  {
1650  // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128"
1651  // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason,
1652  // use neither first, but apparently it applies half of brightness before contrast and half afterwards.
1653  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
1654  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
1655  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
1656  }
1657  if( bGamma )
1658  {
1659  cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
1660  cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
1661  cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
1662  }
1663 
1664  if( bInvert )
1665  {
1666  cMapR[ nX ] = ~cMapR[ nX ];
1667  cMapG[ nX ] = ~cMapG[ nX ];
1668  cMapB[ nX ] = ~cMapB[ nX ];
1669  }
1670  }
1671 
1672  // do modifying
1673  if( pAcc->HasPalette() )
1674  {
1675  BitmapColor aNewCol;
1676 
1677  for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
1678  {
1679  const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1680  aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
1681  aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
1682  aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
1683  pAcc->SetPaletteColor( i, aNewCol );
1684  }
1685  }
1686  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr )
1687  {
1688  for( tools::Long nY = 0; nY < nH; nY++ )
1689  {
1690  Scanline pScan = pAcc->GetScanline( nY );
1691 
1692  for( tools::Long nX = 0; nX < nW; nX++ )
1693  {
1694  *pScan = cMapB[ *pScan ]; pScan++;
1695  *pScan = cMapG[ *pScan ]; pScan++;
1696  *pScan = cMapR[ *pScan ]; pScan++;
1697  }
1698  }
1699  }
1700  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb )
1701  {
1702  for( tools::Long nY = 0; nY < nH; nY++ )
1703  {
1704  Scanline pScan = pAcc->GetScanline( nY );
1705 
1706  for( tools::Long nX = 0; nX < nW; nX++ )
1707  {
1708  *pScan = cMapR[ *pScan ]; pScan++;
1709  *pScan = cMapG[ *pScan ]; pScan++;
1710  *pScan = cMapB[ *pScan ]; pScan++;
1711  }
1712  }
1713  }
1714  else
1715  {
1716  for( tools::Long nY = 0; nY < nH; nY++ )
1717  {
1718  Scanline pScanline = pAcc->GetScanline(nY);
1719  for( tools::Long nX = 0; nX < nW; nX++ )
1720  {
1721  aCol = pAcc->GetPixelFromData( pScanline, nX );
1722  aCol.SetRed( cMapR[ aCol.GetRed() ] );
1723  aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
1724  aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
1725  pAcc->SetPixelOnData( pScanline, nX, aCol );
1726  }
1727  }
1728  }
1729 
1730  pAcc.reset();
1731  bRet = true;
1732  }
1733  }
1734 
1735  return bRet;
1736 }
1737 
1738 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PixelFormat
Pixel format of the bitmap in bits per pixel.
Definition: BitmapTypes.hxx:19
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
static bool HasFastScale()
Returns true if bitmap scaling is considered to be fast.
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
bool Adjust(short nLuminancePercent, short nContrastPercent=0, short nChannelRPercent=0, short nChannelGPercent=0, short nChannelBPercent=0, double fGamma=1.0, bool bInvert=false, bool msoBrightness=false)
Change various global color characteristics.
bool IsGreyPalette8Bit() const
Returns true if the palette is 8-bit grey palette.
tools::Long Height() const
sal_uInt8 GetRed() const
void SetBlue(sal_uInt8 nBlue)
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTMAGENTA
void setWidth(tools::Long nWidth)
BitmapInfoAccess * AcquireInfoAccess()
void SetEntryCount(sal_uInt16 nCount)
bool equalZero(const T &rfVal)
constexpr bool isPalettePixelFormat(PixelFormat ePixelFormat)
Is it a pixel format that forces creation of a palette.
Definition: BitmapTypes.hxx:29
constexpr tools::Long Left() const
bool operator==(const Bitmap &rBitmap) const
constexpr::Color COL_RED(0x80, 0x00, 0x00)
bool Expand(sal_Int32 nDX, sal_Int32 nDY, const Color *pInitColor=nullptr)
Expand the bitmap by pixel padding.
#define CALC_TABLES5
Definition: floyd.hxx:38
sal_uIntPtr sal_uLong
ErrCode compressAsPNG(const Graphic &rGraphic, SvStream &rOutputStream)
long Long
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, tools::Long nMin, tools::Long nMax)
sal_uInt8 GetLuminance() const
Class to import and export graphic formats.
BitmapReadAccess * AcquireReadAccess()
constexpr::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
Size GetSizePixel() const
static BitmapColor getColor(const BitmapReadAccess *pReadAcc, tools::Long nZ)
void ImplAddColorError1(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:73
constexpr::Color COL_MAGENTA(0x80, 0x00, 0x80)
constexpr tools::Long Width() const
HashMap_OWString_Interface aMap
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
#define CALC_ERRORS
Definition: floyd.hxx:22
bool HasGreyPalette8Bit() const
Scanline GetScanline(tools::Long nY) const
constexpr::Color COL_CYAN(0x00, 0x80, 0x80)
int nCount
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
#define GAMMA(_def_cVal, _def_InvGamma)
#define BMP_COL_TRANS
constexpr tools::Long GetWidth() const
sal_uInt8 GetBlue() const
#define CALC_TABLES3
Definition: floyd.hxx:33
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTRED
Bitmap & operator=(const Bitmap &rBitmap)
bool Dither()
Apply a Floyd dither algorithm to the bitmap.
constexpr bool IsEmpty() const
SAL_DLLPRIVATE bool ImplConvertUp(vcl::PixelFormat ePixelFormat, Color const *pExtColor=nullptr)
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:75
sal_uInt16 GetEntryCount() const
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
const sal_uLong nVCLBLut[6]
vcl::PixelFormat getPixelFormat() const
Bitmap CreateDisplayBitmap(OutputDevice *pDisplay) const
int i
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
static sal_Int32 * shiftColor(sal_Int32 *pColorArray, BitmapColor const &rColor)
bool equal(T const &rfValA, T const &rfValB)
tools::Long FRound(double fVal)
void ImplAddColorError5(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:87
BitmapChecksum GetChecksum() const
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_GRAY
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:175
tools::Long Width() const
void SetRed(sal_uInt8 nRed)
bool GetSystemData(BitmapSystemData &rData) const
get system dependent bitmap data
constexpr tools::Long Top() const
static void ReleaseAccess(BitmapInfoAccess *pAccess)
bool ImplVectorize(const Bitmap &rColorBmp, GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
Definition: impvect.cxx:644
bool CopyPixel_AlphaOptimized(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc)
short nBitCount
Definition: ipict.cxx:80
sal_uInt16 GetPaletteEntryCount() const
void SetEmpty()
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
void ImplAddColorError3(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:80
const sal_uLong nVCLGLut[6]
sal_uInt8 GetGreen() const
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTCYAN
constexpr Size GetSize() const
virtual std::shared_ptr< SalBitmap > CreateSalBitmap()=0
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
#define CALC_TABLES7
Definition: floyd.hxx:43
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
unsigned char sal_uInt8
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
constexpr::Color COL_GREEN(0x00, 0x80, 0x00)
bool Convert(BmpConversion eConversion)
Convert bitmap format.
void Vectorize(GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
Convert the bitmap to a meta file.
bool HasGreyPaletteAny() const
void SetGreen(sal_uInt8 nGreen)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_WHITE
const BitmapPalette & GetPalette() const
#define SAL_INFO(area, stream)
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BROWN
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTGREEN
SAL_DLLPRIVATE bool ImplMakeGreyscales()
SalGraphics const * GetGraphics() const
Get the graphic context that the output device uses to draw on.
Definition: outdev.cxx:202
BitmapWriteAccess * AcquireWriteAccess()
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_YELLOW
constexpr sal_uInt16 pixelFormatBitCount(PixelFormat ePixelFormat)
Definition: BitmapTypes.hxx:35
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
void AdaptBitCount(Bitmap &rNew) const
SAL_DLLPRIVATE void ImplMakeUnique()
void ImplAddColorError7(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:94
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_LIGHTBLUE
void setHeight(tools::Long nHeight)
static GraphicFilter & GetGraphicFilter()
SAL_DLLPRIVATE bool ImplConvertDown8BPP(Color const *pExtColor=nullptr)
MapUnit
const sal_uLong nVCLRLut[6]
#define SAL_WARN(area, stream)
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
constexpr::Color COL_BLUE(0x00, 0x00, 0x80)
SAL_DLLPRIVATE void ReassignWithSize(const Bitmap &rBitmap)
ReassignWithSize and recalculate bitmap.
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc=nullptr)
Copy a rectangular area from another bitmap.
MapMode maPrefMapMode
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rColor)
Definition: Octree.cxx:273
virtual ~Bitmap()
std::shared_ptr< SalBitmap > mxSalBmp
BitmapColor ImplGetColor() const
Definition: impoctree.hxx:101
SalInstance * mpDefInst
Definition: svdata.hxx:390
static const BitmapPalette & GetGreyPalette(int nEntries)
bool IsGreyPaletteAny() const
Returns true if the palette is a grey palette (may not be 8-bit).
const BitmapPalette & GetPalette()
Definition: Octree.cxx:197
constexpr tools::Long GetHeight() const
SAL_DLLPRIVATE void ImplSetSalBitmap(const std::shared_ptr< SalBitmap > &xImpBmp)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo