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