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  bRet = ImplConvertGhosted();
310  break;
311 
312  default:
313  OSL_FAIL( "Bitmap::Convert(): Unsupported conversion" );
314  break;
315  }
316 
317  return bRet;
318 }
319 
320 bool Bitmap::ImplMakeGreyscales( sal_uInt16 nGreys )
321 {
322  SAL_WARN_IF( nGreys != 16 && nGreys != 256, "vcl", "Only 16 or 256 greyscales are supported!" );
323 
324  ScopedReadAccess pReadAcc(*this);
325  bool bRet = false;
326 
327  if( pReadAcc )
328  {
329  const BitmapPalette& rPal = GetGreyPalette( nGreys );
330  sal_uLong nShift = ( ( nGreys == 16 ) ? 4UL : 0UL );
331  bool bPalDiffers = !pReadAcc->HasPalette() || ( rPal.GetEntryCount() != pReadAcc->GetPaletteEntryCount() );
332 
333  if( !bPalDiffers )
334  bPalDiffers = ( rPal != pReadAcc->GetPalette() );
335 
336  if( bPalDiffers )
337  {
338  Bitmap aNewBmp( GetSizePixel(), ( nGreys == 16 ) ? 4 : 8, &rPal );
339  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
340 
341  if( pWriteAcc )
342  {
343  const long nWidth = pWriteAcc->Width();
344  const long nHeight = pWriteAcc->Height();
345 
346  if( pReadAcc->HasPalette() )
347  {
348  for( long nY = 0; nY < nHeight; nY++ )
349  {
350  Scanline pScanline = pWriteAcc->GetScanline(nY);
351  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
352  for( long nX = 0; nX < nWidth; nX++ )
353  {
354  const sal_uInt8 cIndex = pReadAcc->GetIndexFromData( pScanlineRead, nX );
355  pWriteAcc->SetPixelOnData( pScanline, nX,
356  BitmapColor(pReadAcc->GetPaletteColor( cIndex ).GetLuminance() >> nShift) );
357  }
358  }
359  }
360  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr &&
362  {
363  nShift += 8;
364 
365  for( long nY = 0; nY < nHeight; nY++ )
366  {
367  Scanline pReadScan = pReadAcc->GetScanline( nY );
368  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
369 
370  for( long nX = 0; nX < nWidth; nX++ )
371  {
372  const sal_uLong nB = *pReadScan++;
373  const sal_uLong nG = *pReadScan++;
374  const sal_uLong nR = *pReadScan++;
375 
376  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
377  }
378  }
379  }
380  else if( pReadAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb &&
382  {
383  nShift += 8;
384 
385  for( long nY = 0; nY < nHeight; nY++ )
386  {
387  Scanline pReadScan = pReadAcc->GetScanline( nY );
388  Scanline pWriteScan = pWriteAcc->GetScanline( nY );
389 
390  for( long nX = 0; nX < nWidth; nX++ )
391  {
392  const sal_uLong nR = *pReadScan++;
393  const sal_uLong nG = *pReadScan++;
394  const sal_uLong nB = *pReadScan++;
395 
396  *pWriteScan++ = static_cast<sal_uInt8>( ( nB * 28UL + nG * 151UL + nR * 77UL ) >> nShift );
397  }
398  }
399  }
400  else
401  {
402  for( long nY = 0; nY < nHeight; nY++ )
403  {
404  Scanline pScanline = pWriteAcc->GetScanline(nY);
405  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
406  for( long nX = 0; nX < nWidth; nX++ )
407  pWriteAcc->SetPixelOnData( pScanline, nX, BitmapColor(pReadAcc->GetPixelFromData( pScanlineRead, nX ).GetLuminance() >> nShift) );
408  }
409  }
410 
411  pWriteAcc.reset();
412  bRet = true;
413  }
414 
415  pReadAcc.reset();
416 
417  if( bRet )
418  {
419  const MapMode aMap( maPrefMapMode );
420  const Size aSize( maPrefSize );
421 
422  *this = aNewBmp;
423 
424  maPrefMapMode = aMap;
425  maPrefSize = aSize;
426  }
427  }
428  else
429  {
430  pReadAcc.reset();
431  bRet = true;
432  }
433  }
434 
435  return bRet;
436 }
437 
438 bool Bitmap::ImplConvertUp(sal_uInt16 nBitCount, Color const * pExtColor)
439 {
440  SAL_WARN_IF( nBitCount <= GetBitCount(), "vcl", "New BitCount must be greater!" );
441 
442  Bitmap::ScopedReadAccess pReadAcc(*this);
443  bool bRet = false;
444 
445  if (pReadAcc)
446  {
447  BitmapPalette aPalette;
448  Bitmap aNewBmp(GetSizePixel(), nBitCount, pReadAcc->HasPalette() ? &pReadAcc->GetPalette() : &aPalette);
449  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
450 
451  if (pWriteAcc)
452  {
453  const long nWidth = pWriteAcc->Width();
454  const long nHeight = pWriteAcc->Height();
455 
456  if (pWriteAcc->HasPalette())
457  {
458  const BitmapPalette& rOldPalette = pReadAcc->GetPalette();
459  const sal_uInt16 nOldCount = rOldPalette.GetEntryCount();
460  assert(nOldCount <= (1 << GetBitCount()));
461 
462  aPalette.SetEntryCount(1 << nBitCount);
463 
464  for (sal_uInt16 i = 0; i < nOldCount; i++)
465  aPalette[i] = rOldPalette[i];
466 
467  if (pExtColor)
468  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
469 
470  pWriteAcc->SetPalette(aPalette);
471 
472  for (long nY = 0; nY < nHeight; nY++)
473  {
474  Scanline pScanline = pWriteAcc->GetScanline(nY);
475  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
476  for (long nX = 0; nX < nWidth; nX++)
477  {
478  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
479  }
480  }
481  }
482  else
483  {
484  if (pReadAcc->HasPalette())
485  {
486  for (long nY = 0; nY < nHeight; nY++)
487  {
488  Scanline pScanline = pWriteAcc->GetScanline(nY);
489  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
490  for (long nX = 0; nX < nWidth; nX++)
491  {
492  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX)));
493  }
494  }
495  }
496  else
497  {
498  for (long nY = 0; nY < nHeight; nY++)
499  {
500  Scanline pScanline = pWriteAcc->GetScanline(nY);
501  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
502  for (long nX = 0; nX < nWidth; nX++)
503  {
504  pWriteAcc->SetPixelOnData(pScanline, nX, pReadAcc->GetPixelFromData(pScanlineRead, nX));
505  }
506  }
507  }
508  }
509  bRet = true;
510  }
511 
512  if (bRet)
513  {
514  const MapMode aMap(maPrefMapMode);
515  const Size aSize(maPrefSize);
516 
517  *this = aNewBmp;
518 
519  maPrefMapMode = aMap;
520  maPrefSize = aSize;
521  }
522  }
523 
524  return bRet;
525 }
526 
527 bool Bitmap::ImplConvertDown(sal_uInt16 nBitCount, Color const * pExtColor)
528 {
529  SAL_WARN_IF(nBitCount > GetBitCount(), "vcl", "New BitCount must be lower ( or equal when pExtColor is set )!");
530 
531  Bitmap::ScopedReadAccess pReadAcc(*this);
532  bool bRet = false;
533 
534  if (pReadAcc)
535  {
536  BitmapPalette aPalette;
537  Bitmap aNewBmp(GetSizePixel(), nBitCount, &aPalette);
538  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
539 
540  if (pWriteAcc)
541  {
542  const sal_uInt16 nCount = 1 << nBitCount;
543  const long nWidth = pWriteAcc->Width();
544  const long nWidth1 = nWidth - 1;
545  const long nHeight = pWriteAcc->Height();
546  Octree aOctree(*pReadAcc, pExtColor ? (nCount - 1) : nCount);
547  aPalette = aOctree.GetPalette();
548  InverseColorMap aColorMap(aPalette);
549  BitmapColor aColor;
550  ImpErrorQuad aErrQuad;
551  std::vector<ImpErrorQuad> aErrQuad1(nWidth);
552  std::vector<ImpErrorQuad> aErrQuad2(nWidth);
553  ImpErrorQuad* pQLine1 = aErrQuad1.data();
554  ImpErrorQuad* pQLine2 = nullptr;
555  long nYTmp = 0;
556  sal_uInt8 cIndex;
557  bool bQ1 = true;
558 
559  if (pExtColor)
560  {
561  aPalette.SetEntryCount(aPalette.GetEntryCount() + 1);
562  aPalette[aPalette.GetEntryCount() - 1] = *pExtColor;
563  }
564 
565  // set Black/White always, if we have enough space
566  if (aPalette.GetEntryCount() < (nCount - 1))
567  {
568  aPalette.SetEntryCount(aPalette.GetEntryCount() + 2);
569  aPalette[aPalette.GetEntryCount() - 2] = COL_BLACK;
570  aPalette[aPalette.GetEntryCount() - 1] = COL_WHITE;
571  }
572 
573  pWriteAcc->SetPalette(aPalette);
574 
575  for (long nY = 0; nY < std::min(nHeight, 2L); nY++, nYTmp++)
576  {
577  pQLine2 = !nY ? aErrQuad1.data() : aErrQuad2.data();
578  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
579  for (long nX = 0; nX < nWidth; nX++)
580  {
581  if (pReadAcc->HasPalette())
582  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
583  else
584  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
585  }
586  }
587 
588  assert(pQLine2 || nHeight == 0);
589 
590  for (long nY = 0; nY < nHeight; nY++, nYTmp++)
591  {
592  // first pixel in the line
593  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[0].ImplGetColor()));
594  Scanline pScanline = pWriteAcc->GetScanline(nY);
595  pWriteAcc->SetPixelOnData(pScanline, 0, BitmapColor(cIndex));
596 
597  long nX;
598  for (nX = 1; nX < nWidth1; nX++)
599  {
600  aColor = pQLine1[nX].ImplGetColor();
601  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(aColor));
602  aErrQuad = (ImpErrorQuad(aColor) -= pWriteAcc->GetPaletteColor(cIndex));
603  pQLine1[++nX].ImplAddColorError7(aErrQuad);
604  pQLine2[nX--].ImplAddColorError1(aErrQuad);
605  pQLine2[nX--].ImplAddColorError5(aErrQuad);
606  pQLine2[nX++].ImplAddColorError3(aErrQuad);
607  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
608  }
609 
610  // Last RowPixel
611  if (nX < nWidth)
612  {
613  cIndex = static_cast<sal_uInt8>(aColorMap.GetBestPaletteIndex(pQLine1[nWidth1].ImplGetColor()));
614  pWriteAcc->SetPixelOnData(pScanline, nX, BitmapColor(cIndex));
615  }
616 
617  // Refill/copy row buffer
618  pQLine1 = pQLine2;
619  bQ1 = !bQ1;
620  pQLine2 = bQ1 ? aErrQuad2.data() : aErrQuad1.data();
621 
622  if (nYTmp < nHeight)
623  {
624  Scanline pScanlineRead = pReadAcc->GetScanline(nYTmp);
625  for (nX = 0; nX < nWidth; nX++)
626  {
627  if (pReadAcc->HasPalette())
628  pQLine2[nX] = pReadAcc->GetPaletteColor(pReadAcc->GetIndexFromData(pScanlineRead, nX));
629  else
630  pQLine2[nX] = pReadAcc->GetPixelFromData(pScanlineRead, nX);
631  }
632  }
633  }
634 
635  bRet = true;
636  }
637 
638  if(bRet)
639  {
640  const MapMode aMap(maPrefMapMode);
641  const Size aSize(maPrefSize);
642 
643  *this = aNewBmp;
644 
645  maPrefMapMode = aMap;
646  maPrefSize = aSize;
647  }
648  }
649 
650  return bRet;
651 }
652 
654 {
655  Bitmap aNewBmp;
656  ScopedReadAccess pR(*this);
657  bool bRet = false;
658 
659  if( pR )
660  {
661  if( pR->HasPalette() )
662  {
663  BitmapPalette aNewPal( pR->GetPaletteEntryCount() );
664 
665  for( long i = 0, nCount = aNewPal.GetEntryCount(); i < nCount; i++ )
666  {
667  const BitmapColor& rOld = pR->GetPaletteColor( static_cast<sal_uInt16>(i) );
668  aNewPal[ static_cast<sal_uInt16>(i) ] = BitmapColor( ( rOld.GetRed() >> 1 ) | 0x80,
669  ( rOld.GetGreen() >> 1 ) | 0x80,
670  ( rOld.GetBlue() >> 1 ) | 0x80 );
671  }
672 
673  aNewBmp = Bitmap( GetSizePixel(), GetBitCount(), &aNewPal );
674  BitmapScopedWriteAccess pW(aNewBmp);
675 
676  if( pW )
677  {
678  pW->CopyBuffer( *pR );
679  bRet = true;
680  }
681  }
682  else
683  {
684  aNewBmp = Bitmap( GetSizePixel(), 24 );
685 
686  BitmapScopedWriteAccess pW(aNewBmp);
687 
688  if( pW )
689  {
690  const long nWidth = pR->Width(), nHeight = pR->Height();
691 
692  for( long nY = 0; nY < nHeight; nY++ )
693  {
694  Scanline pScanline = pW->GetScanline(nY);
695  Scanline pScanlineRead = pR->GetScanline(nY);
696  for( long nX = 0; nX < nWidth; nX++ )
697  {
698  const BitmapColor aOld( pR->GetPixelFromData( pScanlineRead, nX ) );
699  pW->SetPixelOnData( pScanline, nX, BitmapColor( ( aOld.GetRed() >> 1 ) | 0x80,
700  ( aOld.GetGreen() >> 1 ) | 0x80,
701  ( aOld.GetBlue() >> 1 ) | 0x80 ) );
702 
703  }
704  }
705 
706  bRet = true;
707  }
708  }
709 
710  pR.reset();
711  }
712 
713  if( bRet )
714  {
715  const MapMode aMap( maPrefMapMode );
716  const Size aSize( maPrefSize );
717 
718  *this = aNewBmp;
719 
720  maPrefMapMode = aMap;
721  maPrefSize = aSize;
722  }
723 
724  return bRet;
725 }
726 
727 bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
728 {
730  {
731  // no scale
732  return true;
733  }
734 
735  if(basegfx::fTools::equal(rScaleX, 1.0) && basegfx::fTools::equal(rScaleY, 1.0))
736  {
737  // no scale
738  return true;
739  }
740 
741  const sal_uInt16 nStartCount(GetBitCount());
742 
743  if (mxSalBmp && mxSalBmp->ScalingSupported())
744  {
745  // implementation specific scaling
746  std::shared_ptr<SalBitmap> xImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
747  if (xImpBmp->Create(*mxSalBmp) && xImpBmp->Scale(rScaleX, rScaleY, nScaleFlag))
748  {
749  ImplSetSalBitmap(xImpBmp);
750  SAL_INFO( "vcl.opengl", "Ref count: " << mxSalBmp.use_count() );
751  maPrefMapMode = MapMode( MapUnit::MapPixel );
752  maPrefSize = xImpBmp->GetSize();
753  return true;
754  }
755  }
756 
757  // fdo#33455
758  //
759  // If we start with a 1 bit image, then after scaling it in any mode except
760  // BmpScaleFlag::Fast we have a 24bit image which is perfectly correct, but we
761  // are going to down-shift it to mono again and Bitmap::MakeMonochrome just
762  // has "Bitmap aNewBmp( GetSizePixel(), 1 );" to create a 1 bit bitmap which
763  // will default to black/white and the colors mapped to which ever is closer
764  // to black/white
765  //
766  // So the easiest thing to do to retain the colors of 1 bit bitmaps is to
767  // just use the fast scale rather than attempting to count unique colors in
768  // the other converters and pass all the info down through
769  // Bitmap::MakeMonochrome
770  if (nStartCount == 1)
771  nScaleFlag = BmpScaleFlag::Fast;
772 
773  BitmapEx aBmpEx(*this);
774  bool bRetval(false);
775 
776  switch(nScaleFlag)
777  {
779  if (GetSizePixel().Width() < 2 || GetSizePixel().Height() < 2)
780  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
781  else
782  bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
783  break;
784 
785  case BmpScaleFlag::Fast:
787  bRetval = BitmapFilter::Filter(aBmpEx, BitmapFastScaleFilter(rScaleX, rScaleY));
788  break;
789 
791  bRetval = BitmapFilter::Filter(aBmpEx, BitmapInterpolateScaleFilter(rScaleX, rScaleY));
792  break;
793 
794  case BmpScaleFlag::Super:
795  bRetval = BitmapFilter::Filter(aBmpEx, BitmapScaleSuperFilter(rScaleX, rScaleY));
796  break;
799  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleLanczos3Filter(rScaleX, rScaleY));
800  break;
801 
803  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBicubicFilter(rScaleX, rScaleY));
804  break;
805 
807  bRetval = BitmapFilter::Filter(aBmpEx, vcl::BitmapScaleBilinearFilter(rScaleX, rScaleY));
808  break;
809  }
810 
811  if (bRetval)
812  *this = aBmpEx.GetBitmapRef();
813 
814  OSL_ENSURE(!bRetval || nStartCount == GetBitCount(), "Bitmap::Scale has changed the ColorDepth, this should *not* happen (!)");
815  return bRetval;
816 }
817 
818 bool Bitmap::Scale( const Size& rNewSize, BmpScaleFlag nScaleFlag )
819 {
820  const Size aSize( GetSizePixel() );
821  bool bRet;
822 
823  if( aSize.Width() && aSize.Height() )
824  {
825  bRet = Scale( static_cast<double>(rNewSize.Width()) / aSize.Width(),
826  static_cast<double>(rNewSize.Height()) / aSize.Height(),
827  nScaleFlag );
828  }
829  else
830  bRet = true;
831 
832  return bRet;
833 }
834 
836 {
837 #if HAVE_FEATURE_OPENGL
839 #else
840  return false;
841 #endif
842 }
843 
844 void Bitmap::AdaptBitCount(Bitmap& rNew) const
845 {
846  // aNew is the result of some operation; adapt it's BitCount to the original (this)
847  if(GetBitCount() != rNew.GetBitCount())
848  {
849  switch(GetBitCount())
850  {
851  case 1:
852  {
854  break;
855  }
856  case 4:
857  {
858  if(HasGreyPalette())
859  {
861  }
862  else
863  {
865  }
866  break;
867  }
868  case 8:
869  {
870  if(HasGreyPalette())
871  {
873  }
874  else
875  {
877  }
878  break;
879  }
880  case 24:
881  {
883  break;
884  }
885  default:
886  {
887  OSL_ENSURE(false, "BitDepth adaptation failed (!)");
888  break;
889  }
890  }
891  }
892 }
893 
895 {
896  const Size aSize( GetSizePixel() );
897 
898  if( aSize.Width() == 1 || aSize.Height() == 1 )
899  return true;
900 
901  bool bRet = false;
902 
903  if( ( aSize.Width() > 3 ) && ( aSize.Height() > 2 ) )
904  {
905  ScopedReadAccess pReadAcc(*this);
906  Bitmap aNewBmp( GetSizePixel(), 8 );
907  BitmapScopedWriteAccess pWriteAcc(aNewBmp);
908 
909  if( pReadAcc && pWriteAcc )
910  {
911  BitmapColor aColor;
912  long nWidth = pReadAcc->Width();
913  long nWidth1 = nWidth - 1;
914  long nHeight = pReadAcc->Height();
915  long nX;
916  long nW = nWidth * 3;
917  long nW2 = nW - 3;
918  long nRErr, nGErr, nBErr;
919  long nRC, nGC, nBC;
920  std::unique_ptr<long[]> p1(new long[ nW ]);
921  std::unique_ptr<long[]> p2(new long[ nW ]);
922  long* p1T = p1.get();
923  long* p2T = p2.get();
924  long* pTmp;
925  bool bPal = pReadAcc->HasPalette();
926 
927  pTmp = p2T;
928 
929  if( bPal )
930  {
931  Scanline pScanlineRead = pReadAcc->GetScanline(0);
932  for( long nZ = 0; nZ < nWidth; nZ++ )
933  {
934  aColor = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( 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  else
942  {
943  Scanline pScanlineRead = pReadAcc->GetScanline(0);
944  for( long nZ = 0; nZ < nWidth; nZ++ )
945  {
946  aColor = pReadAcc->GetPixelFromData( pScanlineRead, nZ );
947 
948  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
949  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
950  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
951  }
952  }
953 
954  for( long nY = 1, nYAcc = 0; nY <= nHeight; nY++, nYAcc++ )
955  {
956  pTmp = p1T;
957  p1T = p2T;
958  p2T = pTmp;
959 
960  if( nY < nHeight )
961  {
962  if( bPal )
963  {
964  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
965  for( long nZ = 0; nZ < nWidth; nZ++ )
966  {
967  aColor = pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nZ ) );
968 
969  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
970  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
971  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
972  }
973  }
974  else
975  {
976  Scanline pScanlineRead = pReadAcc->GetScanline(nY);
977  for( long nZ = 0; nZ < nWidth; nZ++ )
978  {
979  aColor = pReadAcc->GetPixelFromData( pScanlineRead, nZ );
980 
981  *pTmp++ = static_cast<long>(aColor.GetBlue()) << 12;
982  *pTmp++ = static_cast<long>(aColor.GetGreen()) << 12;
983  *pTmp++ = static_cast<long>(aColor.GetRed()) << 12;
984  }
985  }
986  }
987 
988  // Examine first Pixel separately
989  nX = 0;
990  long nTemp;
991  CALC_ERRORS;
992  CALC_TABLES7;
993  nX -= 5;
994  CALC_TABLES5;
995  Scanline pScanline = pWriteAcc->GetScanline(nYAcc);
996  pWriteAcc->SetPixelOnData( pScanline, 0, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
997 
998  // Get middle Pixels using a loop
999  long nXAcc;
1000  for ( nX = 3, nXAcc = 1; nX < nW2; nXAcc++ )
1001  {
1002  CALC_ERRORS;
1003  CALC_TABLES7;
1004  nX -= 8;
1005  CALC_TABLES3;
1006  CALC_TABLES5;
1007  pWriteAcc->SetPixelOnData( pScanline, nXAcc, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1008  }
1009 
1010  // Treat last Pixel separately
1011  CALC_ERRORS;
1012  nX -= 5;
1013  CALC_TABLES3;
1014  CALC_TABLES5;
1015  pWriteAcc->SetPixelOnData( pScanline, nWidth1, BitmapColor(static_cast<sal_uInt8>(nVCLBLut[ nBC ] + nVCLGLut[nGC ] + nVCLRLut[nRC ])) );
1016  }
1017 
1018  bRet = true;
1019  }
1020 
1021  pReadAcc.reset();
1022  pWriteAcc.reset();
1023 
1024  if( bRet )
1025  {
1026  const MapMode aMap( maPrefMapMode );
1027  const Size aPrefSize( maPrefSize );
1028 
1029  *this = aNewBmp;
1030 
1031  maPrefMapMode = aMap;
1032  maPrefSize = aPrefSize;
1033  }
1034  }
1035 
1036  return bRet;
1037 }
1038 
1039 void Bitmap::Vectorize( GDIMetaFile& rMtf, sal_uInt8 cReduce, const Link<long,void>* pProgress )
1040 {
1041  ImplVectorizer::ImplVectorize( *this, rMtf, cReduce, pProgress );
1042 }
1043 
1044 bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
1045  short nChannelRPercent, short nChannelGPercent, short nChannelBPercent,
1046  double fGamma, bool bInvert, bool msoBrightness )
1047 {
1048  bool bRet = false;
1049 
1050  // nothing to do => return quickly
1051  if( !nLuminancePercent && !nContrastPercent &&
1052  !nChannelRPercent && !nChannelGPercent && !nChannelBPercent &&
1053  ( fGamma == 1.0 ) && !bInvert )
1054  {
1055  bRet = true;
1056  }
1057  else
1058  {
1059  BitmapScopedWriteAccess pAcc(*this);
1060 
1061  if( pAcc )
1062  {
1063  BitmapColor aCol;
1064  const long nW = pAcc->Width();
1065  const long nH = pAcc->Height();
1066  std::unique_ptr<sal_uInt8[]> cMapR(new sal_uInt8[ 256 ]);
1067  std::unique_ptr<sal_uInt8[]> cMapG(new sal_uInt8[ 256 ]);
1068  std::unique_ptr<sal_uInt8[]> cMapB(new sal_uInt8[ 256 ]);
1069  double fM, fROff, fGOff, fBOff, fOff;
1070 
1071  // calculate slope
1072  if( nContrastPercent >= 0 )
1073  fM = 128.0 / ( 128.0 - 1.27 * MinMax( nContrastPercent, 0, 100 ) );
1074  else
1075  fM = ( 128.0 + 1.27 * MinMax( nContrastPercent, -100, 0 ) ) / 128.0;
1076 
1077  if(!msoBrightness)
1078  // total offset = luminance offset + contrast offset
1079  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55 + 128.0 - fM * 128.0;
1080  else
1081  fOff = MinMax( nLuminancePercent, -100, 100 ) * 2.55;
1082 
1083  // channel offset = channel offset + total offset
1084  fROff = nChannelRPercent * 2.55 + fOff;
1085  fGOff = nChannelGPercent * 2.55 + fOff;
1086  fBOff = nChannelBPercent * 2.55 + fOff;
1087 
1088  // calculate gamma value
1089  fGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
1090  const bool bGamma = ( fGamma != 1.0 );
1091 
1092  // create mapping table
1093  for( long nX = 0; nX < 256; nX++ )
1094  {
1095  if(!msoBrightness)
1096  {
1097  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fROff ), 0, 255 ));
1098  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fGOff ), 0, 255 ));
1099  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( nX * fM + fBOff ), 0, 255 ));
1100  }
1101  else
1102  {
1103  // LO simply uses (in a somewhat optimized form) "newcolor = (oldcolor-128)*contrast+brightness+128"
1104  // as the formula, i.e. contrast first, brightness afterwards. MSOffice, for whatever weird reason,
1105  // use neither first, but apparently it applies half of brightness before contrast and half afterwards.
1106  cMapR[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fROff/2-128) * fM + 128 + fROff/2 ), 0, 255 ));
1107  cMapG[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fGOff/2-128) * fM + 128 + fGOff/2 ), 0, 255 ));
1108  cMapB[ nX ] = static_cast<sal_uInt8>(MinMax( FRound( (nX+fBOff/2-128) * fM + 128 + fBOff/2 ), 0, 255 ));
1109  }
1110  if( bGamma )
1111  {
1112  cMapR[ nX ] = GAMMA( cMapR[ nX ], fGamma );
1113  cMapG[ nX ] = GAMMA( cMapG[ nX ], fGamma );
1114  cMapB[ nX ] = GAMMA( cMapB[ nX ], fGamma );
1115  }
1116 
1117  if( bInvert )
1118  {
1119  cMapR[ nX ] = ~cMapR[ nX ];
1120  cMapG[ nX ] = ~cMapG[ nX ];
1121  cMapB[ nX ] = ~cMapB[ nX ];
1122  }
1123  }
1124 
1125  // do modifying
1126  if( pAcc->HasPalette() )
1127  {
1128  BitmapColor aNewCol;
1129 
1130  for( sal_uInt16 i = 0, nCount = pAcc->GetPaletteEntryCount(); i < nCount; i++ )
1131  {
1132  const BitmapColor& rCol = pAcc->GetPaletteColor( i );
1133  aNewCol.SetRed( cMapR[ rCol.GetRed() ] );
1134  aNewCol.SetGreen( cMapG[ rCol.GetGreen() ] );
1135  aNewCol.SetBlue( cMapB[ rCol.GetBlue() ] );
1136  pAcc->SetPaletteColor( i, aNewCol );
1137  }
1138  }
1139  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcBgr )
1140  {
1141  for( long nY = 0; nY < nH; nY++ )
1142  {
1143  Scanline pScan = pAcc->GetScanline( nY );
1144 
1145  for( long nX = 0; nX < nW; nX++ )
1146  {
1147  *pScan = cMapB[ *pScan ]; pScan++;
1148  *pScan = cMapG[ *pScan ]; pScan++;
1149  *pScan = cMapR[ *pScan ]; pScan++;
1150  }
1151  }
1152  }
1153  else if( pAcc->GetScanlineFormat() == ScanlineFormat::N24BitTcRgb )
1154  {
1155  for( long nY = 0; nY < nH; nY++ )
1156  {
1157  Scanline pScan = pAcc->GetScanline( nY );
1158 
1159  for( long nX = 0; nX < nW; nX++ )
1160  {
1161  *pScan = cMapR[ *pScan ]; pScan++;
1162  *pScan = cMapG[ *pScan ]; pScan++;
1163  *pScan = cMapB[ *pScan ]; pScan++;
1164  }
1165  }
1166  }
1167  else
1168  {
1169  for( long nY = 0; nY < nH; nY++ )
1170  {
1171  Scanline pScanline = pAcc->GetScanline(nY);
1172  for( long nX = 0; nX < nW; nX++ )
1173  {
1174  aCol = pAcc->GetPixelFromData( pScanline, nX );
1175  aCol.SetRed( cMapR[ aCol.GetRed() ] );
1176  aCol.SetGreen( cMapG[ aCol.GetGreen() ] );
1177  aCol.SetBlue( cMapB[ aCol.GetBlue() ] );
1178  pAcc->SetPixelOnData( pScanline, nX, aCol );
1179  }
1180  }
1181  }
1182 
1183  pAcc.reset();
1184  bRet = true;
1185  }
1186  }
1187 
1188  return bRet;
1189 }
1190 
1191 /* 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:835
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:1044
#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:653
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:618
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
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:1039
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
bool Dither()
Apply a Floyd dither algorithm to the bitmap.
Definition: bitmap3.cxx:894
Bitmap GetBitmap(const Color *pTransReplaceColor=nullptr) const
Definition: bitmapex.cxx:236
SAL_DLLPRIVATE bool ImplConvertDown(sal_uInt16 nBitCount, Color const *pExtColor=nullptr)
Definition: bitmap3.cxx:527
const long FloydError7[61]
Definition: bitmap3.cxx:207
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:67
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:438
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
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:320
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:818
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:844
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
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: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