C RLE算法在bmp文件中的应用
我目前在尝试将游程算法应用于.bmp图片时遇到了一些问题。当我进行编码时,一切正常,但在解码时有一个问题,我无法解决,即我无法读取重复像素的数量,因此我的输出是一个空白图像。使用调试器时,无法从二进制文件(位图文件上应用RLE的结果)正确读取重复像素数。这是我的密码C RLE算法在bmp文件中的应用,c,bitmap,C,Bitmap,我目前在尝试将游程算法应用于.bmp图片时遇到了一些问题。当我进行编码时,一切正常,但在解码时有一个问题,我无法解决,即我无法读取重复像素的数量,因此我的输出是一个空白图像。使用调试器时,无法从二进制文件(位图文件上应用RLE的结果)正确读取重复像素数。这是我的密码 #include<stdlib.h> #include <stdint.h> //structure defiens bitmap header struct BITMAPFILEHEADER{ ui
#include<stdlib.h>
#include <stdint.h>
//structure defiens bitmap header
struct BITMAPFILEHEADER{
uint8_t type[2];//type of file (bit map)
uint32_t size;//size of file
uint16_t reserved1;//
uint16_t reserved2;//
uint32_t offsetbits;//off set bits
} __attribute__ ((packed));
struct BITMAPINFOHEADER{
uint32_t size;//bitmap size
// uint16_t w2;
uint32_t width;//width of bitmap
//uint16_t h2;
uint32_t height;//hight of bitmap
uint16_t planes;
uint16_t bitcount;
uint32_t compression;// compression ratio (zero for no compression)
uint32_t sizeimage;//size of image
long xpelspermeter;
long ypelspermeter;
uint32_t colorsused;
uint32_t colorsimportant;
} __attribute__ ((packed));
//const char* INPUT_FILE = "/home/bogdan/bee.bmp";
const char* INPUT_FILE = "/home/bogdan/Linux.bmp";
const char* ENCODED_FILE = "/home/bogdan/encoded.bin";
const char* DECODED_FILE = "/home/bogdan/decoded.bmp";
typedef struct SINGLE_PIXEL{
uint8_t green;//Green level 0-255
uint8_t red; //Red level 0-255
} PIXEL;
int comparePixels(PIXEL, PIXEL);
void encode();
void decode(char*);
int main()
{
encode();
decode(ENCODED_FILE);
return 0;
}
void encode() {
uint32_t i=0;//to count pixels read
uint32_t pixno=0;//number of pixels to read
struct BITMAPFILEHEADER source_head;//to store file header
struct BITMAPINFOHEADER source_info;//to store bitmap info header
PIXEL pixel;// the current pixel
FILE *in;// bitmap imput pointer file
FILE *out;//output file pointer
if(!(in=fopen(INPUT_FILE,"rb")))//open in binary read mode
{
printf("\ncan not open file");//error at opening file
exit(-1);
}
out=fopen(ENCODED_FILE,"wb");//opne in binary write mode
//read the headers to source file
fread(&source_head,sizeof(struct BITMAPFILEHEADER),1,in);
fread(&source_info,sizeof(struct BITMAPINFOHEADER),1,in);
//write the headers to the output file
fwrite(&source_head,sizeof(struct BITMAPFILEHEADER),1,out);
fwrite(&source_info,sizeof(struct BITMAPINFOHEADER),1,out);
//cumpute the number of pixels to read
pixno=source_info.width*source_info.height;
// init list of pixels
PIXEL pixArr[pixno];
printf("total pixels: %d", pixno);
//printf("w:%f h:%u pn:%lu", (source_head.size/1024.0/1024), source_info.height, pixno);
uint32_t sum = 0;
//read, modify and write pixels
for(i=0;i<pixno;++i)
{
//read pixel form source file
fread(&pixel,sizeof(PIXEL),1,in);
pixArr[i] = pixel;
}
for (i = 0; i < pixno; i++) {
// printf ("i = %d\tred = %d green = %d blue = %d\n",i, pixArr[i].red, pixArr[i].green, pixArr[i].blue);
int runlength = 1;
while ((i + 1) < pixno) {
if (comparePixels(pixArr[i], pixArr[i+1]) == 0){
// printf ("i = %d\t red = %d green = %d blue = %d\n",i, pixArr[i].red, pixArr[i].green, pixArr[i].blue);
runlength++;
i++;
} else {
break;
}
}
//fprintf(out, "%d", runlength);
fwrite(&runlength, sizeof(runlength), 1, out);
fwrite(&pixel,sizeof(PIXEL),1,out);
sum += runlength;
runlength = 0;
}
//write the modification to the output file
//close all fiels
fclose(in);
fclose(out);
printf("sum = %d",sum);
}
void decode(char * filePath) {
uint32_t i=0;//to count pixels read
uint32_t j=0;
uint32_t totalPixels=0;//number of pixels to read
uint32_t pixelRepetition = 1;
struct BITMAPFILEHEADER source_head;//to store file header
struct BITMAPINFOHEADER source_info;//to store bitmap info header
PIXEL pixel;// the current pixel
FILE *in;// bitmap encoded pointer file
FILE *out;//decoded bitmap file pointer
if (!(in = fopen(filePath, "rb"))) {
printf("\ncan not open file");
exit(-1);
}
out = fopen(DECODED_FILE, "wb");
//read the headers to source file
fread(&source_head,sizeof(struct BITMAPFILEHEADER),1,in);
fread(&source_info,sizeof(struct BITMAPINFOHEADER),1,in);
//write the headers to the output file
fwrite(&source_head,sizeof(struct BITMAPFILEHEADER),1,out);
fwrite(&source_info,sizeof(struct BITMAPINFOHEADER),1,out);
totalPixels=source_info.width*source_info.height;
while(i < totalPixels) {
fread(&pixelRepetition, sizeof(pixelRepetition), 1, out);
fread(&pixel,sizeof(PIXEL),1,in);
for (j = 0; j < pixelRepetition; j++) {
fwrite(&pixel,sizeof(PIXEL),1,out);
}
i += pixelRepetition;
}
fclose(in);
fclose(out);
}
int comparePixels(PIXEL px1, PIXEL px2) {
if (px1.red == px2.red && px1.green == px2.green && px1.blue == px2.blue) {
return 0;
} else {
return -1;
}
}
#包括
#包括
//结构定义位图头
结构BITMAPFILEHEADER{
uint8_t type[2];//文件类型(位图)
uint32\u t size;//文件大小
uint16保留1//
uint16_t储备2//
uint32\u t偏移位;//偏移位
}_uuu属性_uuu((压缩));
结构BitMapInfo标头{
uint32\u t size;//位图大小
//uint16_t w2;
uint32\u t width;//位图的宽度
//uint16_t h2;
uint32\u t height;//位图的高度
uint16_t平面;
uint16_t比特计数;
uint32\u t compression;//压缩比(零表示无压缩)
uint32\u t sizeimage;//图像的大小
长xpelspermeter;
长渗透计;
使用的uint32_t颜色;
uint32_t颜色很重要;
}_uuu属性_uuu((压缩));
//const char*INPUT_FILE=“/home/bogdan/bee.bmp”;
const char*INPUT_FILE=“/home/bogdan/Linux.bmp”;
const char*ENCODED_FILE=“/home/bogdan/ENCODED.bin”;
const char*DECODED_FILE=“/home/bogdan/DECODED.bmp”;
typedef结构单像素{
uint8_t绿色;//绿色级别0-255
uint8_t red;//红色级别0-255
}像素;
整数比较像素(像素,像素);
void encode();
无效解码(字符*);
int main()
{
编码();
解码(编码的_文件);
返回0;
}
void encode(){
uint32\u t i=0;//计算读取的像素数
uint32_t pixno=0;//要读取的像素数
struct BITMAPFILEHEADER source_head;//用于存储文件头
struct bitmapinfo头source_info;//用于存储位图信息头
像素;//当前像素
FILE*in;//位图输入指针文件
FILE*out;//输出文件指针
if(!(in=fopen(输入_文件,“rb”))//以二进制读取模式打开
{
printf(“\n无法打开文件”);//打开文件时出错
出口(-1);
}
out=fopen(编码的_文件,“wb”);//二进制写入模式下的opne
//将标题读取到源文件
fread(&source_head,sizeof(struct-BITMAPFILEHEADER),1,in);
fread(&source_info,sizeof(struct-bitmapinfo-header),1,in);
//将标题写入输出文件
fwrite(&source_head,sizeof(struct-BITMAPFILEHEADER),1,out);
fwrite(&source_-info,sizeof(struct-bitmapinfo-header),1,out);
//计算要读取的像素数
pixno=源信息宽度*源信息高度;
//初始化像素列表
像素pixArr[pixno];
printf(“总像素:%d”,像素编号);
//printf(“w:%f h:%u pn:%lu”,(source\u head.size/1024.0/1024),source\u info.height,pixno);
uint32_t sum=0;
//读取、修改和写入像素
对于(i=0;i而言,您只会重复写入读取的最后一个像素:
您需要写出当前像素:
fwrite(pixArr[i], sizeof(PIXEL),1,out);
您好。让人们发现代码中的错误并不是特别有效。您应该使用调试器(或添加打印语句)来隔离问题,方法是跟踪程序的进度,并将其与预期发生的情况进行比较。一旦这两种情况出现分歧,您就发现了问题。(然后,如果有必要,您应该构造一个。)另外,“有问题”不是一个有用的描述。您应该准确地描述您看到的输出,以及它与您期望的结果的比较。相信我,我在这里发布代码的原因是我没有使用调试器发现错误。您没有注意我的描述,我说:“我的第一个想法是,我没有正确地从二进制文件中读取int“。如果你知道一些可以帮助我的东西,如果你想,请说出来,否则让我们避免这些讨论。恐怕这不是它的工作原理;它不是一个众包调试器。我鼓励你改进你的问题,以便它能更快地得到更好的帮助,而不是被关闭。另外,请注意“我的第一个想法…”不是对程序行为/症状的描述。请尝试一个小的手工构建的示例,您知道读取代码的预期操作。在调试器中观察它,看看它在哪里执行了您不期望的操作。(或者“玩电脑”,逐行处理代码,并在纸上逐个变量。)找出原因,修复它,继续下一个错误。这是C,三重检查是否使用指针或数组引用以确保它们在范围内。输出的十六进制转储应该立即显示错误。@Matt:同意。OP认为重复值读取错误,但代码表明这不应该是问题所在。首先,谢谢你们的回答!!我发现我的编码程序确实是错误的,我已经纠正了。现在我有另一个问题,我如何从二进制文件中读取int?因为我没有使用类似于fscanf(在,“%d”中,&pixelRepeation)的东西来实现它
提前谢谢。@Costy:..您在这里使用了fread(&pixelRepeation..
),这是“从二进制文件读取int”的一种相对较好的方法。(还有其他一些好方法;fscanf
不是。)如果有疑问,请发布一个新问题。如果您想要可移植代码和可移植文件格式,请注意结尾。
fwrite(pixArr[i], sizeof(PIXEL),1,out);