我正在尝试解压缩以特殊方式压缩的rle文件。
我正在回到一个与原始图像不同的图像,我无法理解为什么。
第一个Ill解释它被压缩的方式:
原始图像是灰色图像,其中只有2种像素:白色或黑色。
在压缩中,他们使用一个字节来表示每个像素序列。
每个字节中的MSB位表示白色(= 1)或黑色(= 0)。另外7位表示序列,因此最大值可以为127。
例如,127个像素的白色将是:11111111B => 255 DEC。
127DEC也代表127个黑色像素(MSB为0)。
原始图像是120x240 BMP,我使用一个已知的功能(它给我)来保存BMP文件,因此如果遵循所有规则,将数组保存到bmp文件没有问题。
同样在压缩文件中,前2个BYTE将表示数组大小。 arraysize = rle [0] * 256 + rle [1]。
我只在这里放置解压缩和压缩的部分(我建两个)
void RleDeCompress(unsigned char rleimage[2 + 240 * 120], unsigned char decompressedimage[][NUMBER_OF_COLUMNS])
{
// 1st MSB bit from the 8 bit of each cell in the array represent color - Black or White
//2nd~7th BIT represent the number of times the color repeats itself
// first 2 cells in the array are represent the size of the array
int arraysize = rleimage[0] * 256 + rleimage[1];
int row = 0;
int col = 0;
unsigned char colormask = 128; //binary 10000000=128dec
unsigned char multiplymask = 127; // binary 01111111 = 127dec
unsigned int total = 0;
for (int i = 2; i < arraysize+2; i++)
{
unsigned char blackorwhitebinary = (rleimage[i] & colormask) >> 7 ; // mask only the msb and then shift it to be the lsb
unsigned char color = 255 * blackorwhitebinary; // decide if this is black or white
unsigned char multiply = rleimage[i] & multiplymask; // number of times the color repeats itself
for (int j = 0; j < multiply; j++)
{
decompressedimage[row][col] = color;
col++;
if (col == NUMBER_OF_COLUMNS)
{
row++;
col = 0;
}
if (row > NUMBER_OF_ROWS) cout << "error too many rows " << endl;
}
total += multiply;
// check total of cells real in the binary file
}
cout << "total is:" << total << endl;
}
void RleCompress(unsigned char image[][NUMBER_OF_COLUMNS], unsigned char RleImage[2 + 240 * 120])
{
unsigned char n = 0;
unsigned int N = 2;
unsigned int arrsize=0;
unsigned char temparray[ 240 * 120];
for (int row = 0; row < NUMBER_OF_ROWS; row++)
{
for (int column = 0; column < NUMBER_OF_COLUMNS; column++)
{
temparray[arrsize] = image[row][column] / 255;
arrsize++;
}
}
for (int i = 0; i < arrsize; i++)
{
n++;
if (n == 127)
{
RleImage[N+2] = temparray[i] * 128 + n;
n = 0;
N++;
}
else
{
if (i == arrsize)
{
RleImage[N + 2] = temparray[i] * 128 + n;
}
else
{
if (temparray[i] != temparray[i + 1])
{
RleImage[N + 2] = temparray[i] * 128 + n;
n = 0;
N++;
}
}
}
}
RleImage[0] = N / 256;
RleImage[1] = N % 256;
}
void SaveRleFile(unsigned char RleImage[2 + 240 * 120])
{
ofstream myfile;
myfile.open("P01C.bin", ios::out | ios::binary);
if (myfile.is_open())
{
int index = 0;
while (index < 2 + 120 * 240)
{
myfile << RleImage[index];
index++;
}
cout << "index is :" << index << endl;
}
myfile.close();
}
void LoadRleBinFile(char binfilename[], unsigned char * image)
{
//for (int j = 0; j < 2 + 120 * 240; j++) image[j] = 255; //clears the array from garbage and sets all of it to white.
ifstream myfile;
char c;
int i = 0;
myfile.open(binfilename, ios::in | ios::binary); // open file in binary mode input only
if (myfile.is_open())
{
while (!myfile.eof())
{
myfile.get(c);
image[i] = (unsigned char) c;
i++;
}
}
else
cout << "error while opening file " << endl;
myfile.close();
}
void main()
{
unsigned char GrayImage[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
unsigned char Rlearray[2 + 240 * 120]; //rlearray size is unknown when first initialzing . worst case is 2 + 240*120
LoadGrayImageFromTrueColorBmpFile(GrayImage, "P01A.bmp");
StoreGrayImageAsGrayBmpFile(GrayImage, "P01B.bmp");
//--------------------------------------------------------------------------------------------------------------------------
ConvertGrayImageToBlackWhite(GrayImage);
StoreGrayImageAsGrayBmpFile(GrayImage, "P01B2.bmp");
RleCompress(GrayImage, Rlearray);
SaveRleFile(Rlearray);
LoadRleBinFile("P01C.rle", Rlearray);
RleDeCompress(Rlearray, GrayImage);
StoreGrayImageAsGrayBmpFile(GrayImage, "P01C.BMP");
//WaitForUserPressKey();
}
我找到了一种检查问题的方法,它在代码中。 图片中的像素数量(120 * 240 = 28800)应该是,或者至少对我而言似乎是最合乎逻辑的,等于所有序列的总和,因为如果没有,那么我们没有压缩整个图像。 在我的代码中,所有序列的总和约为17000。 != 28800。 我不明白,如果我没有正确压缩或没有解压缩,但从查看二进制文件(使用二进制查看器程序),似乎二进制文件是正常的。