其中关键函数是将输入的 pSrcBits数组利用游程编码进行压缩,输出结果数组pRLEBits。需要注意的是判断当前指针是否处在行末的位置。
函数体中有state_start;state_compress;state_no_compress;end_of_line四个状态。
void CDVDBitmapControl::CompressInRLE8(BYTE* pSrcBits, CByteArray& pRLEBits, int& RLE_size)
{
int line;
int src_index = 0, dst_index = 0, counter, i;
// in RLE8 every pixel is one byte
for ( line = 0; line < m_dib.dsBmih.biHeight; line++)
{
state_start: // just at the start of a block
if ( EndOfLine(src_index)) // this is the last pixel of the line
{
pRLEBits[dst_index++] = 1; // block of length 1
pRLEBits[dst_index++] = pSrcBits[src_index];
src_index++;
goto end_of_line;
}
// now the block length is at least 2, look ahead to decide next state
// next two same pixels are the same, enter compress mode
if (pSrcBits[src_index] == pSrcBits[src_index+1])
goto state_compress;
if ( EndOfLine(src_index+1)) // the last 2 pixel of the line
{ // these 2 pixel are not the same
pRLEBits[dst_index++] = 1; // block of length 1
pRLEBits[dst_index++] = pSrcBits[src_index++];
pRLEBits[dst_index++] = 1; // block of length 1
pRLEBits[dst_index++] = pSrcBits[src_index++];
goto end_of_line;
}
// now the block length is at least 3
// in next 3 pixels, the last 2 consecutive pixel are the same
if (pSrcBits[src_index+1] == pSrcBits[src_index+2])
{
pRLEBits[dst_index++] = 1; // block of length 1
pRLEBits[dst_index++] = pSrcBits[src_index++];
goto state_compress;
}
else // in these 3 pixel, no 2 consecutive pixel are the same
goto state_no_compress; // un-compressed block need at least 3 pixel
state_compress: // compress mode
// src_index is the first pixel of a compressd block
// counter is the number of additional pixels following currrent pixel
// (src_index+counter) point to the last pixel of current block
for ( counter = 1; counter <= 254; counter++)
{
// must check this condition first, or a BUG occur!
if ( pSrcBits[src_index+counter] != pSrcBits[src_index] )
break;
if ( EndOfLine(src_index+counter) ) // reach end of line
{
pRLEBits[dst_index++] = counter+1; // block length is (counter+1)
pRLEBits[dst_index++] = pSrcBits[src_index];
src_index += counter +1;
goto end_of_line;
}
}
// now pSrcBits[src_index+counter] falls out of block
pRLEBits[dst_index++] = counter; // block length is (counter)
pRLEBits[dst_index++] = pSrcBits[src_index];
src_index += counter;
goto state_start;
state_no_compress:
// src_index is the first pixel of a un-compressd block
// un-compressed block need at least 3 pixel
// counter is the number of additional pixels following currrent pixel
for (counter = 2; counter <= 254; counter++)
{
if ( EndOfLine(src_index+counter) ) // reach end of line
{
pRLEBits[dst_index++] = 0; // escape character for un-compress block
pRLEBits[dst_index++] = counter + 1; // block length is (counter+1)
for (i = counter + 1; i > 0; i--)
pRLEBits[dst_index++] = pSrcBits[src_index++];
if ( 0 != ((counter+1) % 2) ) // block length is odd
pRLEBits[dst_index++]; // padd with a zero byte
goto end_of_line;
}
if ( EndOfLine(src_index+counter+1) ||
pSrcBits[src_index+counter] != pSrcBits[src_index+counter+1] )
continue; // still no 2 consecutive pixel are the same,
// therefore continue to extend the un-compress block
// we found two pixels are the same
if ( EndOfLine(src_index+counter+2) ||
pSrcBits[src_index+counter+1] != pSrcBits[src_index+counter+2] )
continue; // the third pixel is not the same, no need to exit un-compressed mode
else
{ // // now pSrcBits[src_index+counter] and following 2 pixel are the same
// now we need to exit the un-compressed mode
if ( counter > 2)
counter--; // we can shrink the block one pixel (go backward)
pRLEBits[dst_index++] = 0; // escape character for un-compress block
pRLEBits[dst_index++] = counter+1; // block length is (counter+1)
for (i = counter+1; i > 0; i--)
pRLEBits[dst_index++] = pSrcBits[src_index++];
if ( 0 != ((counter+1) % 2) ) // block length is odd
pRLEBits[dst_index++]; // padd with a zero byte
goto state_compress;
}
} // end of for (counter = 2; counter <= 254; counter++)
// now we have a full block of 255 pixels
pRLEBits[dst_index++] = 0; // escape character for un-compress block
pRLEBits[dst_index++] = counter; // block length is (counter)
for (i = counter; i > 0; i--)
pRLEBits[dst_index++] = pSrcBits[src_index++];
if ( 0 != ((counter) % 2) ) // block length is odd
pRLEBits[dst_index++]; // padd with a zero byte
goto state_start;
end_of_line:
if ( 0 != (src_index % 4 )) // each scan line is dword align
{
int pad = 4 - (src_index%4);
src_index += pad;
}
// src_index already point to the start of next line
pRLEBits[dst_index++] = 0; // mark end-of-line
pRLEBits[dst_index++] = 0;
}
pRLEBits[dst_index++] = 0; // mark end-of-bitmap
pRLEBits[dst_index++] = 1;
RLE_size = dst_index; // image size
}
RLE-BMP 利用一维行程编码压缩8位BMP
最新推荐文章于 2022-03-27 21:52:58 发布
本文详细介绍了如何使用游程编码(RLE)来压缩8位BMP图像。主要关注CDVDBitmapControl类中的CompressInRLE8函数,该函数遍历图像的每一行,根据像素的相似性切换压缩和非压缩状态,以减少数据量。在处理行末和连续相同像素时,函数会生成相应的RLE编码块。
2万+





