【问题标题】:Calculate average RGB value of a PPM file计算 PPM 文件的平均 RGB 值
【发布时间】:2019-03-25 23:01:58
【问题描述】:

我正在尝试计算 PPM 图像的平均 RGB 值。我的尝试可以在下面的代码中看到,但是当我运行解决方案时,cmd 中的输出是:0 0 0

我觉得我尝试int clr = fscanf(f, "%i %i %i", &x, &y, &z); 中的代码行也不正确——我尝试使用 fscanf 作为 getPixel() 的替代品,它使用(显然)过时的“graphics.h”标头。

总结一下:

1.如何计算和打印 PPM 文件的平均 RGB 值?

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

//Image size 
#define WIDTH 2048 
#define HEIGHT 2048

int main()
{
int x, y, z;

//Used for tally
int R = 0;
int G = 0;
int B = 0;

//Loop count value
int total = 0;

//File handle 
FILE *f; 

//File open 
f = fopen("Dog2048x2048.ppm", "r"); 

if (f == NULL)
{
    fprintf(stderr, "Error: file could not be opened");
    exit(1);
}

//Iterate through the image width and height 
for (int i = 0; i < WIDTH; i++)
{
    for (int j = 0; j < HEIGHT; j++)
    {
        //Color clr = bmp.GetPixel(x, y);
        int clr = fscanf(f, "%i %i %i", &x, &y, &z);

        R += clr;
        G += clr;
        B += clr;

        total++;
    }
}

//Calculate average
R /= total;
G /= total;
B /= total;

//Print RGB 
printf("%i %i %i", R, G, B);

return 0; 
}

【问题讨论】:

  • 您没有考虑文件的标题部分(其中包括图像的宽度和高度等内容......您不应该对这些值进行硬编码。)
  • 并查找fscanf() 的文档以查看它返回的内容。然后想想你是如何使用这个价值的......
  • 我认为它是 ascii P3 格式 PPM,因为您使用的是 fscanf(),但您可能需要检查以确认在读取 P6 上的标题和错误时(或者也读取该格式)。如果是 P3,并且图像中有 cmets,则在读取文件时也必须考虑这些因素。
  • R += x; G += y, etc. 最好每次向 R、G 和 B 添加 3,如果 scanf 失败,则最糟糕的是添加 0。假设您有一个完整的 P3 文本 PPM 文件,您也没有考虑标题等。
  • 注意:2048x2048R 可以高达 50% INT_MAX。如果文件可以变得更大,请考虑long long R = 0;

标签: c average rgb


【解决方案1】:

文件Dog2048x2048.ppm 确实是P6 格式的PPM,定义为PPM Format Specification。因此,它的样本不是以文本表示,而是纯二进制,因此不是fscanf(…%i…),而是fread() 适合阅读它们,例如。 G。 Maxval 255 的手头文件:

    // skip over P6\n2048\n2048\n255\n
    if (fscanf(f, "P6 2048 2048%d%*c", &z) < 1)
        puts("unexpected format of file"), exit(1);

    // Iterate through the image width and height 
    for (int i = 0; i < WIDTH; i++)
    {   // Note that you mixed up WIDTH and HEIGHT - just doesn't matter here
        for (int j = 0; j < HEIGHT; j++)
        {
            //Color clr = bmp.GetPixel(x, y);
            unsigned char clr[3];
            if (fread(clr, 3, 1, f) < 1)
                printf("read error at %d,%d\n", i, j), exit(1);

            R += clr[0];
            G += clr[1];
            B += clr[2];
            total++;
        }
    }

【讨论】:

    【解决方案2】:

    在每个对此问题发表评论/分享他们的解决方案的用户的帮助下,我想我现在有一个解决方案,它按照我想要的方式运行,如下所示。

    代码打印出以下格式的 ppm 文件,然后继续查找打印到 cmd 的文件的平均 RGB 值。

    P6 
    # ignores comments in header 
    width 
    height 
    max colour value 
    

    我的工作解决方案尝试如下所示:

    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct {
        unsigned char r, g, b;
    } pixel;
    
    int main(int argc, char* argv[]) {
    
    char magic_number[1];
    int w, h, m;
    int red = 0; 
    int green = 0; 
    int blue = 0;
    int total = 0;      //Loop count initialised at 0 
    FILE* f;            //File handle
    pixel currentPix;   //Variable declaration for the current pixel 
    
    //Open and read the PPM file 
    f = fopen("Dog2048x2048.ppm", "r");
    if (f == NULL) {
        fprintf(stderr, "Error: file cannot be opened");
        exit(1);
    }
    
    //Get P6, width, height, maxcolour value 
    fscanf(f, "%s %d %d %d", &magic_number, &w, &h, &m);
    printf("magic_n = %s, width = %d, height = %d, max_colour = %d\n", magic_number, w, h, m);
    
    //iterate through the height and width of the ppm file 
    for (int j = 0; j < h; j++) {
        for (int i = 0; i < w; i++) {
    
            //Read data from the given stream 
            fread(&currentPix, 3, 1, f);
    
            //Stores current pixel RGB values in red, green, blue variables
            red += currentPix.r;
            green += currentPix.g;
            blue += currentPix.b;
    
            //Counts the iterations 
            total++; 
        }
    }
    
    //calculate averages for red, green, blue
    red /= total;
    green /= total;
    blue /= total;
    
    //print output of average rgb 
    printf("%d, %d, %d", red, green, blue);
    getchar();
    return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 2013-07-19
      • 1970-01-01
      • 2013-01-14
      相关资源
      最近更新 更多