损坏/不支持的.bmp文件

发布于 2025-02-05 18:59:14 字数 2817 浏览 2 评论 0原文

我需要为学校项目实现盒子模糊算法,然后在线发现了该算法。我的问题是,完成算法后,我无法打开“ 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: %d\n", width);
    printf("height: %d\n", 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);
    }

该算法成功读取输入图像的宽度和高度,它创建输出文件,但无法打开文件。

I need to implement a Box Blur algorithm for a school project and I found this algorithm online. My issue is that i can't open the "result.bmp" file after the algorithm is done.
It says the file is either corrupted or damaged and I can't seem to find the cause of this issue.

Code:

    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: %d\n", width);
    printf("height: %d\n", 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);
    }

The algorithm successfully reads the width and the height of the input image, it creates the output file but the file cannot be opened.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

奈何桥上唱咆哮 2025-02-12 18:59:14

您的代码非常接近,但存在一些问题:

  • 您可以根据4字节对齐来计算每行的字节数
    使用((width * 3 + 3) / 4) * 4 < / code>。
  • width高度的附接反之亦然。
  • 您不应施放malloc()的返回值。
  • BMP文件标头由BMP文件标头(14个字节固定)
    dib头(可变大小)。由于存储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: %d\n", width);
    printf("height: %d\n", height);
//  printf("bytesperline: %d\n", 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;
}

Your code is very close but has some issues:

  • You can calculate the byte count per line considering the 4-byte alignment
    with ((width * 3 + 3) / 4) * 4.
  • The addesses of width and height are vice versa.
  • You should not cast the return value of malloc().
  • Bmp file header is composed of BMP File header (14 bytes fixed)
    and DIB header (variable size). As the size of DIB header is stored
    in the starting 4 bytes of the DIB header, lets read the 18 bytes (= 14 + 4)
    at first, determine the remaining header size, then read the rest of DIB header.

Then the modified version will look like:

#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: %d\n", width);
    printf("height: %d\n", height);
//  printf("bytesperline: %d\n", 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文