1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vcl/bmpacc.hxx>
21 #include <vcl/salbtype.hxx>
22 #include <bmpfast.hxx>
24 #define IMPL_CASE_GET_FORMAT( Format ) \
25 case( BMP_FORMAT##Format ): \
26 pFncGetPixel = BitmapReadAccess::GetPixelFor##Format; \
29 #define IMPL_CASE_SET_FORMAT( Format, BitCount ) \
30 case( BMP_FORMAT##Format ): \
32 pFncSetPixel = BitmapReadAccess::SetPixelFor##Format; \
33 pDstBuffer->mnBitCount = BitCount; \
37 #define DOUBLE_SCANLINES() \
38 while( ( nActY < nHeight1 ) && ( pMapY[ nActY + 1 ] == nMapY ) ) \
40 memcpy( pDstScanMap[ nActY + 1L ], pDstScan, rDstBuffer.mnScanlineSize ); \
44 #define TC_TO_PAL_COLORS 4096
46 static long ImplIndexFromColor( const BitmapColor
& rCol
)
48 #if TC_TO_PAL_COLORS == 4096
50 return( ( ( (long) rCol
.GetBlue() >> 4L) << 8L ) |
51 ( ( (long) rCol
.GetGreen() >> 4L ) << 4L ) |
52 ( (long) rCol
.GetRed() >> 4L ) );
54 #elif TC_TO_PAL_COLORS == 32768
56 return( ( ( (long) rCol
.GetBlue() >> 3L) << 10L ) |
57 ( ( (long) rCol
.GetGreen() >> 3L ) << 5L ) |
58 ( (long) rCol
.GetRed() >> 3L ) );
63 static void ImplPALToPAL( const BitmapBuffer
& rSrcBuffer
, BitmapBuffer
& rDstBuffer
,
64 FncGetPixel pFncGetPixel
, FncSetPixel pFncSetPixel
,
65 Scanline
* pSrcScanMap
, Scanline
* pDstScanMap
, long* pMapX
, long* pMapY
)
67 const long nWidth
= rDstBuffer
.mnWidth
, nHeight
= rDstBuffer
.mnHeight
, nHeight1
= nHeight
- 1;
68 const ColorMask
& rSrcMask
= rSrcBuffer
.maColorMask
;
69 const ColorMask
& rDstMask
= rDstBuffer
.maColorMask
;
70 BitmapPalette
aColMap( rSrcBuffer
.maPalette
.GetEntryCount() );
71 BitmapColor
* pColMapBuf
= aColMap
.ImplGetColorBuffer();
72 BitmapColor
aIndex( 0 );
74 for( sal_uInt16 i
= 0, nSrcCount
= aColMap
.GetEntryCount(), nDstCount
= rDstBuffer
.maPalette
.GetEntryCount(); i
< nSrcCount
; i
++ )
76 if( ( i
< nDstCount
) && ( rSrcBuffer
.maPalette
[ i
] == rDstBuffer
.maPalette
[ i
] ) )
77 aIndex
.SetIndex( sal::static_int_cast
<sal_uInt8
>(i
) );
79 aIndex
.SetIndex( sal::static_int_cast
<sal_uInt8
>(rDstBuffer
.maPalette
.GetBestIndex( rSrcBuffer
.maPalette
[ i
] )) );
81 pColMapBuf
[ i
] = aIndex
;
84 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
86 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
88 for( long nX
= 0L; nX
< nWidth
; nX
++ )
89 pFncSetPixel( pDstScan
, nX
, pColMapBuf
[ pFncGetPixel( pSrcScan
, pMapX
[ nX
], rSrcMask
).GetIndex() ], rDstMask
);
95 static void ImplPALToTC( const BitmapBuffer
& rSrcBuffer
, BitmapBuffer
& rDstBuffer
,
96 FncGetPixel pFncGetPixel
, FncSetPixel pFncSetPixel
,
97 Scanline
* pSrcScanMap
, Scanline
* pDstScanMap
, long* pMapX
, long* pMapY
)
99 const long nWidth
= rDstBuffer
.mnWidth
, nHeight
= rDstBuffer
.mnHeight
, nHeight1
= nHeight
- 1;
100 const ColorMask
& rSrcMask
= rSrcBuffer
.maColorMask
;
101 const ColorMask
& rDstMask
= rDstBuffer
.maColorMask
;
102 const BitmapColor
* pColBuf
= rSrcBuffer
.maPalette
.ImplGetColorBuffer();
104 if( BMP_SCANLINE_FORMAT( rSrcBuffer
.mnFormat
) == BMP_FORMAT_1BIT_MSB_PAL
)
106 const BitmapColor
aCol0( pColBuf
[ 0 ] );
107 const BitmapColor
aCol1( pColBuf
[ 1 ] );
110 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
112 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
114 for( long nX
= 0L; nX
< nWidth
; )
117 pFncSetPixel( pDstScan
, nX
++,
118 pSrcScan
[ nMapX
>> 3 ] & ( 1 << ( 7 - ( nMapX
& 7 ) ) ) ? aCol1
: aCol0
,
125 else if( BMP_SCANLINE_FORMAT( rSrcBuffer
.mnFormat
) == BMP_FORMAT_4BIT_MSN_PAL
)
129 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
131 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
133 for( long nX
= 0L; nX
< nWidth
; )
136 pFncSetPixel( pDstScan
, nX
++,
137 pColBuf
[ ( pSrcScan
[ nMapX
>> 1 ] >> ( nMapX
& 1 ? 0 : 4 ) ) & 0x0f ],
144 else if( BMP_SCANLINE_FORMAT( rSrcBuffer
.mnFormat
) == BMP_FORMAT_8BIT_PAL
)
146 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
148 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
150 for( long nX
= 0L; nX
< nWidth
; nX
++ )
151 pFncSetPixel( pDstScan
, nX
, pColBuf
[ pSrcScan
[ pMapX
[ nX
] ] ], rDstMask
);
158 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
160 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
162 for( long nX
= 0L; nX
< nWidth
; nX
++ )
163 pFncSetPixel( pDstScan
, nX
, pColBuf
[ pFncGetPixel( pSrcScan
, pMapX
[ nX
], rSrcMask
).GetIndex() ], rDstMask
);
170 static void ImplTCToTC( const BitmapBuffer
& rSrcBuffer
, BitmapBuffer
& rDstBuffer
,
171 FncGetPixel pFncGetPixel
, FncSetPixel pFncSetPixel
,
172 Scanline
* pSrcScanMap
, Scanline
* pDstScanMap
, long* pMapX
, long* pMapY
)
174 const long nWidth
= rDstBuffer
.mnWidth
, nHeight
= rDstBuffer
.mnHeight
, nHeight1
= nHeight
- 1;
175 const ColorMask
& rSrcMask
= rSrcBuffer
.maColorMask
;
176 const ColorMask
& rDstMask
= rDstBuffer
.maColorMask
;
178 if( BMP_SCANLINE_FORMAT( rSrcBuffer
.mnFormat
) == BMP_FORMAT_24BIT_TC_BGR
)
181 sal_uInt8
* pPixel
= NULL
;
183 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
185 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
187 for( long nX
= 0L; nX
< nWidth
; nX
++ )
189 aCol
.SetBlue( *( pPixel
= ( pSrcScan
+ pMapX
[ nX
] * 3 ) )++ );
190 aCol
.SetGreen( *pPixel
++ );
191 aCol
.SetRed( *pPixel
);
192 pFncSetPixel( pDstScan
, nX
, aCol
, rDstMask
);
200 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
202 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
204 for( long nX
= 0L; nX
< nWidth
; nX
++ )
205 pFncSetPixel( pDstScan
, nX
, pFncGetPixel( pSrcScan
, pMapX
[ nX
], rSrcMask
), rDstMask
);
212 static void ImplTCToPAL( const BitmapBuffer
& rSrcBuffer
, BitmapBuffer
& rDstBuffer
,
213 FncGetPixel pFncGetPixel
, FncSetPixel pFncSetPixel
,
214 Scanline
* pSrcScanMap
, Scanline
* pDstScanMap
, long* pMapX
, long* pMapY
)
216 const long nWidth
= rDstBuffer
.mnWidth
, nHeight
= rDstBuffer
.mnHeight
, nHeight1
= nHeight
- 1;
217 const ColorMask
& rSrcMask
= rSrcBuffer
.maColorMask
;
218 const ColorMask
& rDstMask
= rDstBuffer
.maColorMask
;
219 BitmapPalette
aColMap( rSrcBuffer
.maPalette
.GetEntryCount() );
220 sal_uInt8
* pColToPalMap
= new sal_uInt8
[ TC_TO_PAL_COLORS
];
221 BitmapColor
aIndex( 0 );
223 for( long nR
= 0; nR
< 16; nR
++ )
225 for( long nG
= 0; nG
< 16; nG
++ )
227 for( long nB
= 0; nB
< 16; nB
++ )
229 BitmapColor
aCol( sal::static_int_cast
<sal_uInt8
>(nR
<< 4),
230 sal::static_int_cast
<sal_uInt8
>(nG
<< 4),
231 sal::static_int_cast
<sal_uInt8
>(nB
<< 4) );
232 pColToPalMap
[ ImplIndexFromColor( aCol
) ] = (sal_uInt8
) rDstBuffer
.maPalette
.GetBestIndex( aCol
);
237 for( long nActY
= 0, nMapY
; nActY
< nHeight
; nActY
++ )
239 Scanline
pSrcScan( pSrcScanMap
[ nMapY
= pMapY
[ nActY
] ] ), pDstScan( pDstScanMap
[ nActY
] );
241 for( long nX
= 0L; nX
< nWidth
; nX
++ )
243 aIndex
.SetIndex( pColToPalMap
[ ImplIndexFromColor( pFncGetPixel( pSrcScan
, pMapX
[ nX
], rSrcMask
) ) ] );
244 pFncSetPixel( pDstScan
, nX
, aIndex
, rDstMask
);
250 delete[] pColToPalMap
;
253 BitmapBuffer
* StretchAndConvert( const BitmapBuffer
& rSrcBuffer
, const SalTwoRect
& rTwoRect
,
254 sal_uLong nDstBitmapFormat
, BitmapPalette
* pDstPal
, ColorMask
* pDstMask
)
256 FncGetPixel pFncGetPixel
;
257 FncSetPixel pFncSetPixel
;
258 BitmapBuffer
* pDstBuffer
= new BitmapBuffer
;
261 // set function for getting pixels
262 switch( BMP_SCANLINE_FORMAT( rSrcBuffer
.mnFormat
) )
264 IMPL_CASE_GET_FORMAT( _1BIT_MSB_PAL
);
265 IMPL_CASE_GET_FORMAT( _1BIT_LSB_PAL
);
266 IMPL_CASE_GET_FORMAT( _4BIT_MSN_PAL
);
267 IMPL_CASE_GET_FORMAT( _4BIT_LSN_PAL
);
268 IMPL_CASE_GET_FORMAT( _8BIT_PAL
);
269 IMPL_CASE_GET_FORMAT( _8BIT_TC_MASK
);
270 IMPL_CASE_GET_FORMAT( _16BIT_TC_MSB_MASK
);
271 IMPL_CASE_GET_FORMAT( _16BIT_TC_LSB_MASK
);
272 IMPL_CASE_GET_FORMAT( _24BIT_TC_BGR
);
273 IMPL_CASE_GET_FORMAT( _24BIT_TC_RGB
);
274 IMPL_CASE_GET_FORMAT( _24BIT_TC_MASK
);
275 IMPL_CASE_GET_FORMAT( _32BIT_TC_ABGR
);
276 IMPL_CASE_GET_FORMAT( _32BIT_TC_ARGB
);
277 IMPL_CASE_GET_FORMAT( _32BIT_TC_BGRA
);
278 IMPL_CASE_GET_FORMAT( _32BIT_TC_RGBA
);
279 IMPL_CASE_GET_FORMAT( _32BIT_TC_MASK
);
282 // should never come here
283 // initialize pFncGetPixel to something valid that is
284 // least likely to crash
285 pFncGetPixel
= BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL
;
286 OSL_FAIL( "unknown read format" );
290 // set function for setting pixels
291 const sal_uLong nDstScanlineFormat
= BMP_SCANLINE_FORMAT( nDstBitmapFormat
);
292 switch( nDstScanlineFormat
)
294 IMPL_CASE_SET_FORMAT( _1BIT_MSB_PAL
, 1 );
295 IMPL_CASE_SET_FORMAT( _1BIT_LSB_PAL
, 1 );
296 IMPL_CASE_SET_FORMAT( _4BIT_MSN_PAL
, 1 );
297 IMPL_CASE_SET_FORMAT( _4BIT_LSN_PAL
, 4 );
298 IMPL_CASE_SET_FORMAT( _8BIT_PAL
, 8 );
299 IMPL_CASE_SET_FORMAT( _8BIT_TC_MASK
, 8 );
300 IMPL_CASE_SET_FORMAT( _16BIT_TC_MSB_MASK
, 16 );
301 IMPL_CASE_SET_FORMAT( _16BIT_TC_LSB_MASK
, 16 );
302 IMPL_CASE_SET_FORMAT( _24BIT_TC_BGR
, 24 );
303 IMPL_CASE_SET_FORMAT( _24BIT_TC_RGB
, 24 );
304 IMPL_CASE_SET_FORMAT( _24BIT_TC_MASK
, 24 );
305 IMPL_CASE_SET_FORMAT( _32BIT_TC_ABGR
, 32 );
306 IMPL_CASE_SET_FORMAT( _32BIT_TC_ARGB
, 32 );
307 IMPL_CASE_SET_FORMAT( _32BIT_TC_BGRA
, 32 );
308 IMPL_CASE_SET_FORMAT( _32BIT_TC_RGBA
, 32 );
309 IMPL_CASE_SET_FORMAT( _32BIT_TC_MASK
, 32 );
312 // should never come here
313 // initialize pFncSetPixel to something valid that is
314 // least likely to crash
315 pFncSetPixel
= BitmapReadAccess::SetPixelFor_1BIT_MSB_PAL
;
316 pDstBuffer
->mnBitCount
= 1;
317 OSL_FAIL( "unknown write format" );
321 // fill destination buffer
322 pDstBuffer
->mnFormat
= nDstBitmapFormat
;
323 pDstBuffer
->mnWidth
= rTwoRect
.mnDestWidth
;
324 pDstBuffer
->mnHeight
= rTwoRect
.mnDestHeight
;
325 pDstBuffer
->mnScanlineSize
= AlignedWidth4Bytes( pDstBuffer
->mnBitCount
* pDstBuffer
->mnWidth
);
328 pDstBuffer
->mpBits
= new sal_uInt8
[ pDstBuffer
->mnScanlineSize
* pDstBuffer
->mnHeight
];
330 catch( const std::bad_alloc
& )
332 // memory exception, clean up
333 pDstBuffer
->mpBits
= NULL
;
338 // do we need a destination palette or color mask?
339 if( ( nDstScanlineFormat
== BMP_FORMAT_1BIT_MSB_PAL
) ||
340 ( nDstScanlineFormat
== BMP_FORMAT_1BIT_LSB_PAL
) ||
341 ( nDstScanlineFormat
== BMP_FORMAT_4BIT_MSN_PAL
) ||
342 ( nDstScanlineFormat
== BMP_FORMAT_4BIT_LSN_PAL
) ||
343 ( nDstScanlineFormat
== BMP_FORMAT_8BIT_PAL
) )
345 DBG_ASSERT( pDstPal
, "destination buffer requires palette" );
346 pDstBuffer
->maPalette
= *pDstPal
;
348 else if( ( nDstScanlineFormat
== BMP_FORMAT_8BIT_TC_MASK
) ||
349 ( nDstScanlineFormat
== BMP_FORMAT_16BIT_TC_MSB_MASK
) ||
350 ( nDstScanlineFormat
== BMP_FORMAT_16BIT_TC_LSB_MASK
) ||
351 ( nDstScanlineFormat
== BMP_FORMAT_24BIT_TC_MASK
) ||
352 ( nDstScanlineFormat
== BMP_FORMAT_32BIT_TC_MASK
) )
354 DBG_ASSERT( pDstMask
, "destination buffer requires color mask" );
355 pDstBuffer
->maColorMask
= *pDstMask
;
358 // short circuit the most important conversions
359 bool bFastConvert
= ImplFastBitmapConversion( *pDstBuffer
, rSrcBuffer
, rTwoRect
);
363 const long nSrcX
= rTwoRect
.mnSrcX
, nSrcY
= rTwoRect
.mnSrcY
;
364 const long nSrcDX
= rTwoRect
.mnSrcWidth
, nSrcDY
= rTwoRect
.mnSrcHeight
;
365 const long nDstDX
= rTwoRect
.mnDestWidth
, nDstDY
= rTwoRect
.mnDestHeight
;
366 Scanline
* pSrcScan
= NULL
;
367 Scanline
* pDstScan
= NULL
;
374 pSrcScan
= new Scanline
[ rSrcBuffer
.mnHeight
];
375 pDstScan
= new Scanline
[ nDstDY
];
376 pMapX
= new long[ nDstDX
];
377 pMapY
= new long[ nDstDY
];
379 catch( const std::bad_alloc
& )
381 // memory exception, clean up
382 // remark: the buffer ptr causing the exception
383 // is still NULL here
392 // horizontal mapping table
393 if( nDstDX
!= nSrcDX
)
395 const double fFactorX
= ( nDstDX
> 1 ) ? (double) ( nSrcDX
- 1 ) / ( nDstDX
- 1 ) : 0.0;
397 for( i
= 0L; i
< nDstDX
; i
++ )
398 pMapX
[ i
] = nSrcX
+ FRound( i
* fFactorX
);
402 for( i
= 0L, nTmp
= nSrcX
; i
< nDstDX
; i
++ )
406 // vertical mapping table
407 if( nDstDY
!= nSrcDY
)
409 const double fFactorY
= ( nDstDY
> 1 ) ? (double) ( nSrcDY
- 1 ) / ( nDstDY
- 1 ) : 0.0;
411 for( i
= 0L; i
< nDstDY
; i
++ )
412 pMapY
[ i
] = nSrcY
+ FRound( i
* fFactorY
);
416 for( i
= 0L, nTmp
= nSrcY
; i
< nDstDY
; i
++ )
420 // source scanline buffer
422 if( BMP_SCANLINE_ADJUSTMENT( rSrcBuffer
.mnFormat
) == BMP_FORMAT_TOP_DOWN
)
423 pTmpScan
= rSrcBuffer
.mpBits
, nOffset
= rSrcBuffer
.mnScanlineSize
;
426 pTmpScan
= rSrcBuffer
.mpBits
+ ( rSrcBuffer
.mnHeight
- 1 ) * rSrcBuffer
.mnScanlineSize
;
427 nOffset
= -rSrcBuffer
.mnScanlineSize
;
430 for( i
= 0L; i
< rSrcBuffer
.mnHeight
; i
++, pTmpScan
+= nOffset
)
431 pSrcScan
[ i
] = pTmpScan
;
433 // destination scanline buffer
434 if( BMP_SCANLINE_ADJUSTMENT( pDstBuffer
->mnFormat
) == BMP_FORMAT_TOP_DOWN
)
435 pTmpScan
= pDstBuffer
->mpBits
, nOffset
= pDstBuffer
->mnScanlineSize
;
438 pTmpScan
= pDstBuffer
->mpBits
+ ( nDstDY
- 1 ) * pDstBuffer
->mnScanlineSize
;
439 nOffset
= -pDstBuffer
->mnScanlineSize
;
442 for( i
= 0L; i
< nDstDY
; i
++, pTmpScan
+= nOffset
)
443 pDstScan
[ i
] = pTmpScan
;
445 // do buffer scaling and conversion
446 if( rSrcBuffer
.mnBitCount
<= 8 && pDstBuffer
->mnBitCount
<= 8 )
448 ImplPALToPAL( rSrcBuffer
, *pDstBuffer
, pFncGetPixel
, pFncSetPixel
,
449 pSrcScan
, pDstScan
, pMapX
, pMapY
);
451 else if( rSrcBuffer
.mnBitCount
<= 8 && pDstBuffer
->mnBitCount
> 8 )
453 ImplPALToTC( rSrcBuffer
, *pDstBuffer
, pFncGetPixel
, pFncSetPixel
,
454 pSrcScan
, pDstScan
, pMapX
, pMapY
);
456 else if( rSrcBuffer
.mnBitCount
> 8 && pDstBuffer
->mnBitCount
> 8 )
458 ImplTCToTC( rSrcBuffer
, *pDstBuffer
, pFncGetPixel
, pFncSetPixel
,
459 pSrcScan
, pDstScan
, pMapX
, pMapY
);
463 ImplTCToPAL( rSrcBuffer
, *pDstBuffer
, pFncGetPixel
, pFncSetPixel
,
464 pSrcScan
, pDstScan
, pMapX
, pMapY
);
476 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */