LibreOffice Module vcl (master)  1
bitmap3.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 <math.h>
21 
22 #include <vcl/bitmapaccess.hxx>
23 #include <vcl/bitmapex.hxx>
24 #include <vcl/bitmap.hxx>
25 #include <config_features.h>
26 #include <sal/log.hxx>
27 #include <osl/diagnose.h>
28 #include <tools/helpers.hxx>
29 #if HAVE_FEATURE_OPENGL
31 #endif
32 #if HAVE_FEATURE_SKIA
33 #include <vcl/skia/SkiaHelper.hxx>
34 #endif
36 
41 #include <bitmapwriteaccess.hxx>
42 #include <bitmap/impoctree.hxx>
43 #include <bitmap/Octree.hxx>
44 #include <svdata.hxx>
45 #include <salinst.hxx>
46 #include <salbmp.hxx>
47 
48 #include "impvect.hxx"
49 
50 #include <memory>
51 
52 #define GAMMA( _def_cVal, _def_InvGamma ) (static_cast<sal_uInt8>(MinMax(FRound(pow( _def_cVal/255.0,_def_InvGamma)*255.0),0,255)))
53 
54 #define CALC_ERRORS \
55  nTemp = p1T[nX++] >> 12; \
56  nBErr = MinMax( nTemp, 0, 255 ); \
57  nBErr = nBErr - FloydIndexMap[ nBC = FloydMap[nBErr] ]; \
58  nTemp = p1T[nX++] >> 12; \
59  nGErr = MinMax( nTemp, 0, 255 ); \
60  nGErr = nGErr - FloydIndexMap[ nGC = FloydMap[nGErr] ]; \
61  nTemp = p1T[nX] >> 12; \
62  nRErr = MinMax( nTemp, 0, 255 ); \
63  nRErr = nRErr - FloydIndexMap[ nRC = FloydMap[nRErr] ];
64 
65 #define CALC_TABLES3 \
66  p2T[nX++] += FloydError3[nBErr]; \
67  p2T[nX++] += FloydError3[nGErr]; \
68  p2T[nX++] += FloydError3[nRErr];
69 
70 #define CALC_TABLES5 \
71  p2T[nX++] += FloydError5[nBErr]; \
72  p2T[nX++] += FloydError5[nGErr]; \
73  p2T[nX++] += FloydError5[nRErr];
74 
75 #define CALC_TABLES7 \
76  p1T[++nX] += FloydError7[nBErr]; \
77  p2T[nX++] += FloydError1[nBErr]; \
78  p1T[nX] += FloydError7[nGErr]; \
79  p2T[nX++] += FloydError1[nGErr]; \
80  p1T[nX] += FloydError7[nRErr]; \
81  p2T[nX] += FloydError1[nRErr];
82 
83 const extern sal_uLong nVCLRLut[ 6 ] = { 16, 17, 18, 19, 20, 21 };
84 const extern sal_uLong nVCLGLut[ 6 ] = { 0, 6, 12, 18, 24, 30 };
85 const extern sal_uLong nVCLBLut[ 6 ] = { 0, 36, 72, 108, 144, 180 };
86 
87 const extern sal_uLong nVCLDitherLut[ 256 ] =
88 {
89  0, 49152, 12288, 61440, 3072, 52224, 15360, 64512, 768, 49920, 13056,
90  62208, 3840, 52992, 16128, 65280, 32768, 16384, 45056, 28672, 35840, 19456,
91  48128, 31744, 33536, 17152, 45824, 29440, 36608, 20224, 48896, 32512, 8192,
92  57344, 4096, 53248, 11264, 60416, 7168, 56320, 8960, 58112, 4864, 54016,
93  12032, 61184, 7936, 57088, 40960, 24576, 36864, 20480, 44032, 27648, 39936,
94  23552, 41728, 25344, 37632, 21248, 44800, 28416, 40704, 24320, 2048, 51200,
95  14336, 63488, 1024, 50176, 13312, 62464, 2816, 51968, 15104, 64256, 1792,
96  50944, 14080, 63232, 34816, 18432, 47104, 30720, 33792, 17408, 46080, 29696,
97  35584, 19200, 47872, 31488, 34560, 18176, 46848, 30464, 10240, 59392, 6144,
98  55296, 9216, 58368, 5120, 54272, 11008, 60160, 6912, 56064, 9984, 59136,
99  5888, 55040, 43008, 26624, 38912, 22528, 41984, 25600, 37888, 21504, 43776,
100  27392, 39680, 23296, 42752, 26368, 38656, 22272, 512, 49664, 12800, 61952,
101  3584, 52736, 15872, 65024, 256, 49408, 12544, 61696, 3328, 52480, 15616,
102  64768, 33280, 16896, 45568, 29184, 36352, 19968, 48640, 32256, 33024, 16640,
103  45312, 28928, 36096, 19712, 48384, 32000, 8704, 57856, 4608, 53760, 11776,
104  60928, 7680, 56832, 8448, 57600, 4352, 53504, 11520, 60672, 7424, 56576,
105  41472, 25088, 37376, 20992, 44544, 28160, 40448, 24064, 41216, 24832, 37120,
106  20736, 44288, 27904, 40192, 23808, 2560, 51712, 14848, 64000, 1536, 50688,
107  13824, 62976, 2304, 51456, 14592, 63744, 1280, 50432, 13568, 62720, 35328,
108  18944, 47616, 31232, 34304, 17920, 46592, 30208, 35072, 18688, 47360, 30976,
109  34048, 17664, 46336, 29952, 10752, 59904, 6656, 55808, 9728, 58880, 5632,
110  54784, 10496, 59648, 6400, 55552, 9472, 58624, 5376, 54528, 43520, 27136,
111  39424, 23040, 42496, 26112, 38400, 22016, 43264, 26880, 39168, 22784, 42240,
112  25856, 38144, 21760
113 };
114 
115 const extern sal_uLong nVCLLut[ 256 ] =
116 {
117  0, 1286, 2572, 3858, 5144, 6430, 7716, 9002,
118  10288, 11574, 12860, 14146, 15432, 16718, 18004, 19290,
119  20576, 21862, 23148, 24434, 25720, 27006, 28292, 29578,
120  30864, 32150, 33436, 34722, 36008, 37294, 38580, 39866,
121  41152, 42438, 43724, 45010, 46296, 47582, 48868, 50154,
122  51440, 52726, 54012, 55298, 56584, 57870, 59156, 60442,
123  61728, 63014, 64300, 65586, 66872, 68158, 69444, 70730,
124  72016, 73302, 74588, 75874, 77160, 78446, 79732, 81018,
125  82304, 83590, 84876, 86162, 87448, 88734, 90020, 91306,
126  92592, 93878, 95164, 96450, 97736, 99022,100308,101594,
127  102880,104166,105452,106738,108024,109310,110596,111882,
128  113168,114454,115740,117026,118312,119598,120884,122170,
129  123456,124742,126028,127314,128600,129886,131172,132458,
130  133744,135030,136316,137602,138888,140174,141460,142746,
131  144032,145318,146604,147890,149176,150462,151748,153034,
132  154320,155606,156892,158178,159464,160750,162036,163322,
133  164608,165894,167180,168466,169752,171038,172324,173610,
134  174896,176182,177468,178754,180040,181326,182612,183898,
135  185184,186470,187756,189042,190328,191614,192900,194186,
136  195472,196758,198044,199330,200616,201902,203188,204474,
137  205760,207046,208332,209618,210904,212190,213476,214762,
138  216048,217334,218620,219906,221192,222478,223764,225050,
139  226336,227622,228908,230194,231480,232766,234052,235338,
140  236624,237910,239196,240482,241768,243054,244340,245626,
141  246912,248198,249484,250770,252056,253342,254628,255914,
142  257200,258486,259772,261058,262344,263630,264916,266202,
143  267488,268774,270060,271346,272632,273918,275204,276490,
144  277776,279062,280348,281634,282920,284206,285492,286778,
145  288064,289350,290636,291922,293208,294494,295780,297066,
146  298352,299638,300924,302210,303496,304782,306068,307354,
147  308640,309926,311212,312498,313784,315070,316356,317642,
148  318928,320214,321500,322786,324072,325358,326644,327930
149 };
150 
151 const long FloydMap[256] =
152 {
153  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
154  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
155  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
156  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
157  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
158  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
159  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
160  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
161  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
162  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
163  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
164  3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
165  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
166  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
167  4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
168  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
169 };
170 
171 const long FloydError1[61] =
172 {
173  -7680, -7424, -7168, -6912, -6656, -6400, -6144,
174  -5888, -5632, -5376, -5120, -4864, -4608, -4352,
175  -4096, -3840, -3584, -3328, -3072, -2816, -2560,
176  -2304, -2048, -1792, -1536, -1280, -1024, -768,
177  -512, -256, 0, 256, 512, 768, 1024, 1280, 1536,
178  1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584,
179  3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632,
180  5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680
181 };
182 
183 const long FloydError3[61] =
184 {
185  -23040, -22272, -21504, -20736, -19968, -19200,
186  -18432, -17664, -16896, -16128, -15360, -14592,
187  -13824, -13056, -12288, -11520, -10752, -9984,
188  -9216, -8448, -7680, -6912, -6144, -5376, -4608,
189  -3840, -3072, -2304, -1536, -768, 0, 768, 1536,
190  2304, 3072, 3840, 4608, 5376, 6144, 6912, 7680,
191  8448, 9216, 9984, 10752, 11520, 12288, 13056,
192  13824, 14592, 15360, 16128, 16896, 17664, 18432,
193  19200, 19968, 20736, 21504, 22272, 23040
194 };
195 
196 const long FloydError5[61] =
197 {
198  -38400, -37120, -35840, -34560, -33280, -32000,
199  -30720, -29440, -28160, -26880, -25600, -24320,
200  -23040, -21760, -20480, -19200, -17920, -16640,
201  -15360, -14080, -12800, -11520, -10240, -8960,
202  -7680, -6400, -5120, -3840, -2560, -1280, 0,
203  1280, 2560, 3840, 5120, 6400, 7680, 8960, 10240,
204  11520, 12800, 14080, 15360, 16640, 17920, 19200,
205  20480, 21760, 23040, 24320, 25600, 26880, 28160,
206  29440, 30720, 32000, 33280, 34560, 35840, 37120,
207  38400
208 };
209 
210 const long FloydError7[61] =
211 {
212  -53760, -51968, -50176, -48384, -46592, -44800,
213  -43008, -41216, -39424, -37632, -35840, -34048,
214  -32256, -30464, -28672, -26880, -25088, -23296,
215  -21504, -19712, -17920, -16128, -14336, -12544,
216  -10752, -8960, -7168, -5376, -3584, -1792, 0,
217  1792, 3584, 5376, 7168, 8960, 10752, 12544, 14336,
218  16128, 17920, 19712, 21504, 23296, 25088, 26880,
219  28672, 30464, 32256, 34048, 35840, 37632, 39424,
220  41216, 43008, 44800, 46592, 48384, 50176, 51968,
221  53760
222 };
223 
224 const long FloydIndexMap[6] =
225 {
226  -30, 21, 72, 123, 174, 225
227 };
228 
229 bool Bitmap::Convert( BmpConversion eConversion )
230 {
231  // try to convert in backend
232  if (mxSalBmp)
233  {
234  // avoid large chunk of obsolete and hopefully rarely used conversions.
235  if (eConversion == BmpConversion::N8BitNoConversion)
236  {
237  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
238  // frequently used conversion for creating alpha masks
239  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->InterpretAs8Bit())
240  {
241  ImplSetSalBitmap(xImpBmp);
242  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
243  return true;
244  }
245  }
246  if (eConversion == BmpConversion::N8BitGreys)
247  {
248  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
249  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->ConvertToGreyscale())
250  {
251  ImplSetSalBitmap(xImpBmp);
252  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
253  return true;
254  }
255  }
256  }
257 
258  const sal_uInt16 nBitCount = GetBitCount ();
259  bool bRet = false;
260 
261  switch( eConversion )
262  {
264  {
265  BitmapEx aBmpEx(*this);
266  bRet = BitmapFilter::Filter(aBmpEx, BitmapMonochromeFilter(128));
267  *this = aBmpEx.GetBitmap();
268  }
269  break;
270 
272  bRet = ImplMakeGreyscales( 16 );
273  break;
274 
276  {
277  if( nBitCount < 4 )
278  bRet = ImplConvertUp( 4 );
279  else if( nBitCount > 4 )
280  bRet = ImplConvertDown( 4 );
281  else
282  bRet = true;
283  }
284  break;
285 
288  bRet = ImplMakeGreyscales( 256 );
289  break;
290 
292  {
293  if( nBitCount < 8 )
294  bRet = ImplConvertUp( 8 );
295  else if( nBitCount > 8 )
296  bRet = ImplConvertDown( 8 );
297  else
298  bRet = true;
299  }
300  break;
301 
303  {
304  Color aTrans( BMP_COL_TRANS );
305 
306  if( nBitCount < 8 )
307  bRet = ImplConvertUp( 8, &aTrans );
308  else
309  bRet = ImplConvertDown( 8, &aTrans );
310  }
311  break;
312 
314  {
315  if( nBitCount < 24 )
316  bRet = ImplConvertUp( 24 );
317  else
318  bRet = true;
319  }
320  break;
321 
323  {
324  if( nBitCount < 32 )
325  bRet = ImplConvertUp( 32 );
326  else
327  bRet = true;
328  }
329  break;
330 
331  default:
332  OSL_FAIL( "Bitmap::Convert(): Unsupported conversion" );
333  break;
334  }
335 
336  return bRet;
337 }
338 
339 bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
340 {
341  SAL_WARN_IF( nGreys != 16 && nGreys != 256, "vcl", "Only 16 or 256 greyscales are supported!" );
342 
343  ScopedReadAccess pReadAcc(*this);
344  bool bRet = false;
345 
346  if( pReadAcc )
347  {
348  const BitmapPalette& rPal = GetGreyPalette( nGreys );
349  sal_uLong nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
350  bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
351 
352  if( !bPalDiffers )
353  bPalDiffers = ( rPal != pReadAcc->GetPalette() );
354 
355  if( bPalDiffers )
356  {
357  Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
358  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
359 
360  if( pWriteAcc )
361  {
362  const long nWidth = pWriteAcc->Width();
363  const long nHeight = pWriteAcc->Height();
364 
365  if( pReadAcc->HasPalette() )
366  {
367  for( long nY = 0; nY < nHeight; nY++ )
368  {
369  Scanline pScanline = pWriteAcc->GetScanline(nY);
370  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
371  for( long nX = 0; nX < nWidth; nX++ )
372  {
373  const sal_uInt8 cIndex = pReadAcc->GetIndexFromData( pScanlineRead, nX );
374  pWriteAcc->SetPixelOnData( pScanline, nX,
375  BitmapColor(pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
376  }
377  }
378  }
379  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr &&
381  {
382  nShift += 8;
383 
384  for( long nY = 0; nY < nHeight; nY++ )
385  {
386  Scanline pReadScan = pReadAcc->GetScanline( nY );
387  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
388 
389  for( long nX = 0; nX < nWidth; nX++ )
390  {
391  const sal_uLong nB = *pReadScan++;
392  const sal_uLong nG = *pReadScan++;
393  const sal_uLong nR = *pReadScan++;
394 
395  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
396  }
397  }
398  }
399  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb &&
401  {
402  nShift += 8;
403 
404  for( long nY = 0; nY < nHeight; nY++ )
405  {
406  Scanline pReadScan = pReadAcc->GetScanline( nY );
407  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
408 
409  for( long nX = 0; nX < nWidth; nX++ )
410  {
411  const sal_uLong nR = *pReadScan++;
412  const sal_uLong nG = *pReadScan++;
413  const sal_uLong nB = *pReadScan++;
414 
415  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
416  }
417  }
418  }
419  else
420  {
421  for( long nY = 0; nY < nHeight; nY++ )
422  {
423  Scanline pScanline = pWriteAcc->GetScanline(nY);
424  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
425  for( long nX = 0; nX < nWidth; nX++ )
426  pWriteAcc->SetPixelOnData( pScanline, nX, BitmapColor(pReadAcc->GetPixelFromData( pScanlineRead, nX ).GetLuminance() >> nShift) );
427  }
428  }
429 
430  pWriteAcc.reset();
431  bRet = true;
432  }
433 
434  pReadAcc.reset();
435 
436  if( bRet )
437  {
438  const MapMode aMap( maPrefMapMode );
439  const Size aSize( maPrefSize );
440 
441  *this = aNewBmp;
442 
443  maPrefMapMode = aMap;
444  maPrefSize = aSize;
445  }
446  }
447  else
448  {
449  pReadAcc.reset();
450  bRet = true;
451  }
452  }
453 
454  return bRet;
455 }
456 
457 bool Bitmap::ImplConvertUp(sal_uInt16 nBitCount, Color const * pExtColor)
458 {
459  SAL_WARN_IF( nBitCount <= GetBitCount(), "vcl", "New BitCount must be greater!" );
460 
461  Bitmap::ScopedReadAccess pReadAcc(*this);
462  bool bRet = false;
463 
464  if (pReadAcc)
465  {
466  BitmapPalette aPalette;
467  Bitmap aNewBmp(GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPalette);
468  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
469 
470  if (pWriteAcc)
471  {
472  const long nWidth = pWriteAcc->Width();
473  const long nHeight = pWriteAcc->Height();
474 
475  if (pWriteAcc->HasPalette())
476  {
477  const BitmapPalette& rOldPalette = pReadAcc->GetPalette();
478  const sal_uInt16 nOldCount = rOldPalette.GetEntryCount();
479  assert(nOldCount <= (1 << GetBitCount()));
480 
481  aPalette.SetEntryCount(1 << nBitCount);
482 
483  for (sal_uInt16 i = 0; i < nOldCount; i++)
484  aPalette[i] = rOldPalette[i];
485 
486  if (pExtColor)
487  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
488 
489  pWriteAcc->SetPalette(aPalette);
490 
491  for (long nY = 0; nY < nHeight; nY++)
492  {
493  Scanline pScanline = pWriteAcc->GetScanline(nY);
494  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
495  for (long nX = 0; nX < nWidth; nX++)
496  {
497  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
498  }
499  }
500  }
501  else
502  {
503  if (pReadAcc->HasPalette())
504  {
505  for (long nY = 0; nY < nHeight; nY++)
506  {
507  Scanline pScanline = pWriteAcc->GetScanline(nY);
508  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
509  for (long nX = 0; nX < nWidth; nX++)
510  {
511  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX)));
512  }
513  }
514  }
515  else
516  {
517  for (long nY = 0; nY < nHeight; nY++)
518  {
519  Scanline pScanline = pWriteAcc->GetScanline(nY);
520  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
521  for (long nX = 0; nX < nWidth; nX++)
522  {
523  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
524  }
525  }
526  }
527  }
528  bRet = true;
529  }
530 
531  if (bRet)
532  {
533  const MapMode aMap(maPrefMapMode);
534  const Size aSize(maPrefSize);
535 
536  *this = aNewBmp;
537 
538  maPrefMapMode = aMap;
539  maPrefSize = aSize;
540  }
541  }
542 
543  return bRet;
544 }
545 
546 bool Bitmap::ImplConvertDown(sal_uInt16 nBitCount, Color const * pExtColor)
547 {
548  SAL_WARN_IF(nBitCount > GetBitCount(), "vcl", "New BitCount must be lower ( or equal when pExtColor is set )!");
549 
550  Bitmap::ScopedReadAccess pReadAcc(*this);
551  bool bRet = false;
552 
553  if (pReadAcc)
554  {
555  BitmapPalette aPalette;
556  Bitmap aNewBmp(GetSizePixel(), nBitCount, &aPalette);
557  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
558 
559  if (pWriteAcc)
560  {
561  const sal_uInt16 nCount = 1 << nBitCount;
562  const long nWidth = pWriteAcc->Width();
563  const long nWidth1 = nWidth - 1;
564  const long nHeight = pWriteAcc->Height();
565  Octree aOctree(*pReadAcc, pExtColor ? (nCount - 1) : nCount);
566  aPalette = aOctree.GetPalette();
567  InverseColorMap aColorMap(aPalette);
568  BitmapColor aColor;
569  ImpErrorQuad aErrQuad;
570  std::vector<ImpErrorQuad> aErrQuad1(nWidth);
571  std::vector<ImpErrorQuad> aErrQuad2(nWidth);
572  ImpErrorQuad* pQLine1 = aErrQuad1.data();
573  ImpErrorQuad* pQLine2 = nullptr;
574  long nYTmp = 0;
575  sal_uInt8 cIndex;
576  bool bQ1 = true;
577 
578  if (pExtColor)
579  {
580  aPalette.SetEntryCount(aPalette.GetEntryCount() + 1);
581  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
582  }
583 
584  // set Black/White always, if we have enough space
585  if (aPalette.GetEntryCount() < (nCount - 1))
586  {
587  aPalette.SetEntryCount(aPalette.GetEntryCount() + 2);
588  aPalette[aPalette.GetEntryCount() - 2] = COL_BLACK;
589  aPalette[aPalette.GetEntryCount() - 1] = COL_WHITE;
590  }
591 
592  pWriteAcc->SetPalette(aPalette);
593 
594  for (long nY = 0; nY < std::min(nHeight, 2L); nY++, nYTmp++)
595  {
596  pQLine2 = !nY ? aErrQuad1.data() : aErrQuad2.data();
597  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
598  for (long nX = 0; nX < nWidth; nX++)
599  {
600  if (pReadAcc->HasPalette())
601  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
602  else
603  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
604  }
605  }
606 
607  assert(pQLine2 || nHeight == 0);
608 
609  for (long nY = 0; nY < nHeight; nY++, nYTmp++)
610  {
611  // first pixel in the line
612  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[0].ImplGetColor()));
613  Scanline pScanline = pWriteAcc->GetScanline(nY);
614  pWriteAcc->SetPixelOnData(pScanline, 0, BitmapColor(cIndex));
615 
616  long nX;
617  for (nX = 1; nX < nWidth1; nX++)
618  {
619  aColor = pQLine1[nX].ImplGetColor();
620  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(aColor));
621  aErrQuad = (ImpErrorQuad(aColor) -= pWriteAcc->GetPaletteColor(cIndex));
622  pQLine1[++nX].ImplAddColorError7(aErrQuad);
623  pQLine2[nX--].ImplAddColorError1(aErrQuad);
624  pQLine2[nX--].ImplAddColorError5(aErrQuad);
625  pQLine2[nX++].ImplAddColorError3(aErrQuad);
626  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
627  }
628 
629  // Last RowPixel
630  if (nX < nWidth)
631  {
632  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[nWidth1].ImplGetColor()));
633  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
634  }
635 
636  // Refill/copy row buffer
637  pQLine1 = pQLine2;
638  bQ1 = !bQ1;
639  pQLine2 = bQ1 ? aErrQuad2.data() : aErrQuad1.data();
640 
641  if (nYTmp < nHeight)
642  {
643  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
644  for (nX = 0; nX < nWidth; nX++)
645  {
646  if (pReadAcc->HasPalette())
647  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
648  else
649  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
650  }
651  }
652  }
653 
654  bRet = true;
655  }
656  pWriteAcc.reset();
657 
658  if(bRet)
659  {
660  const MapMode aMap(maPrefMapMode);
661  const Size aSize(maPrefSize);
662 
663  *this = aNewBmp;
664 
665  maPrefMapMode = aMap;
666  maPrefSize = aSize;
667  }
668  }
669 
670  return bRet;
671 }
672 
673 bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
674 {
676  {
677  // no scale
678  return true;
679  }
680 
681  if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
682  {
683  // no scale
684  return true;
685  }
686 
687  const sal_uInt16 nStartCount(GetBitCount());
688 
689  if (mxSalBmp && mxSalBmp->ScalingSupported())
690  {
691  // implementation specific scaling
692  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
693  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->Scale(rScaleX, rScaleY, nScaleFlag))
694  {
695  ImplSetSalBitmap(xImpBmp);
696  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
697  maPrefMapMode = MapMode( MapUnit::MapPixel );
698  maPrefSize = xImpBmp->GetSize();
699  return true;
700  }
701  }
702 
703  // fdo#33455
704  //
705  // If we start with a 1 bit image, then after scaling it in any mode except
706  // BmpScaleFlag::Fast we have a 24bit image which is perfectly correct, but we
707  // are going to down-shift it to mono again and Bitmap::MakeMonochrome just
708  // has "Bitmap aNewBmp( GetSizePixel(), 1 );" to create a 1 bit bitmap which
709  // will default to black/white and the colors mapped to which ever is closer
710  // to black/white
711  //
712  // So the easiest thing to do to retain the colors of 1 bit bitmaps is to
713  // just use the fast scale rather than attempting to count unique colors in
714  // the other converters and pass all the info down through
715  // Bitmap::MakeMonochrome
716  if (nStartCount == 1)
717  nScaleFlag = BmpScaleFlag::Fast;
718 
719  BitmapEx aBmpEx(*this);
720  bool bRetval(false);
721 
722  switch(nScaleFlag)
723  {
725  if (GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
726  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
727  else
728  bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
729  break;
730 
731  case BmpScaleFlag::Fast:
733  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
734  break;
735 
737  bRetval = BitmapFilter::Filter(aBmpEx, BitmapInterpolateScaleFilter(rScaleX, rScaleY));
738  break;
739 
740  case BmpScaleFlag::Super:
741  bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
742  break;
745  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleLanczos3Filter(rScaleX, rScaleY));
746  break;
747 
749  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBicubicFilter(rScaleX, rScaleY));
750  break;
751 
753  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBilinearFilter(rScaleX, rScaleY));
754  break;
755  }
756 
757  if (bRetval)
758  *this = aBmpEx.GetBitmap();
759 
760  OSL_ENSURE(!bRetval || nStartCount == GetBitCount(), "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
761  return bRetval;
762 }
763 
764 bool Bitmap::Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag )
765 {
766  const Size aSize( GetSizePixel() );
767  bool bRet;
768 
769  if( aSize.Width() && aSize.Height() )
770  {
771  bRet = Scale( static_cast<double>(rNewSize.Width()) / aSize.Width(),
772  static_cast<double>(rNewSize.Height()) / aSize.Height(),
773  nScaleFlag );
774  }
775  else
776  bRet = true;
777 
778  return bRet;
779 }
780 
782 {
783 #if HAVE_FEATURE_SKIA
784  if( SkiaHelper::isVCLSkiaEnabled() && SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster)
785  return true;
786 #endif
787 #if HAVE_FEATURE_OPENGL
789  return true;
790 #endif
791  return false;
792 }
793 
794 void Bitmap::AdaptBitCount(Bitmap& rNew) const
795 {
796  // aNew is the result of some operation; adapt it's BitCount to the original (this)
797  if(GetBitCount() != rNew.GetBitCount())
798  {
799  switch(GetBitCount())
800  {
801  case 1:
802  {
804  break;
805  }
806  case 4:
807  {
808  if(HasGreyPaletteAny())
809  {
811  }
812  else
813  {
815  }
816  break;
817  }
818  case 8:
819  {
820  if(HasGreyPaletteAny())
821  {
823  }
824  else
825  {
827  }
828  break;
829  }
830  case 24:
831  {
833  break;
834  }
835  case 32:
836  {
838  break;
839  }
840  default:
841  {
842  SAL_WARN("vcl", "BitDepth adaptation failed, from " << rNew.GetBitCount() << " to " << GetBitCount());
843  break;
844  }
845  }
846  }
847 }
848 
850 {
851  const Size aSize( GetSizePixel() );
852 
853  if( aSize.Width() == 1 || aSize.Height() == 1 )
854  return true;
855 
856  bool bRet = false;
857 
858  if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
859  {
860  ScopedReadAccess pReadAcc(*this);
861  Bitmap aNewBmp( GetSizePixel(), 8 );
862  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
863 
864  if( pReadAcc && pWriteAcc )
865  {
866  BitmapColor aColor;
867  long nWidth = pReadAcc->Width();
868  long nWidth1 = nWidth - 1;
869  long nHeight = pReadAcc->Height();
870  long nX;
871  long nW = nWidth * 3;
872  long nW2 = nW - 3;
873  long nRErr, nGErr, nBErr;
874  long nRC, nGC, nBC;
875  std::unique_ptr<long[]> p1(new long[ nW ]);
876  std::unique_ptr<long[]> p2(new long[ nW ]);
877  long* p1T = p1.get();
878  long* p2T = p2.get();
879  long* pTmp;
880  bool bPal = pReadAcc->HasPalette();
881 
882  pTmp = p2T;
883 
884  if( bPal )
885  {
886  Scanline pScanlineRead = pReadAcc->GetScanline(0);
887  for( long nZ = 0; nZ < nWidth; nZ++ )
888  {
889  aColor = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nZ ) );
890 
891  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
892  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
893  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
894  }
895  }
896  else
897  {
898  Scanline pScanlineRead = pReadAcc->GetScanline(0);
899  for( long nZ = 0; nZ < nWidth; nZ++ )
900  {
901  aColor = pReadAcc->GetPixelFromData( pScanlineRead, nZ );
902 
903  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
904  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
905  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
906  }
907  }
908 
909  for( long nY = 1, nYAcc = 0; nY <= nHeight; nY++, nYAcc++ )
910  {
911  pTmp = p1T;
912  p1T = p2T;
913  p2T = pTmp;
914 
915  if( nY < nHeight )
916  {
917  if( bPal )
918  {
919  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
920  for( long nZ = 0; nZ < nWidth; nZ++ )
921  {
922  aColor = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nZ ) );
923 
924  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
925  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
926  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
927  }
928  }
929  else
930  {
931  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
932  for( long nZ = 0; nZ < nWidth; nZ++ )
933  {
934  aColor = pReadAcc->GetPixelFromData( pScanlineRead, nZ );
935 
936  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
937  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
938  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
939  }
940  }
941  }
942 
943  // Examine first Pixel separately
944  nX = 0;
945  long nTemp;
946  CALC_ERRORS;
947  CALC_TABLES7;
948  nX -= 5;
949  CALC_TABLES5;
950  Scanline pScanline = pWriteAcc->GetScanline(nYAcc);
951  pWriteAcc->SetPixelOnData( pScanline, 0, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
952 
953  // Get middle Pixels using a loop
954  long nXAcc;
955  for ( nX = 3, nXAcc = 1; nX < nW2; nXAcc++ )
956  {
957  CALC_ERRORS;
958  CALC_TABLES7;
959  nX -= 8;
960  CALC_TABLES3;
961  CALC_TABLES5;
962  pWriteAcc->SetPixelOnData( pScanline, nXAcc, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
963  }
964 
965  // Treat last Pixel separately
966  CALC_ERRORS;
967  nX -= 5;
968  CALC_TABLES3;
969  CALC_TABLES5;
970  pWriteAcc->SetPixelOnData( pScanline, nWidth1, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
971  }
972 
973  bRet = true;
974  }
975 
976  pReadAcc.reset();
977  pWriteAcc.reset();
978 
979  if( bRet )
980  {
981  const MapMode aMap( maPrefMapMode );
982  const Size aPrefSize( maPrefSize );
983 
984  *this = aNewBmp;
985 
986  maPrefMapMode = aMap;
987  maPrefSize = aPrefSize;
988  }
989  }
990 
991  return bRet;
992 }
993 
994 void Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, const Link<long,void>* pProgress )
995 {
996  ImplVectorizer::ImplVectorize( *this, rMtf, cReduce, pProgress );
997 }
998 
999 bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
1000  short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
1001  double fGamma, bool bInvert, bool msoBrightness )
1002 {
1003  bool bRet = false;
1004 
1005  // nothing to do => return quickly
1006  if( !nLuminancePercent && !nContrastPercent &&
1007  !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
1008  ( fGamma == 1.0 ) && !bInvert )
1009  {
1010  bRet = true;
1011  }
1012  else
1013  {
1014  BitmapScopedWriteAccess pAcc(*this);
1015 
1016  if( pAcc )
1017  {
1018  BitmapColor aCol;
1019  const long nW = pAcc->Width();
1020  const long nH = pAcc->Height();
1021  std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]);
1022  std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]);
1023  std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]);
1024  double fM, fROff, fGOff, fBOff, fOff;
1025 
1026  // calculate slope
1027  if( nContrastPercent >= 0 )
1028  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
1029  else
1030  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
1031 
1032  if(!msoBrightness)
1033  // total offset = luminance offset + contrast offset
1034  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
1035  else
1036  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
1037 
1038  // channel offset = channel offset + total offset
1039  fROff = nChannelRPercent * 2.55 + fOff;
1040  fGOff = nChannelGPercent * 2.55 + fOff;
1041  fBOff = nChannelBPercent * 2.55 + fOff;
1042 
1043  // calculate gamma value
1044  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
1045  const bool bGamma = ( fGamma != 1.0 );
1046 
1047  // create mapping table
1048  for( long nX = 0; nX < 256; nX++ )
1049  {
1050  if(!msoBrightness)
1051  {
1052  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
1053  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
1054  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
1055  }
1056  else
1057  {
1058  // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128"
1059  // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason,
1060  // use neither first, but apparently it applies half of brightness before contrast and half afterwards.
1061  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
1062  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
1063  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
1064  }
1065  if( bGamma )
1066  {
1067  cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
1068  cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
1069  cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
1070  }
1071 
1072  if( bInvert )
1073  {
1074  cMapR[ nX ] = ~cMapR[ nX ];
1075  cMapG[ nX ] = ~cMapG[ nX ];
1076  cMapB[ nX ] = ~cMapB[ nX ];
1077  }
1078  }
1079 
1080  // do modifying
1081  if( pAcc->HasPalette() )
1082  {
1083  BitmapColor aNewCol;
1084 
1085  for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
1086  {
1087  const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1088  aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
1089  aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
1090  aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
1091  pAcc->SetPaletteColor( i, aNewCol );
1092  }
1093  }
1094  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr )
1095  {
1096  for( long nY = 0; nY < nH; nY++ )
1097  {
1098  Scanline pScan = pAcc->GetScanline( nY );
1099 
1100  for( long nX = 0; nX < nW; nX++ )
1101  {
1102  *pScan = cMapB[ *pScan ]; pScan++;
1103  *pScan = cMapG[ *pScan ]; pScan++;
1104  *pScan = cMapR[ *pScan ]; pScan++;
1105  }
1106  }
1107  }
1108  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb )
1109  {
1110  for( long nY = 0; nY < nH; nY++ )
1111  {
1112  Scanline pScan = pAcc->GetScanline( nY );
1113 
1114  for( long nX = 0; nX < nW; nX++ )
1115  {
1116  *pScan = cMapR[ *pScan ]; pScan++;
1117  *pScan = cMapG[ *pScan ]; pScan++;
1118  *pScan = cMapB[ *pScan ]; pScan++;
1119  }
1120  }
1121  }
1122  else
1123  {
1124  for( long nY = 0; nY < nH; nY++ )
1125  {
1126  Scanline pScanline = pAcc->GetScanline(nY);
1127  for( long nX = 0; nX < nW; nX++ )
1128  {
1129  aCol = pAcc->GetPixelFromData( pScanline, nX );
1130  aCol.SetRed( cMapR[ aCol.GetRed() ] );
1131  aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
1132  aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
1133  pAcc->SetPixelOnData( pScanline, nX, aCol );
1134  }
1135  }
1136  }
1137 
1138  pAcc.reset();
1139  bRet = true;
1140  }
1141  }
1142 
1143  return bRet;
1144 }
1145 
1146 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
static bool HasFastScale()
Returns true if bitmap scaling is considered to be fast.
Definition: bitmap3.cxx:781
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.
Definition: bitmap3.cxx:999
#define BMP_COL_TRANS
Definition: bitmap.hxx:63
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
sal_uInt8 GetRed() const
void SetBlue(sal_uInt8 nBlue)
long FRound(double fVal)
Scanline GetScanline(long nY) const
void SetEntryCount(sal_uInt16 nCount)
const sal_uLong nVCLLut[256]
static bool equal(const double &rfValA, const double &rfValB)
long Height() const
sal_uIntPtr sal_uLong
Size maPrefSize
Definition: bitmap.hxx:542
sal_uInt8 GetLuminance() const
bool ImplVectorize(const Bitmap &rColorBmp, GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< long, void > *pProgress)
Definition: impvect.cxx:644
const sal_uLong nVCLBLut[6]
Size GetSizePixel() const
long Width() const
const sal_uLong nVCLRLut[6]
void SetPalette(const BitmapPalette &rPalette)
void ImplAddColorError1(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:73
HashMap_OWString_Interface aMap
const long FloydError3[61]
Definition: bitmap3.cxx:183
void Vectorize(GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< long, void > *pProgress)
Convert the bitmap to a meta file.
Definition: bitmap3.cxx:994
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
static bool Filter(BitmapEx &rBmpEx, BitmapFilter const &rFilter)
#define CALC_ERRORS
Definition: bitmap3.cxx:54
void SetPixelOnData(sal_uInt8 *pData, long nX, const BitmapColor &rBitmapColor)
#define CALC_TABLES3
Definition: bitmap3.cxx:65
sal_uInt8 GetBlue() const
bool Dither()
Apply a Floyd dither algorithm to the bitmap.
Definition: bitmap3.cxx:849
SAL_DLLPRIVATE bool ImplConvertDown(sal_uInt16 nBitCount, Color const *pExtColor=nullptr)
Definition: bitmap3.cxx:546
const long FloydError7[61]
Definition: bitmap3.cxx:210
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
sal_uInt16 GetEntryCount() const
BitmapColor ImplGetColor()
Definition: impoctree.hxx:101
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
#define CALC_TABLES7
Definition: bitmap3.cxx:75
int i
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
void ImplAddColorError5(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:87
SAL_DLLPRIVATE bool ImplConvertUp(sal_uInt16 nBitCount, Color const *pExtColor=nullptr)
Definition: bitmap3.cxx:457
static bool equalZero(const double &rfVal)
const sal_uLong nVCLDitherLut[256]
void SetRed(sal_uInt8 nRed)
BmpScaleFlag
Definition: bitmap.hxx:48
const long FloydError5[61]
Definition: bitmap3.cxx:196
BmpConversion
Definition: bitmap.hxx:65
short nBitCount
sal_uInt16 GetPaletteEntryCount() const
Bitmap GetBitmap(Color aTransparentReplaceColor) const
Definition: bitmapex.cxx:237
void ImplAddColorError3(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:80
sal_uInt8 GetGreen() const
const long FloydMap[256]
Definition: bitmap3.cxx:151
const sal_uLong nVCLGLut[6]
VCL_DLLPUBLIC bool isVCLSkiaEnabled()
SAL_DLLPRIVATE bool ImplMakeGreyscales(sal_uInt16 nGreyscales)
Definition: bitmap3.cxx:339
long Height() const
#define SAL_WARN_IF(condition, area, stream)
unsigned char sal_uInt8
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
Scale the bitmap.
Definition: bitmap3.cxx:764
bool Convert(BmpConversion eConversion)
Convert bitmap format.
Definition: bitmap3.cxx:229
bool HasGreyPaletteAny() const
void SetGreen(sal_uInt8 nGreen)
const BitmapPalette & GetPalette() const
#define SAL_INFO(area, stream)
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
#define CALC_TABLES5
Definition: bitmap3.cxx:70
BitmapColor GetPixelFromData(const sal_uInt8 *pData, long nX) const
void AdaptBitCount(Bitmap &rNew) const
Definition: bitmap3.cxx:794
const long FloydIndexMap[6]
Definition: bitmap3.cxx:224
void ImplAddColorError7(const ImpErrorQuad &rErrQuad)
Definition: impoctree.hxx:94
const long FloydError1[61]
Definition: bitmap3.cxx:171
#define SAL_WARN(area, stream)
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
sal_uInt16 GetBitCount() const
#define GAMMA(_def_cVal, _def_InvGamma)
Definition: bitmap3.cxx:52
std::enable_if< std::is_signed< T >::value||std::is_floating_point< T >::value, long >::type MinMax(T nVal, long nMin, long nMax)
static bool isVCLOpenGLEnabled()
Returns true if VCL has OpenGL rendering enabled.
MapMode maPrefMapMode
Definition: bitmap.hxx:541
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rColor)
Definition: Octree.cxx:281
void SetPaletteColor(sal_uInt16 nColor, const BitmapColor &rBitmapColor)
std::shared_ptr< SalBitmap > mxSalBmp
Definition: bitmap.hxx:540
static const BitmapPalette & GetGreyPalette(int nEntries)
const BitmapPalette & GetPalette()
Definition: Octree.cxx:204
SAL_DLLPRIVATE void ImplSetSalBitmap(const std::shared_ptr< SalBitmap > &xImpBmp)
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, long nX) const