@ -58,6 +58,7 @@ BmpDecoder::BmpDecoder()
m_origin = ORIGIN_TL ;
m_bpp = 0 ;
m_rle_code = BMP_RGB ;
initMask ( ) ;
}
@ -97,6 +98,7 @@ bool BmpDecoder::readHeader()
int size = m_strm . getDWord ( ) ;
CV_Assert ( size > 0 ) ; // overflow, 2Gb limit
initMask ( ) ;
if ( size > = 36 )
{
m_width = m_strm . getDWord ( ) ;
@ -107,7 +109,30 @@ bool BmpDecoder::readHeader()
m_rle_code = ( BmpCompression ) m_rle_code_ ;
m_strm . skip ( 12 ) ;
int clrused = m_strm . getDWord ( ) ;
m_strm . skip ( size - 36 ) ;
if ( m_bpp = = 32 & & m_rle_code = = BMP_BITFIELDS & & size > = 56 )
{
m_strm . skip ( 4 ) ; //important colors
//0 is Red channel bit mask, 1 is Green channel bit mask, 2 is Blue channel bit mask, 3 is Alpha channel bit mask
for ( int index_rgba = 0 ; index_rgba < 4 ; + + index_rgba )
{
uint mask = m_strm . getDWord ( ) ;
m_rgba_mask [ index_rgba ] = mask ;
if ( mask ! = 0 )
{
int bit_count = 0 ;
while ( ! ( mask & 1 ) )
{
mask > > = 1 ;
+ + bit_count ;
}
m_rgba_bit_offset [ index_rgba ] = bit_count ;
}
}
m_strm . skip ( size - 56 ) ;
}
else
m_strm . skip ( size - 36 ) ;
if ( m_width > 0 & & m_height ! = 0 & &
( ( ( m_bpp = = 1 | | m_bpp = = 4 | | m_bpp = = 8 | |
@ -486,8 +511,14 @@ decode_rle8_bad: ;
icvCvt_BGRA2Gray_8u_C4C1R ( src , 0 , data , 0 , Size ( m_width , 1 ) ) ;
else if ( img . channels ( ) = = 3 )
icvCvt_BGRA2BGR_8u_C4C3R ( src , 0 , data , 0 , Size ( m_width , 1 ) ) ;
else if ( img . channels ( ) = = 4 )
memcpy ( data , src , m_width * 4 ) ;
else if ( img . channels ( ) = = 4 )
{
bool has_bit_mask = ( m_rgba_bit_offset [ 0 ] > = 0 ) & & ( m_rgba_bit_offset [ 1 ] > = 0 ) & & ( m_rgba_bit_offset [ 2 ] > = 0 ) ;
if ( has_bit_mask )
maskBGRA ( data , src , m_width ) ;
else
memcpy ( data , src , m_width * 4 ) ;
}
}
result = true ;
break ;
@ -503,7 +534,26 @@ decode_rle8_bad: ;
return result ;
}
void BmpDecoder : : initMask ( )
{
memset ( m_rgba_mask , 0 , sizeof ( m_rgba_mask ) ) ;
memset ( m_rgba_bit_offset , - 1 , sizeof ( m_rgba_bit_offset ) ) ;
}
void BmpDecoder : : maskBGRA ( uchar * des , uchar * src , int num )
{
for ( int i = 0 ; i < num ; i + + , des + = 4 , src + = 4 )
{
uint data = * ( ( uint * ) src ) ;
des [ 0 ] = ( uchar ) ( ( m_rgba_mask [ 2 ] & data ) > > m_rgba_bit_offset [ 2 ] ) ;
des [ 1 ] = ( uchar ) ( ( m_rgba_mask [ 1 ] & data ) > > m_rgba_bit_offset [ 1 ] ) ;
des [ 2 ] = ( uchar ) ( ( m_rgba_mask [ 0 ] & data ) > > m_rgba_bit_offset [ 0 ] ) ;
if ( m_rgba_bit_offset [ 3 ] > = 0 )
des [ 3 ] = ( uchar ) ( ( m_rgba_mask [ 3 ] & data ) > > m_rgba_bit_offset [ 3 ] ) ;
else
des [ 3 ] = 255 ;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
BmpEncoder : : BmpEncoder ( )