【问题标题】:Inverting colors of pixels in a BMP file in C在C中反转BMP文件中像素的颜色
【发布时间】:2016-10-03 01:42:20
【问题描述】:

我遇到的问题是试图在简单的黑白图像上反转颜色。

当我运行我的 C 程序并对每个 BGR 值执行按位非运算时,我最终得到的图像是这样的。它似乎重复了整个图像的黑色、蓝色、绿色和红色像素。我读过在每个像素的末尾有一个额外的字节用于填充,我试图跳过每次迭代。

这是左下角的特写。

这是我读取 BMP 文件并反转图像颜色的代码。

void invertImage(char fileName[]) {

    struct BMP bmp;
    struct DIB dib;
    struct PIXEL pixel;

    FILE *fp = fopen(fileName, "rb+");

    //FileType
    fread(bmp.filetype, 1, 2, fp);
    printf("Value is %c\n", bmp.filetype[1]);

    //Check if file format is BM
    if (bmp.filetype[0] != 'B' && bmp.filetype[1] != 'M') {
        printf("File format not supported");
        exit(-1);
    }
    //Size of the file in bytes
    fread(&bmp.filesize, 4, 1, fp);
    printf("Value is %d\n", bmp.filesize);

    //Go to dataoffset
    fseek(fp, 4, SEEK_CUR);

    fread(&bmp.dataoffset, 4, 1, fp);
    printf("Offset is %d\n", bmp.dataoffset);


    fread(&dib.fileheader, 4, 1, fp);
    printf("File header is %d bytes\n", dib.fileheader);

    if (dib.fileheader != 40) {
        printf("File format not supported");
        exit(-1);
    }

    fread(&dib.width, 4, 1, fp);
    printf("Width is %d\n", dib.width);

    fread(&dib.height, 4, 1, fp);
    printf("Height is %d\n", dib.height);

    fread(&dib.planes, 2, 1, fp);
    printf("Color planes is %d\n", dib.planes);

    //Number of bits per pixel
    fread(&dib.bitsperpixel, 2, 1, fp);
    printf("Pixels per bit is %d\n", dib.bitsperpixel);


    fread(&dib.compression, 4, 1, fp);
    printf("Compression scheme used is %d\n", dib.compression);

    fread(&dib.bitmapsize, 4, 1, fp);
    printf("Image size is %d\n", dib.bitmapsize);

    fread(&dib.horizontalres, 4, 1, fp);
    printf("Horizontal resolution is %d\n", dib.horizontalres);

    fread(&dib.verticalres, 4, 1, fp);
    printf("Vertical resolution is %d\n", dib.verticalres);

    fread(&dib.numcolors, 4, 1, fp);
    printf("Number of colors used %d\n", dib.numcolors);

    fread(&dib.importantcolors, 4, 1, fp);
    printf("Important colors used %d\n", dib.importantcolors);

    //fseek(fp,3,SEEK_CUR);

    int x = 0;
    while (x < dib.width) {
        int y = 0;
        while (y < dib.height) {

            fread(&pixel.b, 1, 1, fp);
            unsigned int blue = pixel.b;
            blue = ~blue;
            pixel.b = (char) blue;
            printf("Pixel 1 is %d\n", pixel.b);

            fread(&pixel.g, 1, 1, fp);
            unsigned int green = pixel.g;
            green = ~green;
            pixel.g = (char) green;
            printf("Pixel 2 is %d\n", pixel.g);

            fread(&pixel.r, 1, 1, fp);
            unsigned int red = pixel.r;
            red = ~red;
            pixel.r = (char) red;
            printf("Pixel 3 is %d\n", pixel.r);

            fseek(fp, -3, SEEK_CUR);
            fwrite(&pixel.b, 1, 1, fp);
            fwrite(&pixel.g, 1, 1, fp);
            fwrite(&pixel.r, 1, 1, fp);
            fseek(fp, 1, SEEK_CUR);

            y++;
        }
        //  fseek(fp,1,SEEK_CUR);

        x++;
    }

    fclose(fp);
}

int main(int argc, char *argv[]) {

    printf("Program name %s\n", argv[0]);
   if( strcmp(argv[1],"-invert") == 0) {

    printf("Invert\n");
    printf("File name is %s\n", argv[2]);

    invertImage(argv[2]);
}
    return 0;
}

还有我在程序中使用的结构。

struct BMP {
    char filetype[2]; // must be BM, must check if BM
    unsigned int filesize;
    short reserved1;
    short reserved2;
    unsigned int dataoffset;

};

struct DIB {
    unsigned int fileheader;
    unsigned int headersize;
    int width;
    int height;
    short planes;
    short bitsperpixel; /* we only support the value 24 here */
    unsigned int compression; /* we do not support compression */
    unsigned int bitmapsize;
    int horizontalres;
    int verticalres;
    unsigned int numcolors;
    unsigned int importantcolors;
};

struct PIXEL {
    unsigned char b;
    unsigned char g;
    unsigned char r;

};

这是输出减去双 while 循环的输出,即“像素 n 为 0”或“像素 n 为 255”

【问题讨论】:

  • printf 的输出是什么?还有你不想使用图片库的充分理由吗?
  • 那些argv[2]s 应该是argv[1]s 吗?
  • 我会补充的
  • 我认为这些是 32 位 BMP 文件。运行此程序时出现段错误。我在Linux上。也许我在复制代码时在某处出错了......
  • @Mike Smith,现在我看到这些是 24 位的——我的第一个测试位图中仍然有色彩空间信息。现在代码运行了,我得到了你报告的行为......

标签: c image memory memory-leaks pixel


【解决方案1】:

您每 4 个字节跳过一次。

文件包含:

BGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGR...
^ start here

    fread(&pixel.b, 1, 1, fp);
    fread(&pixel.g, 1, 1, fp);
    fread(&pixel.r, 1, 1, fp);

BGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGR...
   ^ now here

    fseek(fp, -3, SEEK_CUR);

BGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGR...
^ now here

    fwrite(&pixel.b, 1, 1, fp);
    fwrite(&pixel.g, 1, 1, fp);
    fwrite(&pixel.r, 1, 1, fp);

bgrBGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGR...
   ^ now here

    fseek(fp, 1, SEEK_CUR);

bgrBGRBGRBGRBGRBGRBGRBGRBGRBGRBGRBGR...
    ^ now here - skipping the blue part of the second pixel?

要解决此问题,请不要在每个像素后跳过一个字节。

【讨论】:

  • 是的,按照@immibis 的建议,我在三个fwrite()s 后面注释掉了fseek() 行,一切似乎都正常。好收获!
  • @DavidBowling 请注意,要符合标准,您应该在编写后致电fflush(fp)fseek(fp, 0, SEEK_CUR)。如果没有它,它可能会在您的操作系统上运行,但如果您想编写可移植代码,则需要注意这一点。
【解决方案2】:

您的主要阅读循环似乎没有考虑https://en.wikipedia.org/wiki/BMP_file_format 中记录的行填充,特别是在“像素存储”部分。

由于 BMP 的宽度不是 4 的倍数,因此您在末尾每行读取 3 个额外字节,从而改变下一行的颜色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多