mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #20875 from Harvey-Huang:master
* bmp specified BI_BITFIELDS should take care RGBA bit mask * change the name * support xrgb bmp file * support xrgb bmp file(add test case) * update testing code
This commit is contained in:
parent
d376fe9e17
commit
9267536fee
@ -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()
|
||||
|
@ -73,6 +73,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void initMask();
|
||||
void maskBGRA(uchar* des, uchar* src, int num);
|
||||
|
||||
enum Origin
|
||||
{
|
||||
ORIGIN_TL = 0,
|
||||
@ -85,6 +88,8 @@ protected:
|
||||
int m_bpp;
|
||||
int m_offset;
|
||||
BmpCompression m_rle_code;
|
||||
uint m_rgba_mask[4];
|
||||
int m_rgba_bit_offset[4];
|
||||
};
|
||||
|
||||
|
||||
|
@ -295,6 +295,32 @@ TEST(Imgcodecs_Bmp, read_rle8)
|
||||
EXPECT_PRED_FORMAT2(cvtest::MatComparator(0, 0), rle, ord);
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Bmp, rgba_bit_mask)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_rgba_mask.bmp";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_8UC4, img.type());
|
||||
|
||||
const uchar* data = img.ptr();
|
||||
ASSERT_EQ(data[3], 255);
|
||||
}
|
||||
|
||||
TEST(Imgcodecs_Bmp, read_32bit_xrgb)
|
||||
{
|
||||
const string root = cvtest::TS::ptr()->get_data_path();
|
||||
const string filenameInput = root + "readwrite/test_32bit_xrgb.bmp";
|
||||
|
||||
const Mat img = cv::imread(filenameInput, IMREAD_UNCHANGED);
|
||||
ASSERT_FALSE(img.empty());
|
||||
ASSERT_EQ(CV_8UC4, img.type());
|
||||
|
||||
const uchar* data = img.ptr();
|
||||
ASSERT_EQ(data[3], 255);
|
||||
}
|
||||
|
||||
#ifdef HAVE_IMGCODEC_HDR
|
||||
TEST(Imgcodecs_Hdr, regression)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user