【问题标题】:Distorted Bitmap File扭曲的位图文件
【发布时间】:2020-02-02 15:47:25
【问题描述】:

我正在编写一个复制 .bmp 文件并将其写入另一个文件以对其进行操作的程序(特别是镜像和反转颜色)。写入的 .bmp 文件失真。有没有人看到任何问题?我已经为此工作了好几个小时,此时我的大脑已经炸了。任何帮助将不胜感激。

#include <cstdint>
#include <cstdio>

#pragma pack(push, 2)
struct BitmapFileHeader {

    uint16_t type;
    uint32_t size;
    uint16_t reserved_1;
    uint16_t reserved_2;
    uint32_t offset;

};
struct BitmapInfoHeader {

    uint32_t size;
    uint32_t width;
    uint32_t height;
    uint16_t planes;
    uint16_t bitcount;
    uint32_t compression;
    uint32_t imagesize;
    uint32_t x_pixels_per_meter;
    uint32_t y_pixels_per_meter;
    uint32_t color_used;
    uint32_t color_important;
};
#pragma pack(pop)

struct Pixel {
    uint8_t blue;
    uint8_t green;
    uint8_t red;
};


int main(int argc, char* argv[])
{
    if(argc != 3) {
        printf("Usage : %s input_file output_file\n", argv[0]);
        return 1;
    }

    FILE *fin;
    FILE *fout;
    BitmapFileHeader bfh;
    BitmapInfoHeader bih;

    fin = fopen(argv[1], "rb");

    if (nullptr == fin) {
        perror(argv[1]);
        return -1;
    }

    if (sizeof(BitmapFileHeader) != fread(&bfh, 1, sizeof(bfh), fin)) {
        printf("Unable to read bitmap file header. \n");
        return -2;
    }

    if (sizeof(BitmapInfoHeader) != fread(&bih, 1, sizeof(bih), fin)) {
        printf("Unable to read bitmap info header. \n");
        return -3;
    }

    printf("Size of File Header = %lu\n", sizeof(BitmapFileHeader));

    int8_t first = (bfh.type >> 8) & 0xff;
    int8_t second = bfh.type & 0xff;

    if ( (first != 'M') && (second != 'B') ){
        printf("Input file is not a Bitmap file. \n");
        return -4;
    }

    printf("File type = %c%c\n", first, second);
    printf("File size = %u\n", bfh.size);
    printf("File offset = %u\n", bfh.offset);
    printf("File width = %u\n", bih.width);
    printf("Info size = %u\n", bih.size);

    uint32_t padding_bytes = 0;
    uint32_t row_bytes_final = bih.width * sizeof(Pixel);
    uint32_t row_bytes_initial = row_bytes_final;

    do{
        uint32_t rem = row_bytes_final % 4;

        if (rem != 0) {
            row_bytes_final += 1;
        }

        padding_bytes = row_bytes_final - row_bytes_initial;

    } while( (row_bytes_final % 4) != 0);


    fseek(fin, bfh.offset, SEEK_SET);

    Pixel *p = new Pixel[bih.height * bih.width];

    for (uint32_t i = 0; i < bih.height; i++) {
        for (uint32_t j = 0; j < bih.width; j++) {
            uint32_t index = i * bih.width + j;
            fread(&p[index], 1, sizeof(Pixel), fin);
        }

       if (padding_bytes > 0) {
            fseek(fin, -1, SEEK_CUR);
            fputc('\0', fin);

       }
      //  fseek(fin, padding_bytes, SEEK_CUR);
    }

    fclose(fin);


    fout = fopen(argv[2], "wb");

    if(nullptr == fout) {
        perror(argv[2]);
        return -5;
    }

    if(sizeof(BitmapFileHeader) != fwrite(&bfh, 1, sizeof(bfh), fout)) {
        printf("Unable to write bitmap file header.\n");
        return -6;
    }

    if(sizeof(BitmapInfoHeader) != fwrite(&bih, 1, sizeof(bih), fout)) {
        printf("Unable to write bitmap info header.\n");
        return -7;
    }

    fseek(fout, bfh.offset, SEEK_SET);

    for (uint32_t i = 0; i < bih.height; i++) {
        for (uint32_t j = 0; j < bih.width; j++) {
            uint32_t index = i * bih.width + j;
            fwrite(&p[index], 1, sizeof(Pixel), fout);
        }

       if (padding_bytes > 0) {
            fseek(fout, -1, SEEK_CUR);
            fputc('\0', fout);
        }

      //  fseek(fout, padding_bytes, SEEK_CUR);
    }



    fclose(fout);
    delete[] p;


    return 0;


}

【问题讨论】:

  • 看来你想逐个像素地读取 - 你有两个按行和列的循环,那么为什么在 fread(&amp;p[index], sizeof(Pixel), bih.width, fin); 你传递 bih.width ?而应该是1 那里。在写作中你也有同样的问题。
  • @rafix07 我根据其他人的建议更改了它。尽管如此,它不会改变文件的结果。我已经更新了代码。
  • 恐怕您必须使用一些工具(我不知道是否存在此类工具)或手动分析错误的文件。我宁愿做后者,因为它比搜索工具花费的时间更少。然后,如果您可以查明错误的内容,请查看您的来源以找到错误。
  • 最多可以有三个填充字节。我看到你只写了一个。
  • 扫描线大小计算为(((bits) + 31) / 32 * 4)bits 是扫描线像素中的位数。减去width*pixelsize 得到填充字节。

标签: c++ c binary


【解决方案1】:
        for (uint32_t i = 0; i < bih.height; i++){
            for (uint32_t j = 0; j < bih.width; j++){
                uint32_t index = i * bih.width + j;
                fread(&p[index], 1, sizeof(Pixel), fin);
            }

            //if (padding_bytes > 0) {
            //fseek(fin, -1, SEEK_CUR);
            //for(int kk=0;kk<padding_bytes;kk++)
            //fputc('\0', fin);
            //}
              fseek(fin, padding_bytes, SEEK_CUR);      //ok
        }

//.....

        for (uint32_t i = 0; i < bih.height; i++){
            for (uint32_t j = 0; j < bih.width; j++){
                uint32_t index = i * bih.width + j;
                fwrite(&p[index], 1, sizeof(Pixel), fout);
            }

            //if (padding_bytes > 0){
            //  fseek(fout, -1, SEEK_CUR);
            //  fputc('\0', fout);
            //}
            //fseek(fout, padding_bytes, SEEK_CUR);
              for (int t = 0; t < padding_bytes; t++) fputc('\0', fout);   //ok
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-31
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多