2012-01-11 107 views
6

我想寫(使用libpng)一個16位灰度圖像,其中每個點的顏色等於其座標的總和。下面的代碼應該產生一個16位的PNG,但產生8位像this。爲什麼?16位灰度PNG

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

void save_png(FILE* fp, long int size) 
{ 
    png_structp png_ptr = NULL; 
    png_infop info_ptr = NULL; 
    size_t x, y; 
    png_bytepp row_pointers; 

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 
    if (png_ptr == NULL) { 
     return ; 
    } 

    info_ptr = png_create_info_struct(png_ptr); 
    if (info_ptr == NULL) { 
     png_destroy_write_struct(&png_ptr, NULL); 
     return ; 
    } 

    if (setjmp(png_jmpbuf(png_ptr))) { 
     png_destroy_write_struct(&png_ptr, &info_ptr); 
     return ; 
    } 

    png_set_IHDR(png_ptr, info_ptr, 
       size, size, // width and height 
       16, // bit depth 
       PNG_COLOR_TYPE_GRAY, // color type 
       PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 

    /* Initialize rows of PNG. */ 
    row_pointers = (png_bytepp)png_malloc(png_ptr, 
     size*png_sizeof(png_bytep)); 

    for (int i=0; i<size; i++) 
     row_pointers[i]=NULL; 

    for (int i=0; i<size; i++) 
     row_pointers[i]=png_malloc(png_ptr, size*2); 

    //set row data 
    for (y = 0; y < size; ++y) { 
     png_bytep row = row_pointers[y]; 
     for (x = 0; x < size; ++x) { 
       short color = x+y; 
       *row++ = (png_byte)(color & 0xFF); 
       *row++ = (png_byte)(color >> 8); 
     } 
    } 

    /* Actually write the image data. */ 
    png_init_io(png_ptr, fp); 
    png_set_rows(png_ptr, info_ptr, row_pointers); 
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); 
    //png_write_image(png_ptr, row_pointers); 

    /* Cleanup. */ 
    for (y = 0; y < size; y++) { 
     png_free(png_ptr, row_pointers[y]); 
    } 
    png_free(png_ptr, row_pointers); 
    png_destroy_write_struct(&png_ptr, &info_ptr); 
} 

int main() 
{ 
    FILE* f; 
    if((f=fopen("test.png", "wb"))!=NULL) 
    { 
    save_png(f, 257); 

    fclose(f); 
    } 
    return 0; 
} 

回答

5

鏈接的圖像在Windows 7的「屬性」中顯示爲「16位」。我想你只是看到各種應用程序回落到轉換爲8位顯示,這(我猜)是相當期望的,因爲大多數顯示設備不支持16位。

+0

Windows 7顯示兩個漸變填充三角形。這應該是16位圖像的正方形和8位的三角形。 – Yagg 2012-01-11 12:02:20

+0

哦,你是對的。我再次用libpng讀取圖像並測試點的顏色。他們應該如此。 – Yagg 2012-01-11 13:08:45

1

對不起復活舊的線程,但我在這裏搜索後如何編寫16位灰度圖像。我遇到了類似的問題,我認爲發佈我如何解決問題會很有幫助。

TL; DR:

一)字節必須提供圖書館MSB第一,所以如果你翻車了上面這行它的工作原理:

*row++ = (png_byte)(color >> 8); 
*row++ = (png_byte)(color & 0xFF); 

二)要真正看到8位屏幕上的16位值,256以下的任何值將被簡單地修剪爲黑色。實際上,應該使用256倍數的值來查看任何內容。上面的color = x + y代碼可能不會產生足夠明亮的值。

我如何得到了上述結論:

我開始用上面的代碼,只用「X」的顏色,而不是「X + Y」。

意圖是有一個漸變,從左邊的黑色漸變爲右邊的最大值x。

但是,我沒有一個長漸變,而是得到了幾個窄漸變。這個尖叫聲「錯誤的ENDIANNESS!」

我嘗試顛倒位,但後來我得到了一個黑色的圖像。花了我一段時間才找到線索,但由於屏幕只顯示8位,所以即使(在我的情況下)968的最大值太暗。這在8位屏幕上映射到2或3,甚至在高伽瑪的情況下,我也看不出差異。

因爲我知道我的最大X大約是1000,並且16位值的最大值是65000 ish,所以我用(x * 60)作爲我的顏色。最終產生了可見的結果。

感謝您的原始文章。這是一個很好的例子,開始。