2013-04-26 110 views
0

我一直有成吨的麻烦让我的算法成功读取PPM图像... 它与一些图像完美的作品,但与其他人失败,导致半灰色(RGB 205,205 ,205)图像。阅读PPM图像问题

我已经试过了我可以找到并研究了几个小时的所有东西。我一直坚持一个星期了...

我希望你们能帮忙。

Image* pnm_read(char* filePath) 
    { 
     FILE* file; 
     char token[20]; 
     int imageWidth, imageHeight, maximumColorValue; 
     Image* image; 

     /* Abre arquivo PNM. */ 
     file = fopen(filePath, "r"); 
     if (file == NULL) 
     { 
      fprintf(stderr, "Não foi possível localizar o arquivo de imagem %s.\n", filePath); 
      return 0; 
     } 

     /* Lê Magic Number do cabecalho e vê se é P6*/ 
     pnm_get_token(file, token, sizeof token); 
     if (strcmp(token, "P6")) 
     { 
      fprintf(stderr, "%s não é um arquivo PPM válido.\n", filePath); 
      fclose(file); 
      return 0; 
     } 

     //Lê widht, height e valor máximo rgb 
     if (sscanf(pnm_get_token(file, token, sizeof token), "%d", &imageWidth)  != 1 || 
      sscanf(pnm_get_token(file, token, sizeof token), "%d", &imageHeight)  != 1 || 
      sscanf(pnm_get_token(file, token, sizeof token), "%d", &maximumColorValue) != 1) 
     { 
      fprintf(stderr, "%s não é um arquivo PNM válido.\n", filePath); 
      fclose(file); 
      return 0; 
     } 

     //Se não for RGB com componentes de 8 bits (0-255) dá erro 
     if (maximumColorValue != 255) 
     { 
      fprintf(stderr, "%s does not have 8-bit components: maximumColorValue=%d\n", filePath, maximumColorValue); 
      fclose(file); 
      return 0; 
     } 

     image = new Image(imageWidth, imageHeight); 
     unsigned char* pixelComponents = new unsigned char[imageWidth * imageHeight * 3]; 
     fread(pixelComponents, sizeof(unsigned char), imageWidth * imageHeight * 3, file); 
     fclose(file); 

     int r, g, b, pixel; 

     for(int i = 3; i <= imageWidth * imageHeight * 3; i += 3) 
     { 
      r = pixelComponents[i-3] & 0xff; 
      g = pixelComponents[i-2] & 0xff; 
      b = pixelComponents[i-1] & 0xff; 

      /*fread(&r, sizeof(char), sizeof(char), file); 
      fread(&g, sizeof(char), sizeof(char), file); 
      fread(&b, sizeof(char), sizeof(char), file); 

      r = r & 0xff; 
      g = g & 0xff; 
      b = b & 0xff;*/ 

      pixel = (255 << 24) | (r << 16) | (g << 8) | b;    

      // Atribuindo os pixels e virando imagem de cabeca para baixo 
      image->pixels[ (imageWidth * imageHeight) - (i/3) - 1] = pixel; 
     } 

     printf("Lido arquivo PNM (%s): %dx%d pixels.\n", filePath, image->width, image->height); 

     return image; 
    } 
+0

你的代码失败了哪种图像? – 2013-04-26 00:33:44

+0

随机,下载的PPM图像。但它工作(或工作,在我改变它一千次以使它工作100%之前)至少有一个例子是我在这里下载的。 它工作(或工作):https://dl.dropboxusercontent.com/u/11352921/exempla1b.ppm 它从来没有与: https://dl.dropboxusercontent.com/u/11352921/exempla2b.ppm – user1422133 2013-04-26 00:36:21

+0

您可以发布打印屏幕和/或错误消息吗?这将有很大的帮助... – 2013-04-26 02:33:56

回答

-1

一旦你正确地从文件(宽度和高度)读取数据,你可以做这样的事情 (我适应,我写了一段时间前一码):

... 
for(int i=0; i < height; ++i) 
{ 
    for(int j=0; j < width; ++j) 
    { 
     // Get pixel index from the PPM data 
     int pixelIndex = (i*3) * width + (j*3); 

     int r = pixelComponents[pixelIndex]; 
     int g = pixelComponents[pixelIndex + 1]; 
     int b = pixelComponents[pixelIndex + 2]; 

     // Calc gray value from RGB 
     int pixelValue = 0.2126f * r + 0.7152f * g + 0.0722f * b;    

     // Set pixel (i, j) in the output image 
     image->pixel[i * width + j] = pixelValue; 
    } 
} 
... 

我不能保证代码是正确的,但我认为它可以帮助你找到解决问题的办法。

祝你好运!

0

我修改了你的代码来使用结构来帮助理解和帮助调试。我还删除了诸如“(imageWidth * imageHeight) - (i/3) - 1”之类的难以调试的片段,并引入了一些临时变量来协助。

一些注意事项:你的图像像素似乎包括一个alpha通道,所以我已经添加了一个RGBA像素类型。这些杂项也与gcc保持一致。由于没有提及编译器,我会认为这是可以接受的。最后,这个例子有利于可读性而不是效率。有更好的方法来处理RGB和RGBA像素类型,但希望这会让您开始朝正确的方向发展。

typedef unsigned char u8; // define a more concise data type 

// Save current packing to ensure the pixel struct is 3 bytes in size 
#pragma pack(push) 

// Pack on 1-byte boundaries 
#pragma pack(1) 


typedef struct 
{ 
    u8 red; 
    u8 green; 
    u8 blue; 
    u8 alpha; 
} RgbaPixel; 

typedef struct 
{ 
    u8 red; 
    u8 green; 
    u8 blue; 
} RgbPixel; 

// Restore previous packing 
#pragma pack(pop) 

Image* pnm_read(char* filePath) 
{ 


    FILE* file = NULL; 
    char token[20] = ""; 
    int imageWidth = 0; 
    int imageHeight = 0; 
    int maximumColorValue = 0; 
    int numPixels = 0; 
    int numRead = 0; 
    Image* image = NULL; 

    /* Abre arquivo PNM. */ 
    file = fopen(filePath, "r"); 
    if (file == NULL) 
    { 
     fprintf(stderr, "Não foi possível localizar o arquivo de imagem %s.\n", filePath); 
     return 0; 
    } 

    /* Lê Magic Number do cabecalho e vê se é P6*/ 
    pnm_get_token(file, token, sizeof token); 
    if (strcmp(token, "P6")) 
    { 
     fprintf(stderr, "%s não é um arquivo PPM válido.\n", filePath); 
     fclose(file); 
     return 0; 
    } 

    //Lê widht, height e valor máximo rgb 
    if (sscanf(pnm_get_token(file, token, sizeof token), "%d", &imageWidth)  != 1 || 
     sscanf(pnm_get_token(file, token, sizeof token), "%d", &imageHeight)  != 1 || 
     sscanf(pnm_get_token(file, token, sizeof token), "%d", &maximumColorValue) != 1) 
    { 
     fprintf(stderr, "%s não é um arquivo PNM válido.\n", filePath); 
     fclose(file); 
     return 0; 
    } 

    //Se não for RGB com componentes de 8 bits (0-255) dá erro 
    if (maximumColorValue != 255) 
    { 
     fprintf(stderr, "%s does not have 8-bit components: maximumColorValue=%d\n", filePath, maximumColorValue); 
     fclose(file); 
     return 0; 
    } 

    image = new Image(imageWidth, imageHeight); 

    numPixels = imageWidth * imageHeight; 
    RgbPixel* pixelComponents = new RgbPixel [numPixels]; 
    numRead = fread(pixelComponents, sizeof(RgbPixel), numPixels, file); 
    fclose(file); 

    if (numRead != numPixels) 
    { 
     // Problem! 

     return 0; 
    } 

    RgbaPixel pixel = {0}; 

    for (int i = 0; i < numPixels; i++) 
    { 
       pixel.alpha = 255; 
     pixel.red = pixelComponents[i].red; 
     pixel.green = pixelComponents[i].green; 
     pixel.blue = pixelComponents[i].blue; 

     // Atribuindo os pixels e virando imagem de cabeca para baixo 
     image->pixels[i] = pixel; 
    } 

    printf("Lido arquivo PNM (%s): %dx%d pixels.\n", filePath, image->width, image->height); 

    return image; 
} 
+0

哇...感谢一大堆兄弟。一直以来都有不错的改进...但可悲的是,最终的结果依然如此。我的图像类的像素属性是一个int数组。这可能是问题吗?我在做什么来存储这些像素是 int pixel =(int)(pixel.alpha << 24 | pixel.red << 16 | pixel.green << 8 | pixel.blue); – user1422133 2013-04-26 05:08:42

+1

您的shift-and-OR像素分配是在for循环的前四行(即pixel.alpha = 255等)中完成的。生成的代码应该是等价的,但struct方法更易于读取/调试。像素属性是如何组织的?你确定它的ARGB作为你的移位和OR分配吗?您确定缺陷不在您的图像查看过程中吗? – Throwback1986 2013-04-26 14:58:14