【问题标题】:Reading In PPM Pixels As RGB Integers以 RGB 整数形式读取 PPM 像素
【发布时间】:2022-01-02 19:05:32
【问题描述】:

所以我的代码涉及读取 PPM 图像,然后将其存储在数组中,以便可以将其保存在新的 ppm 文件中。尽管我认为我的指针存在问题,这意味着它实际上并未读取文件。此外,我的代码在为数组分配内存后结束。非常感谢任何帮助。

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

#define maxheight 1080
#define maxwidth 1920
#define RGB_COMPONENT_COLOUR 255
#define pgmtype "P2"
#define ppmtype "P3"

typedef struct
{
    int red, green, blue;
} PPMPixel;

typedef struct
{
    int x, y;
} PPMImage;

typedef struct 
{
    int rgb_comp_colour;
    char filetype[3];
    int height;
    int width;
} PPMHead;


/*PPMHead head[3];
{
    head[3].filetype;
    head[3].height;
    head[3].width;
}*/

PPMHead head;
PPMHead* head_ptr = &head;

PPMPixel p;
PPMPixel* p_ptr = &p;

PPMPixel *data; //Defines pointer to PPMPixel
int **Array; //Double pointer defines as a pointer pointing to a pointer that is pointing to an integer
PPMPixel **RGBArray; //Double pointer defines as a pointer pointing to a pointer that is pointing to the PPMPixel structure
FILE *fp;
int r, g, b;

void headercheck ()
{

    fscanf(fp, "%s %d %d %d", head.filetype, &head.width, &head.height, &head.rgb_comp_colour);
    printf("%s %d %d %d", head.filetype, head.width, head.height, head.rgb_comp_colour);

    if (head.width > maxwidth || head.height > maxheight)
    {
        printf("\tInvalid image size. The maximum value of image is 1920x1080.\n");
        printf("\tImage size is %d x %d\n", head.width, head.height);
    }
    else
    {
        printf("\tImage size is valid\n");
        printf("\tImage size is %d x %d\n", head.width, head.height);
    }

    if ((strcmp (head.filetype, pgmtype)!=0) && (strcmp (head.filetype, ppmtype)!=0))
    {
        printf("\tInvalid filetype\n");
    }
    else
    {
        if(strcmp (head.filetype, pgmtype)==0)
        {
            printf("\t File is PGM type image\n");
        }
        else
        {
            if(strcmp (head.filetype, ppmtype)==0)
            {
                printf("\t File is PPM type image\n");
            }
        }
    }

    if ((head.rgb_comp_colour == RGB_COMPONENT_COLOUR))
    {
        printf("\t Image is 8 bit\n");
    }
    else
    {
        if (head.rgb_comp_colour > RGB_COMPONENT_COLOUR)
        {
            printf("Maximum bit-depth is 8 bits\n");
        }
        else
        {
            printf("\tImage is not 8 bit\n");
        }
    }
}

int main(void)
{
    char fname[100];
    printf("Enter file name: ");
    scanf("%s", fname);
    fseek(stdin,0,SEEK_END);
    fp = fopen(fname, "r");
    if (fp == NULL)
    {   
        printf("\tError while opening the file\n");
    }                        
    else    
    {
        printf("\tReading in %s\n", fname);
    }

    headercheck();

    if (strcmp (head.filetype, ppmtype)==0)
    {
        RGBArray = (PPMPixel **)malloc(head.height*sizeof(PPMPixel*)); //Points to malloc
            if((RGBArray == NULL))
                {
                    printf("Error allocating memory to the array");
                }
                else
                {
                    printf("Memory allocated to the PPM array sucessfully");
                }
        for (int i=0;i<head.width;i++)
        {
            RGBArray[i] = (PPMPixel *)malloc(head.width*sizeof(PPMPixel));
        }
        
        printf("Error 2");
        //Initialising each element
        for (int j=0;j<head.height;j++)
        {
            for (int i=0;i<head.width;i++)
            {
                fscanf(fp, "%3d %3d %3d ", &p.red, &p.green, &p.blue); //Scans in integers of the address pointer to PPMPixel
                data = &RGBArray[i][j]; //Defines data pointer pointing to address of RGBArray[i][j]
                data->red = p.red; //Access member of PPMPixel structure to equal one of the three RGB channels
                data->green = p.green;
                data->blue = p.blue;
            }
        }
    }
    fclose(fp);
    
    //Save PPM Array Into New PPM File
    FILE *pf;
    int i, j;
    char fname2[100];
    printf("Enter file name: ");
    scanf("%s", fname2);
    fseek(stdin,0,SEEK_END);
    pf = fopen(fname2, "w");
    if (pf == NULL)
    {   
        printf("\tError while opening the file\n");
    }
    else    
    {
        printf("\tWriting in %s\n", fname2);
    }

    for(j=0;j<head.height;j++)
    {
        fprintf(pf, "\n");
        for(i=0;i<head.width;i++)
        {
            fprintf(pf, "%3d ", RGBArray[i][j].red);
            fprintf(pf, "%3d ", RGBArray[i][j].green);
            fprintf(pf, "%3d ", RGBArray[i][j].blue);
            //fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*r);
            //fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*g);
            //fprintf(pf, "%3d ", (RGBArray+j*head.width + i)*b);
        }
    }

    fclose(pf);
    free(RGBArray);
    RGBArray = NULL;
    for(int i=0;i<head.width;i++)
        {
            free(RGBArray[i]);
            RGBArray[i] = NULL;
        }
    return 0;
}

【问题讨论】:

    标签: arrays c malloc rgb ppm


    【解决方案1】:

    你主要是把widthheight混用了,但还有其他问题。

    • width 是列数
    • height 是行数

    按内存顺序排列的C二维数组是Row Major
    在内存中存储图像的惯例是“按行”。
    索引是RGBArray[col][row](在你的代码中应该是RGBArray[j][i])。

    插图:

     RGBArray[0][0]               RGBArray[0][14]
                   |             |
                   V             V
                   <--- width --->
    RGBArray[0] -> ############### ^
    RGBArray[1] -> ############### |
    RGBArray[2] -> ############### height
    RGBArray[3] -> ############### |
    RGBArray[4] -> ############### V
    

    我使用以下 PPM 文本文件进行测试 (in.ppm):

    P3
    # ppm comment
    4 3
    255
      1   2   3    11  12  13   21  22  23    31  32  33
    101 102 103   111 112 113  121 122 123   131 132 133
    201 202 203   211 212 213  221 222 223   231 232 233
    

    更正的代码(请阅读 cmets):

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define maxheight 1080
    #define maxwidth 1920
    #define RGB_COMPONENT_COLOUR 255
    #define pgmtype "P2"
    #define ppmtype "P3"
    
    typedef struct
    {
        int red, green, blue;
    } PPMPixel;
    
    typedef struct
    {
        int x, y;
    } PPMImage;
    
    typedef struct
    {
        int rgb_comp_colour;
        char filetype[3];
        int height;
        int width;
    } PPMHead;
    
    
    PPMHead head;
    PPMHead* head_ptr = &head;
    
    PPMPixel p;
    PPMPixel* p_ptr = &p;
    
    PPMPixel *data; //Defines pointer to PPMPixel
    int **Array; //Double pointer defines as a pointer pointing to a pointer that is pointing to an integer
    PPMPixel **RGBArray; //Double pointer defines as a pointer pointing to a pointer that is pointing to the PPMPixel structure
    FILE *fp;
    int r, g, b;
    
    void headercheck()
    {
        char tmp[201]; //Temporary string.
        fscanf(fp, "%2s", head.filetype); //%2s ensures that no more than two characters are read.
        fscanf(fp, "%200s", tmp);
    
        if (tmp[0] == '#')
        {
            //The second line may be a comment starting with '#'
            fgets(tmp, 200, fp);    //Skip the comment.
            fscanf(fp, "%d", &head.width);
        }
        else
        {
            //If not a comment, read width from tmp.
            sscanf(tmp, "%d", &head.width);
        }
    
        //fscanf(fp, "%s %d %d %d", head.filetype, &head.width, &head.height, &head.rgb_comp_colour);
    
        fscanf(fp, "%d %d", &head.height, &head.rgb_comp_colour);
        printf("%s %d %d %d", head.filetype, head.width, head.height, head.rgb_comp_colour);
    
        if (head.width > maxwidth || head.height > maxheight)
        {
            printf("\tInvalid image size. The maximum value of image is 1920x1080.\n");
            printf("\tImage size is %d x %d\n", head.width, head.height);
        }
        else
        {
            printf("\tImage size is valid\n");
            printf("\tImage size is %d x %d\n", head.width, head.height);
        }
    
        if ((strcmp(head.filetype, pgmtype) != 0) && (strcmp(head.filetype, ppmtype) != 0))
        {
            printf("\tInvalid filetype\n");
        }
        else
        {
            if (strcmp(head.filetype, pgmtype) == 0)
            {
                printf("\t File is PGM type image\n");
            }
            else
            {
                if (strcmp(head.filetype, ppmtype) == 0)
                {
                    printf("\t File is PPM type image\n");
                }
            }
        }
    
        if ((head.rgb_comp_colour == RGB_COMPONENT_COLOUR))
        {
            printf("\t Image is 8 bit\n");
        }
        else
        {
            if (head.rgb_comp_colour > RGB_COMPONENT_COLOUR)
            {
                printf("Maximum bit-depth is 8 bits\n");
            }
            else
            {
                printf("\tImage is not 8 bit\n");
            }
        }
    }
    
    int main(void)
    {
        const char *fname = "in.ppm";
        //char fname[100];
        //printf("Enter file name: ");
        //scanf("%s", fname);
        //fseek(stdin, 0, SEEK_END);
        fp = fopen(fname, "r");
        if (fp == NULL)
        {
            printf("\tError while opening the file\n");
        }
        else
        {
            printf("\tReading in %s\n", fname);
        }
    
        headercheck();
    
        if (strcmp(head.filetype, ppmtype) == 0)
        {
            RGBArray = (PPMPixel **)malloc(head.height * sizeof(PPMPixel*)); //Points to malloc
            if ((RGBArray == NULL))
            {
                printf("Error allocating memory to the array\n");
            }
            else
            {
                printf("Memory allocated to the PPM array successfully\n");
            }
    
            //for (int i = 0; i < head.width; i++)
            for (int i = 0; i < head.height; i++)   //Iterate height rows
            {
                RGBArray[i] = (PPMPixel *)malloc(head.width * sizeof(PPMPixel));
    
                if ((RGBArray[i] == NULL))
                {
                    printf("Error allocating memory to the array\n");
                }
            }
    
            //printf("Error 2");
            //Initializing each element
            for (int j = 0; j < head.height; j++)
            {
                for (int i = 0; i < head.width; i++)
                {
                    fscanf(fp, "%3d %3d %3d ", &p.red, &p.green, &p.blue); //Scans in integers of the address pointer to PPMPixel
                    //data = &RGBArray[i][j]; //Defines data pointer pointing to address of RGBArray[i][j]
                    data = &RGBArray[j][i]; //The row index comes first - (use [j][i] instead of [i][j])
                    data->red = p.red; //Access member of PPMPixel structure to equal one of the three RGB channels
                    data->green = p.green;
                    data->blue = p.blue;
                }
            }
        }
        fclose(fp);
    
        //Save PPM Array Into New PPM File
        FILE *pf;
        int i, j;
        //char fname2[100];
        //printf("Enter file name: ");
        //scanf("%s", fname2);
        //fseek(stdin, 0, SEEK_END);
        const char *fname2 = "out.ppm";
        pf = fopen(fname2, "w");
        if (pf == NULL)
        {
            printf("\tError while opening the file\n");
        }
        else
        {
            printf("\tWriting in %s\n", fname2);
        }
    
        //Write the PPM header
        ////////////////////////////////////////////////////////////////////////////
        fprintf(fp, "%s\n", head.filetype);
        fprintf(fp, "%d %d\n", head.width, head.height);
        fprintf(fp, "%d\n", head.rgb_comp_colour);
        ////////////////////////////////////////////////////////////////////////////
    
        for (j = 0; j < head.height; j++)
        {
            //fprintf(pf, "\n");
            for (i = 0; i < head.width; i++)
            {
                //fprintf(pf, "%3d ", RGBArray[i][j].red);
                //fprintf(pf, "%3d ", RGBArray[i][j].green);
                //fprintf(pf, "%3d ", RGBArray[i][j].blue);
    
                fprintf(pf, "%3d ", RGBArray[j][i].red);    //row index comes first - use [j][i] instead of [i][j]
                fprintf(pf, "%3d ", RGBArray[j][i].green);
                fprintf(pf, "%3d ", RGBArray[j][i].blue);
            }
            fprintf(pf, "\n");
        }
    
        fclose(pf);
        //free(RGBArray);
        //RGBArray = NULL;
        for (int i = 0; i < head.height; i++)
        {
            free(RGBArray[i]);
            RGBArray[i] = NULL;
        }
        free(RGBArray); //Free RGBArray after free RGBArray[i]
        RGBArray = NULL;
        return 0;
    }
    

    输出文件(out.ppm):

    P3
    4 3
    255
      1   2   3  11  12  13  21  22  23  31  32  33 
    101 102 103 111 112 113 121 122 123 131 132 133 
    201 202 203 211 212 213 221 222 223 231 232 233 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 2021-08-05
      • 2019-03-11
      相关资源
      最近更新 更多