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