c-读取P6二进制ppm文件



所以我已经读了很多与此相关的问题,但没有一个能解决我的问题。我正在尝试读取P6 ppm文件(它是一个二进制文件)。我当前的代码是

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct pixel {
    char red;
    char green;
    char blue;
};
int main(int argc, char **argv)
{
    char type[3];
    int numRow, numCol, maxNum;
    FILE *oldFile, *newFile;
    struct pixel currentPixel;
    char buffer[5];
    oldFile = fopen(argv[1], "rb");
    if(oldFile == NULL) {
        fprintf(stderr, "Could not open file %s for reading in binary", argv[1]);
        return 0;
    }
    fscanf(oldFile, "%2s", type);
    type[2] = '';
    if(strcmp(type, "P6") != 0) {  //Make sure we have a P6 file
        printf("This file is not of type P6");
        return 0;
    }
    newFile = fopen(argv[2], "wb");
    fprintf(newFile, "%sn", type);
    /*Read number of columns
    rows and
    The max number that can represent a colour*/
    fscanf(oldFile, "%d", &numCol);
    fscanf(oldFile, "%d", &numRow);
    fscanf(oldFile, "%d", &maxNum);
    /*Print the information to newFile*/
    fprintf(newFile, "%d %dn", numCol, numRow);
    fprintf(newFile, "%dn", maxNum);
    fseek(oldFile, 1, SEEK_CUR);
    fread(&currentPixel, sizeof(struct pixel), 1, oldFile);
    printf("%c %c %c", currentPixel.red, currentPixel.green, currentPixel.blue);
    fclose(newFile);
    fclose(oldFile);
    return 0;
}

因此,开头部分有效,我的newFile包含第P6行、第33行和第255行。然后,我尝试用fread行读取实际像素。这就是它失败的地方,我不知道为什么。它目前在一颗钻石内部打印出两个问号。我目前只想读取组成一个像素的前三个数字(一个红色分量,一个绿色分量和一个蓝色分量)。

我还有一个相同图片的P3文件,P3文件看起来像:

 P3
3 3
255
  0 255 255   0   0   0   0   0 255
255   0 255 100 100 100 255   0   0
255 255   0 255 255 255   0 255   0

所以二进制文件应该这样设置,但只是二进制格式。当我输入时

od-c二进制图像.ppm

我得到

0000000   P   6  n   3       3  n   2   5   5  n   377 377    
0000020       377 377   377   X   X   X 377     377 377  
0000040 377 377 377   377  
0000046

我不知道为什么我的fread功能不起作用。不确定是否相关,但我正在使用在Linux Ubuntu上编译

gcc-墙旋转。c-o旋转

您将RGB值打印为字符,而不是数字。在结构中保持它们为unsigned char(因为它们的值在[0-255]之间),但在打印时使用%d。您应该按如下方式使用printf

printf("%d %d %d", currentPixel.red, currentPixel.green, currentPixel.blue);

此外,我建议不要使用结构来读取RGB值,因为编译器可能会添加一个填充字节来将结构与机器字对齐(例如32位)。在32位系统中,您将读取4个字节。您可以检查打印sizeof(struct pixel)。要了解更多关于结构对齐的信息,您可以查看维基百科文章"数据结构对齐"。

使用char数组代替结构:

unsigned char currentPixel[3];
...
fread(currentPixel, 3, 1, oldFile);
printf("%d %d %d", currentPixel[0], currentPixel[1], currentPixel[2]);

此外,如果需要读取整个图像,请创建一个大小为number of pixels x 3unsigned char数组。3是RGB元组的字节数。如果PPM格式在每行的末尾都包含一些填充,那么您也需要考虑这一点。

最新更新