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