質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2014閲覧

Libpngで16bitのpng画像を生成するときにpng_write_pngでエラーが発生する

_momizi

総合スコア8

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/01/28 05:22

前提・実現したいこと

高さマップのために16bitグレースケールのpngもしくはリトルエンディアンバイトオーダーのRAWを生成したいです。
そのため、簡潔なものがあればLibpng以外のライブラリでも良いのですが、今回はLibpngを使ってpngを生成しようとしています。
元データとしては0-65535に正規化した2000*2000のデータを使用しています。

発生している問題・エラーメッセージ

実行するとpng_write_png()関数で以下のようなエラーが出て動作が停止します。 デバッグで実行するとpng_write_png()関数を通るときに「wtnpdbは読み込まれていません」と出ます。 Debugでデバッグ無しで実行を行うとexeが停止したとのエラーメッセージが表示されますが、VisualStudioでデバッグを 選択すると、「クラッシュプロセスにアタッチできません。このコマンドを実行するための記憶領域がありません」と出ます。

該当のソースコード

C++

1#include"png.h" 2 3#define PictureSize 2000 4#define PictureDepth 16 5 6 int i, x, y; 7 int row_size; 8 int color_type; 9 10 //保存先ファイル 11 FILE *hp; 12 hp = fopen("HeightMap.png", "wb"); 13 14 //設定 15 png_structp png = NULL; 16 png_infop info = NULL; 17 png_bytep row; 18 png_bytepp rows = NULL; 19 png_colorp palette = NULL; 20 color_type = PNG_COLOR_TYPE_GRAY; 21 row_size = sizeof(png_byte) * PictureSize; 22 23 //構造体初期化 24 png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 25 if (png == NULL) { 26 goto error; 27 } 28 info = png_create_info_struct(png); 29 if (info == NULL) { 30 goto error; 31 } 32 if (setjmp(png_jmpbuf(png))) { 33 goto error; 34 } 35 //画像の設定 36 png_init_io(png, hp); 37 png_set_IHDR(png, info, PictureSize, PictureSize, PictureDepth, 38 color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, 39 PNG_FILTER_TYPE_DEFAULT); 40 41 //メモリ確保 42 rows = (png_bytepp)png_malloc(png, sizeof(png_bytep) * PictureSize); 43 if (rows == NULL) { 44 goto error; 45 } 46 47 memset(rows, 0, sizeof(png_bytep) * PictureSize); 48 for (y = 0; y < PictureSize; y++) { 49 if ((rows[y] = (png_byte*)png_malloc(png, row_size)) == NULL) { 50 goto error; 51 } 52 } 53 54 //グレースケールでpixelの画素値を設定 55 for (y = 0; y < PictureSize; y++) { 56 row = rows[y]; 57 for (x = 0; x < PictureSize; x++) { 58 *row++ = Buffer[y][x];//0-65535に正規化したデータを代入 59 } 60 } 61 png_set_rows(png, info, rows); 62 63 //保存ここでバグる 64 png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL); 65 66error: 67 if (rows != NULL) { 68 for (y = 0; y < PictureSize; y++) { 69 png_free(png, rows[y]); 70 } 71 png_free(png, rows); 72 } 73 74 png_destroy_write_struct(&png, &info); 75 fclose(hp);

試したこと

以下のことを試しましたが、エラーは解決しませんでした。

・元データとなる20002000のデータが存在するかの確認
・10
10などの小さなサイズでの確認
・「グレースケールでpixelの画素値を設定」の部分で元データを使わずに適当な値を入れて確認
・3番目と合わせてPictureDepthを8に設定して確認

補足情報(FW/ツールのバージョンなど)

VisualStdio 2013 および 2017

LibpngはNugetから取得
https://github.com/coapp-packages/libpng

参考サイト
https://www.mm2d.net/main/prog/c/image_io-15.html
→mallocのキャストを追加

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1画素16bitのグレースケール画像を扱うのであれば、少なくとも
png_byte
ではなく
png_uint_16
にするべきかな、と思います。png_bytepやpng_byteppも同様に。

ただ、VisualStudioではなくて申し訳ないですが、こちらのCygwin環境では

C

1#include <string.h> 2#include "png.h" 3 4#define PictureSize 2000 5#define PictureDepth 8 6 7int main(int ac, char *av[]) 8{ 9 int i, x, y; 10 int row_size; 11 int color_type; 12 13 //保存先ファイル 14 FILE *hp; 15 hp = fopen("HeightMap.png", "wb"); 16 17 //設定 18 png_structp png = NULL; 19 png_infop info = NULL; 20 png_bytep row; 21 png_bytepp rows = NULL; 22 png_colorp palette = NULL; 23 color_type = PNG_COLOR_TYPE_GRAY; 24 row_size = sizeof(png_byte) * PictureSize; 25 26 //構造体初期化 27 png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 28 if (png == NULL) { 29 goto error; 30 } 31 info = png_create_info_struct(png); 32 if (info == NULL) { 33 goto error; 34 } 35 if (setjmp(png_jmpbuf(png))) { 36 goto error; 37 } 38 //画像の設定 39 png_init_io(png, hp); 40 png_set_IHDR(png, info, PictureSize, PictureSize, PictureDepth, 41 color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, 42 PNG_FILTER_TYPE_DEFAULT); 43 44 //メモリ確保 45 rows = (png_bytepp)png_malloc(png, sizeof(png_bytep) * PictureSize); 46 if (rows == NULL) { 47 goto error; 48 } 49 50 memset(rows, 0, sizeof(png_bytep) * PictureSize); 51 for (y = 0; y < PictureSize; y++) { 52 if ((rows[y] = (png_byte*)png_malloc(png, row_size)) == NULL) { 53 goto error; 54 } 55 } 56 57 //グレースケールでpixelの画素値を設定 58 for (y = 0; y < PictureSize; y++) { 59 row = rows[y]; 60 for (x = 0; x < PictureSize; x++) { 61 *row++ = (x+y); 62 } 63 } 64 png_set_rows(png, info, rows); 65 66 //保存ここでバグる 67 png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL); 68 69error: 70 if (rows != NULL) { 71 for (y = 0; y < PictureSize; y++) { 72 png_free(png, rows[y]); 73 } 74 png_free(png, rows); 75 } 76 77 png_destroy_write_struct(&png, &info); 78 fclose(hp); 79 80 return 0; 81} 82

で、エラーなく実行できてpng画像が生成されました。
・「グレースケールでpixelの画素値を設定」の部分で元データを使わずに適当な値を入れて確認

・PictureDepthを8に設定して確認
に相当する変更だけのはずなんですが。

投稿2018/01/28 13:13

okrt

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

_momizi

2018/01/29 11:55 編集

解答ありがとうございます。 既存のプロジェクト内に実装していたのですが、新規にプロジェクトを作りそちらで実装したところエラーがなくなりましたので、おそらくプロジェクトの設定の問題だったようです。 どのあたりの設定がダメだったのかの解明はできておりませんが、アドバイスを参考に以下のように修正したところ、16bitのpng画像の生成は可能になりました。 ありがとうございました。 int main(int ac, char *av[]) { int x, y; int row_size; int color_type; //保存先ファイル FILE *hp; hp = fopen("HeightMap.png", "wb"); //設定 png_structp png = NULL; png_infop info = NULL; png_uint_16p row; png_uint_16pp rows = NULL; png_colorp palette = NULL; color_type = PNG_COLOR_TYPE_GRAY; row_size = sizeof(png_uint_16) * PictureSize; //構造体初期化 png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { goto error; } info = png_create_info_struct(png); if (info == NULL) { goto error; } if (setjmp(png_jmpbuf(png))) { goto error; } //画像の設定 png_init_io(png, hp); png_set_IHDR(png, info, PictureSize, PictureSize, PictureDepth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //メモリ確保 rows = (png_uint_16pp)png_malloc(png, sizeof(png_uint_16p) * PictureSize); if (rows == NULL) { goto error; } memset(rows, 0, sizeof(png_bytep) * PictureSize); for (y = 0; y < PictureSize; y++) { if ((rows[y] = (png_uint_16*)png_malloc(png, row_size)) == NULL) { goto error; } } //グレースケールでpixelの画素値を設定 for (y = 0; y < PictureSize; y++) { row = rows[y]; for (x = 0; x < PictureSize; x++) { *row++ = (x + y); } } png_set_rows(png, info, (png_bytepp)rows); //保存ここでバグる png_write_png(png, info, PNG_TRANSFORM_SWAP_ENDIAN, NULL); error: if (rows != NULL) { for (y = 0; y < PictureSize; y++) { png_free(png, rows[y]); } png_free(png, rows); } png_destroy_write_struct(&png, &info); fclose(hp); return 0; }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問