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