c - 在C中显示ppm图像的rgb值和冲突类型错误

标签 c image printing rgb

我对 C 语言相当陌生,我的任务是创建一个读取图像并显示该图像的程序。我创建了(我认为是)一个函数来读取文件格式/注释等,并尝试创建一个函数来显示每个像素的 RGB 值。

我无法测试它,因为我的程序中有一个错误 - “getPPM 类型冲突”。谁能解释一下为什么我会收到此错误?任何可能的修复都会很棒。

如果有人可以建议一种能够存储评论(也许在数组中?)并稍后打印它们的方法,那也会非常有帮助!谢谢。

也请随意检查整个程序并向我提供反馈,我不完全确定一旦修复上述错误它是否会真正执行任何操作。 非常感谢!

#include <stdio.h>
#include <stdlib.h>


#define MAX_HEIGHT 600
#define MAX_WIDTH 400

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

    // get image file
    FILE *file;
    file = fopen("aab(1).ppm", "r");

    //if there is no file then return an error
    if(file == NULL){
        fprintf(stderr, "File is not valid");
        return 0;
    }
    else {
        struct PPM *newPPM = getPPM(file);
        return 0;
    }
}

struct PPM {
    char format[2]; //PPM format code
    int height, width; //image pixel height and width
    int max; //max rgb colour value

} PPM;

struct PPM_Pixel {
    //Create variables to hold the rgb pixel values
    int red, green, blue;
} PPM_Pixel;

struct PPM *getPPM(FILE * fd){

    struct PPM *image;
    char buffer[16];
    char c;
    char commentArray[256];
    fd = fopen(fd, "r");

    struct PPM *newPPM = malloc(sizeof(PPM));

    //checks if the file being read is valid/the correct file
    if(fd == NULL){
        exit(1);
    }

    //read the image of the format
    if(!fgets(buffer, sizeOf(buffer), fd)){
        exit(1);
    }

    //checks the format of the ppm file is correct
    if(buffer[0] != 'P' || buffer[1] != '3'){
        fprintf(stderr, "Invalid image format! \n");
        exit(1);
    }else {
        printf("%s", newPPM->format);
    }


    //allocate memory for the image
    image = malloc(sizeof(PPM));
    if(!image){
        fprintf(stderr, "Cannot allocate memory");
        exit(1);
    }

    //checks whether the next character is a comment and store it in a linked list
    c = getc(fd);
    while(c == '#'){
        while(getc(fd) != '\n'){
        c = getc(fd);
        }
    }

    if(fscaf(fd, "%d %d", &image->height, &image->width)!= 2){
         fprintf(stderr, "Size of image is invalid");
         exit(1);
    }

    fclose(fd);
    return newPPM;
 };

showPPM(struct PPM * image){

    //two-dimensional array to show the rows and columns of pixels.

    int rgb_array[MAX_HEIGHT][MAX_WIDTH];
    int i;
    int j;

    for(i = 0; i<MAX_HEIGHT; i++){
        for(j = 0; j<MAX_WIDTH; j++){
            printf("%d", rgb_array[i][j]);
        }
    }



};

最佳答案

下面的代码

  1. 包含大量关于错误和/或如何纠正的评论
  2. 执行适当的错误检查
  3. 更正了一些函数签名
  4. 为每个函数正确声明原型(prototype)
  5. 纠正了一些“按键”错误
  6. 更正“语法”错误
  7. 将结构定义移至首次引用这些定义之前

警告:此代码无法解决访问 PPM 图像文件的问题。

警告:此代码仍然不会将 malloc 的内存区域传递给 free(),因此仍然需要添加这些语句。

#include <stdio.h>
#include <stdlib.h>


#define MAX_HEIGHT 600
#define MAX_WIDTH 400

// 1) giving the struct tag name the same as an instance name is a bad idea
// 2) good programming practice is to define a struct separately
//    from the instance of that struct

struct PPM
{
    char format[2]; //PPM format code
    int height, width; //image pixel height and width
    int max; //max rgb colour value

};

struct PPM myPPM;

struct PPM_Pixel
{
    //Create variables to hold the rgb pixel values
    //int red, green, blue;
    // follow the axiom:
    //    only one statement per line and (at most) one variable declaration per statement
    int red;
    int green;
    int blue;
};

struct PPM_Pixel myPPM_Pixel;

// prototypes
struct PPM *getPPM(FILE * fp);
void showPPM(struct PPM * image);

// this line will cause the compiler to raise two warnings 
//    about unused variable 'argc' and 'argv'
//int main(int argc, char ** argv)
int main( void )
{
    // get image file
    //FILE *file;
    //file = fopen("aab(1).ppm", "r");

    //if there is no file then return an error
    //if(file == NULL)
    FILE *fp == NULL;
    if( NUL == (fp = fopen("aab(1).ppm", "r") ) )
    {
        //fprintf(stderr, "File is not valid");
        //  should include system error message
        perror( "fopen for read of aab(1).ppm failed" );
        //return 0;
        // need to indicate an error occurred
        exit( EXIT_FAILURE );
    }

    // implied else, fopen was successful

    // following statement will raise a compiler warning
    //    about: 'set but not used variable'
    struct PPM *newPPM = getPPM(fp);

    fclose( fp ); // moved to here from 'getPPM()'
} // end function: main




struct PPM *getPPM(FILE * fp)
{
    struct PPM *image;
    char buffer[16];

    //char c;
    // the returned value from 'getc()' is an integer, not a character
    int  c;
    char commentArray[256];

    // following line is nonsence and the passed in parameter is already open
    //fd = fopen(fd, "r");

    // when allocating memory, always check the returned value
    //    to assure the operation was successful
    struct PPM *newPPM = NULL;
    if( NULL == (newPPM = malloc( sizeof struct PPM ) ) )
    {
        perror( "malloc for struct PPM failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful

    // already done in main()
    //checks if the file being read is valid/the correct file
    //if(fd == NULL){
    //    exit(1);
    //}

    //read the image of the format
    if(!fgets(buffer, sizeOf(buffer), fd)){
        exit(1);
    }

    //checks the format of the ppm file is correct
    if(buffer[0] != 'P' || buffer[1] != '3'){
        fprintf(stderr, "Invalid image format! \n");
        exit( EXIT_FAILURE );
    }

    // implied else, file format correct

    printf("%s", newPPM->format);



    //allocate memory for the image
    // note: there is no item named 'PPM'
    // image = malloc(sizeof(PPM));
    //if(!image){
    // best to keep things together
    if( NULL == (image = malloc( sizeof struct PPM ) ) )
    {
        //fprintf(stderr, "Cannot allocate memory");
        // should include the OS message for the failure
        perror( "malloc for struct PPM failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, malloc successful


    // the following code does not store a comment in a linked list
    // and
    // skips over 1/2 the characters in the line due to the double call
    // to 'getc()' in the inner while loop
    //checks whether the next character is a comment and store it in a linked list
    //c = getc(fd);
    //while(c == '#'){
    //    while(getc(fd) != '\n'){
    //    c = getc(fd);
    //    }
    //}

    // this line does not compile!  did you actually mean to call: 'fscanf()'?
    //if(fscaf(fd, "%d %d", &image->height, &image->width)!= 2)
    if( 2 == fscanf( fp, "%d %d", &image->height, &image->width) )
    {
        // next line NOT true, what actually happened is the call to 'fscanf()' failed
        //fprintf(stderr, "Size of image is invalid");
        perror( "fscanf for image height and width failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fscanf successful

    // best practice to close a file, where it was opened.
    //fclose(fd);
    return newPPM;
 //};  do not follow a function definition with a semicolon
}


// Note: the following function is never called
// showPPM(struct PPM * image) each function signature needs a return type, even if 'void'
void showPPM(struct PPM * image)
{
    // Note: PPM images have the number of pixels in each row rounded up to a multiple of 4
    //       but this posted code fails to handle that
    //two-dimensional array to show the rows and columns of pixels.
    // bad idea, suggest passing the (already input) width and height
    //   and use those passed in values to define the array sizes
    int rgb_array[MAX_HEIGHT][MAX_WIDTH];
    int i;
    int j;

    for(i = 0; i<MAX_HEIGHT; i++)
    {
        for(j = 0; j<MAX_WIDTH; j++)
        {
            printf("%d", rgb_array[i][j]);
        }
    }
// }; do not follow a function definition with a semicolon
}

关于c - 在C中显示ppm图像的rgb值和冲突类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35326911/

相关文章:

html - 自定义打印页面大小 css 在 Windows 系统中不起作用

c - union 在c中初始化

iphone - 如何在 iPhone 的 MFMailComposeViewController 中将图像嵌入 html

C 通用打印数组函数 - 打印字符串数组

android - 如何图像按钮在 android 的 ListView 中创建圆圈?

java - 两张图片,一张在 Java 中

javascript - 是否可以使用 JavaScript 直接进入打印过程而不加载 html 页面?

c - 以多平台方式将 4 个数组写入一个文件的最简单方法是什么?

c++ - 不使用预处理器调用 Clang

c - 是否可以从内存泄漏中获取数据?