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
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
63Bitmap::Bitmap(const Bitmap& rBitmap)
64 : mxSalBmp(rBitmap.mxSalBmp)
65 , maPrefMapMode(rBitmap.maPrefMapMode)
66 , maPrefSize(rBitmap.maPrefSize)
67{
68}
69
70Bitmap::Bitmap(std::shared_ptr<SalBitmap> const & pSalBitmap)
71 : mxSalBmp(pSalBitmap)
72 , maPrefMapMode(MapMode(MapUnit::MapPixel))
73 , maPrefSize(mxSalBmp->GetSize())
74{
75}
76
77Bitmap::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
140namespace
141{
142void 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
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
233{
234 if (this == &rBitmap)
235 return *this;
236
237 maPrefSize = rBitmap.maPrefSize;
239 mxSalBmp = rBitmap.mxSalBmp;
240
241 return *this;
242}
243
244Bitmap& 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
253bool 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{
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
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
387void 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
433bool 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
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
812bool 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
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
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
1100 maPrefSize = aSize;
1101 }
1102 }
1103 else
1104 {
1105 pReadAcc.reset();
1106 bRet = true;
1107 }
1108 }
1109
1110 return bRet;
1111}
1112
1113bool 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
1195 maPrefSize = aSize;
1196 }
1197 }
1198
1199 return bRet;
1200}
1201
1202bool 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
1323 maPrefSize = aSize;
1324 }
1325 }
1326
1327 return bRet;
1328}
1329
1330bool 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 {
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
1399 bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleLanczos3Filter(rScaleX, rScaleY));
1400 break;
1401
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
1418bool 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
1487static 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 tools::Long nWidth = pReadAcc->Width();
1516 tools::Long nWidth1 = nWidth - 1;
1517 tools::Long nHeight = pReadAcc->Height();
1518 tools::Long nW = nWidth * 3;
1519 tools::Long nW2 = nW - 3;
1520 std::unique_ptr<sal_Int32[]> p1(new sal_Int32[ nW ]);
1521 std::unique_ptr<sal_Int32[]> p2(new sal_Int32[ nW ]);
1522 sal_Int32* p1T = p1.get();
1523 sal_Int32* p2T = p2.get();
1524 sal_Int32* pTmp = p2T;
1525 for (tools::Long nZ = 0; nZ < nWidth; nZ++)
1526 {
1527 pTmp = shiftColor(pTmp, getColor(pReadAcc.get(), nZ));
1528 }
1529 tools::Long nRErr, nGErr, nBErr;
1530 tools::Long nRC, nGC, nBC;
1531 for( tools::Long nY = 1, nYAcc = 0; nY <= nHeight; nY++, nYAcc++ )
1532 {
1533 pTmp = p1T;
1534 p1T = p2T;
1535 p2T = pTmp;
1536 if (nY < nHeight)
1537 {
1538 for (tools::Long nZ = 0; nZ < nWidth; nZ++)
1539 {
1540 pTmp = shiftColor(pTmp, getColor(pReadAcc.get(), nZ));
1541 }
1542 }
1543 // Examine first Pixel separately
1544 tools::Long nX = 0;
1545 tools::Long nTemp;
1548 nX -= 5;
1550 Scanline pScanline = pWriteAcc->GetScanline(nYAcc);
1551 pWriteAcc->SetPixelOnData( pScanline, 0, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1552 // Get middle Pixels using a loop
1553 tools::Long nXAcc;
1554 for ( nX = 3, nXAcc = 1; nX < nW2; nXAcc++ )
1555 {
1558 nX -= 8;
1561 pWriteAcc->SetPixelOnData( pScanline, nXAcc, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1562 }
1563 // Treat last Pixel separately
1565 nX -= 5;
1568 pWriteAcc->SetPixelOnData( pScanline, nWidth1, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1569 }
1570 pReadAcc.reset();
1571 pWriteAcc.reset();
1572 const MapMode aMap( maPrefMapMode );
1573 const Size aPrefSize( maPrefSize );
1574 *this = aNewBmp;
1576 maPrefSize = aPrefSize;
1577 return true;
1578 }
1579 pReadAcc.reset();
1580 pWriteAcc.reset();
1581 }
1582 return false;
1583}
1584
1585void Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, const Link<tools::Long,void>* pProgress )
1586{
1587 ImplVectorizer::ImplVectorize( *this, rMtf, cReduce, pProgress );
1588}
1589
1590bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
1591 short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
1592 double fGamma, bool bInvert, bool msoBrightness )
1593{
1594 bool bRet = false;
1595
1596 // nothing to do => return quickly
1597 if( !nLuminancePercent && !nContrastPercent &&
1598 !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
1599 ( fGamma == 1.0 ) && !bInvert )
1600 {
1601 bRet = true;
1602 }
1603 else
1604 {
1605 BitmapScopedWriteAccess pAcc(*this);
1606
1607 if( pAcc )
1608 {
1609 BitmapColor aCol;
1610 const tools::Long nW = pAcc->Width();
1611 const tools::Long nH = pAcc->Height();
1612 std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]);
1613 std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]);
1614 std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]);
1615 double fM, fROff, fGOff, fBOff, fOff;
1616
1617 // calculate slope
1618 if( nContrastPercent >= 0 )
1619 fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
1620 else
1621 fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
1622
1623 if(!msoBrightness)
1624 // total offset = luminance offset + contrast offset
1625 fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
1626 else
1627 fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
1628
1629 // channel offset = channel offset + total offset
1630 fROff = nChannelRPercent * 2.55 + fOff;
1631 fGOff = nChannelGPercent * 2.55 + fOff;
1632 fBOff = nChannelBPercent * 2.55 + fOff;
1633
1634 // calculate gamma value
1635 fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
1636 const bool bGamma = ( fGamma != 1.0 );
1637
1638 // create mapping table
1639 for( tools::Long nX = 0; nX < 256; nX++ )
1640 {
1641 if(!msoBrightness)
1642 {
1643 cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
1644 cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
1645 cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
1646 }
1647 else
1648 {
1649 // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128"
1650 // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason,
1651 // use neither first, but apparently it applies half of brightness before contrast and half afterwards.
1652 cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
1653 cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
1654 cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
1655 }
1656 if( bGamma )
1657 {
1658 cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
1659 cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
1660 cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
1661 }
1662
1663 if( bInvert )
1664 {
1665 cMapR[ nX ] = ~cMapR[ nX ];
1666 cMapG[ nX ] = ~cMapG[ nX ];
1667 cMapB[ nX ] = ~cMapB[ nX ];
1668 }
1669 }
1670
1671 // do modifying
1672 if( pAcc->HasPalette() )
1673 {
1674 BitmapColor aNewCol;
1675
1676 for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
1677 {
1678 const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1679 aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
1680 aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
1681 aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
1682 pAcc->SetPaletteColor( i, aNewCol );
1683 }
1684 }
1685 else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr )
1686 {
1687 for( tools::Long nY = 0; nY < nH; nY++ )
1688 {
1689 Scanline pScan = pAcc->GetScanline( nY );
1690
1691 for( tools::Long nX = 0; nX < nW; nX++ )
1692 {
1693 *pScan = cMapB[ *pScan ]; pScan++;
1694 *pScan = cMapG[ *pScan ]; pScan++;
1695 *pScan = cMapR[ *pScan ]; pScan++;
1696 }
1697 }
1698 }
1699 else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb )
1700 {
1701 for( tools::Long nY = 0; nY < nH; nY++ )
1702 {
1703 Scanline pScan = pAcc->GetScanline( nY );
1704
1705 for( tools::Long nX = 0; nX < nW; nX++ )
1706 {
1707 *pScan = cMapR[ *pScan ]; pScan++;
1708 *pScan = cMapG[ *pScan ]; pScan++;
1709 *pScan = cMapB[ *pScan ]; pScan++;
1710 }
1711 }
1712 }
1713 else
1714 {
1715 for( tools::Long nY = 0; nY < nH; nY++ )
1716 {
1717 Scanline pScanline = pAcc->GetScanline(nY);
1718 for( tools::Long nX = 0; nX < nW; nX++ )
1719 {
1720 aCol = pAcc->GetPixelFromData( pScanline, nX );
1721 aCol.SetRed( cMapR[ aCol.GetRed() ] );
1722 aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
1723 aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
1724 pAcc->SetPixelOnData( pScanline, nX, aCol );
1725 }
1726 }
1727 }
1728
1729 pAcc.reset();
1730 bRet = true;
1731 }
1732 }
1733
1734 return bRet;
1735}
1736
1737/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
static BitmapColor getColor(const BitmapReadAccess *pReadAcc, tools::Long nZ)
static sal_Int32 * shiftColor(sal_Int32 *pColorArray, BitmapColor const &rColor)
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: BitmapEx.cxx:203
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
tools::Long Height() const
tools::Long Width() const
const BitmapPalette & GetPalette() const
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
sal_uInt16 GetPaletteEntryCount() const
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
sal_uInt16 GetEntryCount() const
bool IsGreyPaletteAny() const
Returns true if the palette is a grey palette (may not be 8-bit).
void SetEntryCount(sal_uInt16 nCount)
bool IsGreyPalette8Bit() const
Returns true if the palette is 8-bit grey palette.
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
Scanline GetScanline(tools::Long nY) const
bool Dither()
Apply a Floyd dither algorithm to the bitmap.
Bitmap CreateDisplayBitmap(OutputDevice *pDisplay) const
Bitmap & operator=(const Bitmap &rBitmap)
bool Crop(const tools::Rectangle &rRectPixel)
Crop the bitmap.
BitmapWriteAccess * AcquireWriteAccess()
bool HasGreyPalette8Bit() const
SAL_DLLPRIVATE void ImplSetSalBitmap(const std::shared_ptr< SalBitmap > &xImpBmp)
bool Convert(BmpConversion eConversion)
Convert bitmap format.
static const BitmapPalette & GetGreyPalette(int nEntries)
SAL_DLLPRIVATE void ImplMakeUnique()
BitmapChecksum GetChecksum() const
SAL_DLLPRIVATE void ReassignWithSize(const Bitmap &rBitmap)
ReassignWithSize and recalculate bitmap.
Size GetSizePixel() const
static void ReleaseAccess(BitmapInfoAccess *pAccess)
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
virtual ~Bitmap()
bool CopyPixel_AlphaOptimized(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc)
void Vectorize(GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
Convert the bitmap to a meta file.
BitmapReadAccess * AcquireReadAccess()
bool HasGreyPaletteAny() const
bool operator==(const Bitmap &rBitmap) const
SAL_DLLPRIVATE bool ImplConvertUp(vcl::PixelFormat ePixelFormat, Color const *pExtColor=nullptr)
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.
SAL_DLLPRIVATE bool ImplMakeGreyscales()
bool CopyPixel(const tools::Rectangle &rRectDst, const tools::Rectangle &rRectSrc, const Bitmap *pBmpSrc=nullptr)
Copy a rectangular area from another bitmap.
SAL_DLLPRIVATE bool ImplConvertDown8BPP(Color const *pExtColor=nullptr)
MapMode maPrefMapMode
void AdaptBitCount(Bitmap &rNew) const
bool GetSystemData(BitmapSystemData &rData) const
get system dependent bitmap data
bool Expand(sal_Int32 nDX, sal_Int32 nDY, const Color *pInitColor=nullptr)
Expand the bitmap by pixel padding.
vcl::PixelFormat getPixelFormat() const
static bool HasFastScale()
Returns true if bitmap scaling is considered to be fast.
std::shared_ptr< SalBitmap > mxSalBmp
BitmapInfoAccess * AcquireInfoAccess()
void SetEmpty()
sal_uInt8 GetLuminance() const
sal_uInt8 GetBlue() const
void SetGreen(sal_uInt8 nGreen)
void SetRed(sal_uInt8 nRed)
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
void SetBlue(sal_uInt8 nBlue)
Class to import and export graphic formats.
static GraphicFilter & GetGraphicFilter()
ErrCode compressAsPNG(const Graphic &rGraphic, SvStream &rOutputStream)
void ImplAddColorError7(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:94
BitmapColor ImplGetColor() const
Definition: impoctree.hxx:101
void ImplAddColorError5(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:87
void ImplAddColorError3(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:80
void ImplAddColorError1(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:73
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rColor)
Definition: Octree.cxx:273
const BitmapPalette & GetPalette()
Definition: Octree.cxx:197
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:176
SalGraphics const * GetGraphics() const
Get the graphic context that the output device uses to draw on.
Definition: outdev.cxx:202
virtual std::shared_ptr< SalBitmap > CreateSalBitmap()=0
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr Size GetSize() const
constexpr tools::Long GetHeight() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
constexpr bool IsEmpty() const
constexpr ::Color COL_LIGHTRED(0xFF, 0x00, 0x00)
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_GREEN(0x00, 0x80, 0x00)
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_LIGHTCYAN(0x00, 0xFF, 0xFF)
constexpr ::Color COL_MAGENTA(0x80, 0x00, 0x80)
constexpr ::Color COL_LIGHTMAGENTA(0xFF, 0x00, 0xFF)
constexpr ::Color COL_BROWN(0x80, 0x80, 0x00)
constexpr ::Color COL_YELLOW(0xFF, 0xFF, 0x00)
constexpr ::Color COL_RED(0x80, 0x00, 0x00)
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_LIGHTBLUE(0x00, 0x00, 0xFF)
constexpr ::Color COL_CYAN(0x00, 0x80, 0x80)
constexpr ::Color COL_LIGHTGREEN(0x00, 0xFF, 0x00)
constexpr ::Color COL_BLUE(0x00, 0x00, 0x80)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
int nCount
#define CALC_TABLES7
Definition: floyd.hxx:43
const sal_uLong nVCLBLut[6]
#define CALC_ERRORS
Definition: floyd.hxx:22
const sal_uLong nVCLGLut[6]
const sal_uLong nVCLRLut[6]
#define CALC_TABLES3
Definition: floyd.hxx:33
#define CALC_TABLES5
Definition: floyd.hxx:38
tools::Long FRound(double fVal)
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)
#define BMP_COL_TRANS
#define GAMMA(_def_cVal, _def_InvGamma)
short nBitCount
Definition: ipict.cxx:80
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
MapUnit
const ContentProperties & rData
bool ImplVectorize(const Bitmap &rColorBmp, GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
Definition: impvect.cxx:644
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
bool equalZero(const T &rfVal)
bool equal(T const &rfValA, T const &rfValB)
int i
long Long
constexpr bool isPalettePixelFormat(PixelFormat ePixelFormat)
Is it a pixel format that forces creation of a palette.
Definition: BitmapTypes.hxx:29
PixelFormat
Pixel format of the bitmap in bits per pixel.
Definition: BitmapTypes.hxx:20
constexpr sal_uInt16 pixelFormatBitCount(PixelFormat ePixelFormat)
Definition: BitmapTypes.hxx:35
HashMap_OWString_Interface aMap
sal_uIntPtr sal_uLong
SalInstance * mpDefInst
Definition: svdata.hxx:390
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
unsigned char sal_uInt8