2016-10-03 67 views
0

我遇到的问题是试图反转简单黑白图像上的颜色。在C中反转BMP文件中的像素颜色

enter image description here

当我运行我的C程序,并在每个BGR值I代替,象这样的图像结束的执行按位NOT。它似乎重复了整个图像的黑色,蓝色,绿色和红色像素。我读过每个像素末尾都有一个额外的填充字节,我试图跳过每次迭代。

enter image description here

这是一个近距离的左下角。

enter image description here

这里是我的代码读取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”

enter image description here

+0

'printf'的输出是什么?还有一个很好的理由,你不想使用图像库? –

+0

这些'argv [2]是否应该是'argv [1]'? –

+0

我会补充一点, –

回答

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? 

为了解决这个问题,不要每一个像素后跳过一个字节。

+0

是的,遵循建议在@immibis之后,我在三个'fwrite()'之后注释了'fseek()'行,并且所有东西都可以工作。接得好! –

+0

@DavidBowling请注意,为了符合标准,您应在写入后调用'fflush(fp)'或'fseek(fp,0,SEEK_CUR)'。它可能在你的操作系统上没有它,但是如果你想编写可移植的代码,这是需要注意的。 – immibis

0

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

由于您的BMP不是宽度为4的倍数,所以在结束移动下一行的颜色时,每行读取3个额外的字节。