1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 #include <tools/debug.hxx>
27 #include <vcl/bmpacc.hxx>
28 #include <tools/color.hxx>
29 #include <vcl/alpha.hxx>
30
31 // -------------
32 // - AlphaMask -
33 // -------------
34
AlphaMask()35 AlphaMask::AlphaMask()
36 {
37 }
38
39 // -----------------------------------------------------------------------------
40
AlphaMask(const Bitmap & rBitmap)41 AlphaMask::AlphaMask( const Bitmap& rBitmap ) :
42 Bitmap( rBitmap )
43 {
44 if( !!rBitmap )
45 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
46 }
47
48 // -----------------------------------------------------------------------------
49
AlphaMask(const AlphaMask & rAlphaMask)50 AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) :
51 Bitmap( rAlphaMask )
52 {
53 }
54
55 // -----------------------------------------------------------------------------
56
AlphaMask(const Size & rSizePixel,sal_uInt8 * pEraseTransparency)57 AlphaMask::AlphaMask( const Size& rSizePixel, sal_uInt8* pEraseTransparency ) :
58 Bitmap( rSizePixel, 8, &Bitmap::GetGreyPalette( 256 ) )
59 {
60 if( pEraseTransparency )
61 Bitmap::Erase( Color( *pEraseTransparency, *pEraseTransparency, *pEraseTransparency ) );
62 }
63
64 // -----------------------------------------------------------------------------
65
~AlphaMask()66 AlphaMask::~AlphaMask()
67 {
68 }
69
70 // -----------------------------------------------------------------------------
71
operator =(const Bitmap & rBitmap)72 AlphaMask& AlphaMask::operator=( const Bitmap& rBitmap )
73 {
74 *(Bitmap*) this = rBitmap;
75
76 if( !!rBitmap )
77 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
78
79 return *this;
80 }
81
82 // -----------------------------------------------------------------------------
83
ImplGetBitmap() const84 const Bitmap& AlphaMask::ImplGetBitmap() const
85 {
86 return( (const Bitmap&) *this );
87 }
88
89 // -----------------------------------------------------------------------------
90
ImplSetBitmap(const Bitmap & rBitmap)91 void AlphaMask::ImplSetBitmap( const Bitmap& rBitmap )
92 {
93 DBG_ASSERT( ( 8 == rBitmap.GetBitCount() ) && rBitmap.HasGreyPalette(), "AlphaMask::ImplSetBitmap: invalid bitmap" );
94 *(Bitmap*) this = rBitmap;
95 }
96
97 // -----------------------------------------------------------------------------
98
GetBitmap() const99 Bitmap AlphaMask::GetBitmap() const
100 {
101 return ImplGetBitmap();
102 }
103
104 // -----------------------------------------------------------------------------
105
Crop(const Rectangle & rRectPixel)106 sal_Bool AlphaMask::Crop( const Rectangle& rRectPixel )
107 {
108 return Bitmap::Crop( rRectPixel );
109 }
110
111 // -----------------------------------------------------------------------------
112
Expand(sal_uLong nDX,sal_uLong nDY,sal_uInt8 * pInitTransparency)113 sal_Bool AlphaMask::Expand( sal_uLong nDX, sal_uLong nDY, sal_uInt8* pInitTransparency )
114 {
115 Color aColor;
116
117 if( pInitTransparency )
118 aColor = Color( *pInitTransparency, *pInitTransparency, *pInitTransparency );
119
120 return Bitmap::Expand( nDX, nDY, pInitTransparency ? &aColor : NULL );
121 }
122
123 // -----------------------------------------------------------------------------
124
CopyPixel(const Rectangle & rRectDst,const Rectangle & rRectSrc,const AlphaMask * pAlphaSrc)125 sal_Bool AlphaMask::CopyPixel( const Rectangle& rRectDst, const Rectangle& rRectSrc,
126 const AlphaMask* pAlphaSrc )
127 {
128 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
129 // this optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
130
131 const Size aSizePix( GetSizePixel() );
132 Rectangle aRectDst( rRectDst );
133 sal_Bool bRet = sal_False;
134
135 aRectDst.Intersection( Rectangle( Point(), aSizePix ) );
136
137 if( !aRectDst.IsEmpty() )
138 {
139 if( pAlphaSrc && ( *pAlphaSrc != *this ) )
140 {
141 Bitmap* pSrc = (Bitmap*) pAlphaSrc;
142 const Size aCopySizePix( pSrc->GetSizePixel() );
143 Rectangle aRectSrc( rRectSrc );
144
145 aRectSrc.Intersection( Rectangle( Point(), aCopySizePix ) );
146
147 if( !aRectSrc.IsEmpty() )
148 {
149 BitmapReadAccess* pReadAcc = pSrc->AcquireReadAccess();
150
151 if( pReadAcc )
152 {
153 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
154
155 if( pWriteAcc )
156 {
157 const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
158 const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
159 const long nSrcEndX = aRectSrc.Left() + nWidth;
160 const long nSrcEndY = aRectSrc.Top() + nHeight;
161 long nDstY = aRectDst.Top();
162
163 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
164 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
165 pWriteAcc->SetPixel( nDstY, nDstX, pReadAcc->GetPixel( nSrcY, nSrcX ) );
166
167 ReleaseAccess( pWriteAcc );
168 bRet = ( nWidth > 0L ) && ( nHeight > 0L );
169 }
170
171 pSrc->ReleaseAccess( pReadAcc );
172 }
173 }
174 }
175 else
176 {
177 Rectangle aRectSrc( rRectSrc );
178
179 aRectSrc.Intersection( Rectangle( Point(), aSizePix ) );
180
181 if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
182 {
183 BitmapWriteAccess* pWriteAcc = AcquireWriteAccess();
184
185 if( pWriteAcc )
186 {
187 const long nWidth = Min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
188 const long nHeight = Min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
189 const long nSrcX = aRectSrc.Left();
190 const long nSrcY = aRectSrc.Top();
191 const long nSrcEndX1 = nSrcX + nWidth - 1L;
192 const long nSrcEndY1 = nSrcY + nHeight - 1L;
193 const long nDstX = aRectDst.Left();
194 const long nDstY = aRectDst.Top();
195 const long nDstEndX1 = nDstX + nWidth - 1L;
196 const long nDstEndY1 = nDstY + nHeight - 1L;
197
198 if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
199 {
200 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
201 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
202 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
203 }
204 else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
205 {
206 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
207 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
208 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
209 }
210 else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
211 {
212 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
213 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
214 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
215 }
216 else
217 {
218 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
219 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
220 pWriteAcc->SetPixel( nYN, nXN, pWriteAcc->GetPixel( nY, nX ) );
221 }
222
223 ReleaseAccess( pWriteAcc );
224 bRet = sal_True;
225 }
226 }
227 }
228 }
229
230 return bRet;
231
232 }
233
234 // -----------------------------------------------------------------------------
235
Erase(sal_uInt8 cTransparency)236 sal_Bool AlphaMask::Erase( sal_uInt8 cTransparency )
237 {
238 return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) );
239 }
240
241 // -----------------------------------------------------------------------------
242
Invert()243 sal_Bool AlphaMask::Invert()
244 {
245 BitmapWriteAccess* pAcc = AcquireWriteAccess();
246 sal_Bool bRet = sal_False;
247
248 if( pAcc && pAcc->GetBitCount() == 8 )
249 {
250 BitmapColor aCol( 0 );
251 const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
252 sal_uInt8* pMap = new sal_uInt8[ 256 ];
253
254 for( long i = 0; i < 256; i++ )
255 pMap[ i ] = ~(sal_uInt8) i;
256
257 for( long nY = 0L; nY < nHeight; nY++ )
258 {
259 for( long nX = 0L; nX < nWidth; nX++ )
260 {
261 aCol.SetIndex( pMap[ pAcc->GetPixel( nY, nX ).GetIndex() ] );
262 pAcc->SetPixel( nY, nX, aCol );
263 }
264 }
265
266 delete[] pMap;
267 bRet = sal_True;
268 }
269
270 if( pAcc )
271 ReleaseAccess( pAcc );
272
273 return bRet;
274 }
275
276 // -----------------------------------------------------------------------------
277
Mirror(sal_uLong nMirrorFlags)278 sal_Bool AlphaMask::Mirror( sal_uLong nMirrorFlags )
279 {
280 return Bitmap::Mirror( nMirrorFlags );
281 }
282
283 // -----------------------------------------------------------------------------
284
Scale(const Size & rNewSize,sal_uInt32 nScaleFlag)285 sal_Bool AlphaMask::Scale( const Size& rNewSize, sal_uInt32 nScaleFlag )
286 {
287 sal_Bool bRet = Bitmap::Scale( rNewSize, nScaleFlag );
288
289 if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
290 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
291
292 return bRet;
293 }
294
295 // -----------------------------------------------------------------------------
296
Scale(const double & rScaleX,const double & rScaleY,sal_uInt32 nScaleFlag)297 sal_Bool AlphaMask::Scale( const double& rScaleX, const double& rScaleY, sal_uInt32 nScaleFlag )
298 {
299 sal_Bool bRet = Bitmap::Scale( rScaleX, rScaleY, nScaleFlag );
300
301 if( bRet && ( nScaleFlag == BMP_SCALE_INTERPOLATE ) )
302 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
303
304 return bRet;
305 }
306
307 // -----------------------------------------------------------------------------
308
Rotate(long nAngle10,sal_uInt8 cFillTransparency)309 sal_Bool AlphaMask::Rotate( long nAngle10, sal_uInt8 cFillTransparency )
310 {
311 return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) );
312 }
313
314 // -----------------------------------------------------------------------------
315
Replace(const Bitmap & rMask,sal_uInt8 cReplaceTransparency)316 sal_Bool AlphaMask::Replace( const Bitmap& rMask, sal_uInt8 cReplaceTransparency )
317 {
318 BitmapReadAccess* pMaskAcc = ( (Bitmap&) rMask ).AcquireReadAccess();
319 BitmapWriteAccess* pAcc = AcquireWriteAccess();
320 sal_Bool bRet = sal_False;
321
322 if( pMaskAcc && pAcc )
323 {
324 const BitmapColor aReplace( cReplaceTransparency );
325 const long nWidth = Min( pMaskAcc->Width(), pAcc->Width() );
326 const long nHeight = Min( pMaskAcc->Height(), pAcc->Height() );
327 const BitmapColor aMaskWhite( pMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) ) );
328
329 for( long nY = 0L; nY < nHeight; nY++ )
330 for( long nX = 0L; nX < nWidth; nX++ )
331 if( pMaskAcc->GetPixel( nY, nX ) == aMaskWhite )
332 pAcc->SetPixel( nY, nX, aReplace );
333 }
334
335 ( (Bitmap&) rMask ).ReleaseAccess( pMaskAcc );
336 ReleaseAccess( pAcc );
337
338 return bRet;
339 }
340
341 // -----------------------------------------------------------------------------
342
Replace(sal_uInt8 cSearchTransparency,sal_uInt8 cReplaceTransparency,sal_uLong nTol)343 sal_Bool AlphaMask::Replace( sal_uInt8 cSearchTransparency, sal_uInt8 cReplaceTransparency, sal_uLong
344 #ifdef DBG_UTIL
345 nTol
346 #endif
347 )
348 {
349 BitmapWriteAccess* pAcc = AcquireWriteAccess();
350 sal_Bool bRet = sal_False;
351
352 DBG_ASSERT( !nTol, "AlphaMask::Replace: nTol not used yet" );
353
354 if( pAcc && pAcc->GetBitCount() == 8 )
355 {
356 const long nWidth = pAcc->Width(), nHeight = pAcc->Height();
357
358 if( pAcc->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL )
359 {
360 for( long nY = 0L; nY < nHeight; nY++ )
361 {
362 Scanline pScan = pAcc->GetScanline( nY );
363
364 for( long nX = 0L; nX < nWidth; nX++, pScan++ )
365 {
366 if( *pScan == cSearchTransparency )
367 *pScan = cReplaceTransparency;
368 }
369 }
370 }
371 else
372 {
373 BitmapColor aReplace( cReplaceTransparency );
374
375 for( long nY = 0L; nY < nHeight; nY++ )
376 {
377 for( long nX = 0L; nX < nWidth; nX++ )
378 {
379 if( pAcc->GetPixel( nY, nX ).GetIndex() == cSearchTransparency )
380 pAcc->SetPixel( nY, nX, aReplace );
381 }
382 }
383 }
384
385 bRet = sal_True;
386 }
387
388 if( pAcc )
389 ReleaseAccess( pAcc );
390
391 return bRet;
392 }
393
394 // -----------------------------------------------------------------------------
395
Replace(sal_uInt8 * pSearchTransparencies,sal_uInt8 * pReplaceTransparencies,sal_uLong nColorCount,sal_uLong * pTols)396 sal_Bool AlphaMask::Replace( sal_uInt8* pSearchTransparencies, sal_uInt8* pReplaceTransparencies,
397 sal_uLong nColorCount, sal_uLong* pTols )
398 {
399 Color* pSearchColors = new Color[ nColorCount ];
400 Color* pReplaceColors = new Color[ nColorCount ];
401 sal_Bool bRet;
402
403 for( sal_uLong i = 0; i < nColorCount; i++ )
404 {
405 const sal_uInt8 cSearchTransparency = pSearchTransparencies[ i ];
406 const sal_uInt8 cReplaceTransparency = pReplaceTransparencies[ i ];
407
408 pSearchColors[ i ] = Color( cSearchTransparency, cSearchTransparency, cSearchTransparency );
409 pReplaceColors[ i ] = Color( cReplaceTransparency, cReplaceTransparency, cReplaceTransparency );
410 }
411
412 bRet = Bitmap::Replace( pSearchColors, pReplaceColors, nColorCount, pTols ) &&
413 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
414
415 delete[] pSearchColors;
416 delete[] pReplaceColors;
417
418 return bRet;
419 }
420
421 // -----------------------------------------------------------------------------
422
ReleaseAccess(BitmapReadAccess * pAccess)423 void AlphaMask::ReleaseAccess( BitmapReadAccess* pAccess )
424 {
425 if( pAccess )
426 {
427 Bitmap::ReleaseAccess( pAccess );
428 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS );
429 }
430 }
431