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 35 AlphaMask::AlphaMask() 36 { 37 } 38 39 // ----------------------------------------------------------------------------- 40 41 AlphaMask::AlphaMask( const Bitmap& rBitmap ) : 42 Bitmap( rBitmap ) 43 { 44 if( !!rBitmap ) 45 Bitmap::Convert( BMP_CONVERSION_8BIT_GREYS ); 46 } 47 48 // ----------------------------------------------------------------------------- 49 50 AlphaMask::AlphaMask( const AlphaMask& rAlphaMask ) : 51 Bitmap( rAlphaMask ) 52 { 53 } 54 55 // ----------------------------------------------------------------------------- 56 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 66 AlphaMask::~AlphaMask() 67 { 68 } 69 70 // ----------------------------------------------------------------------------- 71 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 84 const Bitmap& AlphaMask::ImplGetBitmap() const 85 { 86 return( (const Bitmap&) *this ); 87 } 88 89 // ----------------------------------------------------------------------------- 90 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 99 Bitmap AlphaMask::GetBitmap() const 100 { 101 return ImplGetBitmap(); 102 } 103 104 // ----------------------------------------------------------------------------- 105 106 sal_Bool AlphaMask::Crop( const Rectangle& rRectPixel ) 107 { 108 return Bitmap::Crop( rRectPixel ); 109 } 110 111 // ----------------------------------------------------------------------------- 112 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 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 236 sal_Bool AlphaMask::Erase( sal_uInt8 cTransparency ) 237 { 238 return Bitmap::Erase( Color( cTransparency, cTransparency, cTransparency ) ); 239 } 240 241 // ----------------------------------------------------------------------------- 242 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 278 sal_Bool AlphaMask::Mirror( sal_uLong nMirrorFlags ) 279 { 280 return Bitmap::Mirror( nMirrorFlags ); 281 } 282 283 // ----------------------------------------------------------------------------- 284 285 sal_Bool AlphaMask::Scale( const Size& rNewSize, sal_uLong 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 297 sal_Bool AlphaMask::Scale( const double& rScaleX, const double& rScaleY, sal_uLong 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 309 sal_Bool AlphaMask::Rotate( long nAngle10, sal_uInt8 cFillTransparency ) 310 { 311 return Bitmap::Rotate( nAngle10, Color( cFillTransparency, cFillTransparency, cFillTransparency ) ); 312 } 313 314 // ----------------------------------------------------------------------------- 315 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 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 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 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