2013-04-26 123 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