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