我需要为一个学校项目实现一个Box Blur算法,我在网上找到了这个算法。我的问题是我不能打开;result.bmp";文件。它说文件要么被损坏,要么被破坏,我似乎找不到这个问题的原因。
代码:
FILE* fIn = fopen("test.bmp", "r"); // Input File name
FILE* fOut = fopen("result.bmp", "w+"); // Output File name
int i, j, y, x;
unsigned char byte[54];
for (i = 0; i < 54; i++) // read the 54 byte header from fIn
{
byte[i] = fgetc(fIn);
}
fwrite(byte, sizeof(unsigned char), 54, fOut); // write the header back
// extract image height, width and bitDepth from imageHeader
int height = *(int*)&byte[18];
int width = *(int*)&byte[22];
int bitDepth = *(int*)&byte[28];
printf("width: %dn", width);
printf("height: %dn", height);
int size = height * width;
unsigned char** buffer = (unsigned char**)malloc(size * sizeof(unsigned char*));
for (int i = 0; i < size; i++)
buffer[i] = (unsigned char*)malloc(3 * sizeof(unsigned char));
unsigned char** out = (unsigned char**)malloc(size * sizeof(unsigned char*));
for (int i = 0; i < size; i++)
out[i] = (unsigned char*)malloc(3 * sizeof(unsigned char));
for (i = 0; i < size; i++)
{
buffer[i][2] = getc(fIn); // blue
buffer[i][1] = getc(fIn); // green
buffer[i][0] = getc(fIn); // red
}
float v = 1.0 / 9.0; // initialize the blurring kernel
float kernel[3][3] = { {v,v,v},
{v,v,v},
{v,v,v} };
for (x = 1; x < height - 1; x++)
{
for (y = 1; y < width - 1; y++)
{
float sum0 = 0.0;
float sum1 = 0.0;
float sum2 = 0.0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
// matrix multiplication with kernel with every color plane
sum0 = sum0 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][0];
sum1 = sum1 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][1];
sum2 = sum2 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][2];
}
}
out[(x)*width + (y)][0] = (unsigned char)sum0;
out[(x)*width + (y)][1] = (unsigned char)sum1;
out[(x)*width + (y)][2] = (unsigned char)sum2;
}
}
for (i = 0; i < size; i++) //write image data back to the file
{
fputc(out[i][2], fOut);
fputc(out[i][1], fOut);
fputc(out[i][0], fOut);
}
该算法成功读取了输入图像的宽度和高度,创建了输出文件,但无法打开该文件。
您的代码非常接近,但存在一些问题:
- 您可以计算每行的字节数,考虑4字节对齐用CCD_ 1
- CCD_ 2和CCD_
- 您不应该强制转换
malloc()
的返回值 - Bmp文件头由
BMP File header
组成(固定14字节)以及CCD_ 6(可变大小)。由于DIB标头的大小已存储在DIB标头的起始4个字节中,让我们读取18个字节(=14+4)首先,确定剩余的报头大小,然后读取DIB报头的其余部分
然后修改后的版本将看起来像:
#include <stdio.h>
#include <stdlib.h>
#define INFILE "test.bmp" // input file name
#define OUTFILE "result.bmp" // output file name
#define HEADER1 (14 + 4) // Bitmap File Header + word for header size
#define HEADER2 (124 - 4) // DIB (Information) File Header - word for header size
int main()
{
FILE *fIn = fopen(INFILE, "r");
if (fIn == NULL) {
perror(INFILE);
exit(1);
}
FILE *fOut = fopen(OUTFILE, "w+");
if (fOut == NULL) {
perror(OUTFILE);
exit(1);
}
int i, j, y, x;
int dibsize; // size of DIB Header
unsigned char header1[HEADER1];
unsigned char header2[HEADER2];
fread(header1, sizeof(unsigned char), HEADER1, fIn); // read file header + DIB header size
dibsize = *(int *)&header1[14]; // size of DIB header
fwrite(header1, sizeof(unsigned char), HEADER1, fOut); // write the header back
fread(header2, sizeof(unsigned char), dibsize - 4, fIn); // read remaining DIB header except for the word for the header size
fwrite(header2, sizeof(unsigned char), dibsize - 4, fOut); // write the header back
// extract image height, width and bitDepth from imageHeader
int width = *(int *)&header2[0];
int height = *(int *)&header2[4];
int bitDepth = *(int *)&header2[20];
int bytesperline = ((width * 3 + 3) / 4) * 4; // bytes per line including 4-byte alignment
printf("width: %dn", width);
printf("height: %dn", height);
// printf("bytesperline: %dn", bytesperline);
int size = height * width;
unsigned char **buffer = malloc(size * sizeof(unsigned char *));
for (int i = 0; i < size; i++)
buffer[i] = malloc(3 * sizeof(unsigned char));
unsigned char **out = malloc(size * sizeof(unsigned char *));
for (int i = 0; i < size; i++)
out[i] = malloc(3 * sizeof(unsigned char));
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
buffer[i * width + j][2] = getc(fIn); // blue
buffer[i * width + j][1] = getc(fIn); // green
buffer[i * width + j][0] = getc(fIn); // red
}
for (j = width * 3; j < bytesperline; j++) // zero padding for 4-byte alignment
{
getc(fIn);
}
}
float v = 1.0 / 9.0; // initialize the blurring kernel
float kernel[3][3] = { {v,v,v},
{v,v,v},
{v,v,v} };
for (x = 1; x < height - 1; x++)
{
for (y = 1; y < width - 1; y++)
{
float sum0 = 0.0;
float sum1 = 0.0;
float sum2 = 0.0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
// matrix multiplication with kernel with every color plane
sum0 = sum0 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][0];
sum1 = sum1 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][1];
sum2 = sum2 + (float)kernel[i + 1][j + 1] * buffer[(x + i) * width + (y + j)][2];
}
}
out[x * width + y][0] = (unsigned char)sum0;
out[x * width + y][1] = (unsigned char)sum1;
out[x * width + y][2] = (unsigned char)sum2;
}
}
for (i = 0; i < height; i++) // write image data back to the file
{
for (j = 0; j < width; j++)
{
fputc(out[i * width + j][2], fOut); // blue
fputc(out[i * width + j][1], fOut); // green
fputc(out[i * width + j][0], fOut); // red
}
for (j = width * 3; j < bytesperline; j++) // zero padding for 4-byte alignment
{
fputc(0, fOut);
}
}
fclose(fIn);
fclose(fOut);
return 0;
}