質問
私は(libpngを使用して)16ビットのグレースケール画像を書き込もうとしています。各ポイント色は、その座標の合計に等しくなります。次のコードは16ビットPNGを生成する必要がありますが、代わりに8ビットのように生成されます これ. 。なんで?
#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;
}
解決
リンクされた画像は、Windows 7の「プロパティ」の「16ビット」であることを示しています。さまざまなアプリケーションがディスプレイ用の8ビットに変換されることに戻るのを見ているだけだと思います。これは、ほとんどのディスプレイデバイスが16ビットをサポートしていないため、かなり期待されています。
他のヒント
古いスレッドを復活させて申し訳ありませんが、16ビットのグレースケール画像を書く方法についてグーグルでグーグルでここに来ました。私は同様の問題に遭遇しましたが、問題を解決した方法を投稿するのに役立つと思いました。
tl; dr:
a)バイトを最初にライブラリMSBに提供する必要があるため、上記の行をこれに裏返すと機能します。
*row++ = (png_byte)(color >> 8);
*row++ = (png_byte)(color & 0xFF);
b)8ビット画面に実際に16ビット値を見るために、256未満の値は単に黒にクリップされます。実際に言えば、256の複数の倍数である値を使用して、何でも見る必要があります。上記の色= x + yコードは、おそらく十分に明るい値を生成しなかったでしょう。
上記の結論に達した方法:
上記のコードから始めて、「x + y」ではなく「x」のみを色として使用しました。
意図は、左側の黒から右側にあるものにあらゆるものに消える勾配を持つことでした。
ただし、長い勾配を1つ持つ代わりに、代わりにいくつかの狭い勾配を取得していました。これは「間違ったエンディアンネス!」と叫びました。
私はビットを反転させようとしましたが、それから黒い画像を手に入れました。手がかりを得るのに時間がかかりましたが、画面には8ビットのみが表示されるため、(私の場合)968の最大値でさえ暗すぎました。これは、8ビット画面で2または3にマッピングされ、高いガンマがあっても違いはわかりませんでした。
最大Xが約1000であり、16ビット値の最大値が65000 ISHであることを知っていたので、色として(x * 60)を使用しました。それは目に見える結果を生み出すことになりました。
元の投稿をありがとう。それは始めるのに最適な例でした。