libpng Simplified API 解説
ver.1.6から、簡単にpngデータの読み書きができるように追加されたAPI群です。試しに使って見たら、ほんとに簡単だったので紹介したいと思います。
Simplified APIで出来ること
画像サイズやピクセルフォーマット、ベタデータ(解凍済み)になったデータ部を扱うことができます。
代わりにチャンクへの直接的なアクセスはできませんので、補助チャンクの情報が欲しい時は使えません。
基本
SimplifiedAPIは、png_image構造体が基点になります。
png_imageは、幅・高さ・フォーマットなど画像としての基本情報を扱います。BITMAPINFOHEADERやFT_Faceなどに相当する構造体です。
png_image構造体を、png_imageで始まる各種関数に渡しながら使っていきます。
読み出し
手順
- png_image構造体初期化
- png_image_begin_read_from_file関数で、画像情報を取得
- 画像情報を元にデータ部を格納できるバッファを確保
- png_image_finish_read関数で、データ部を取得
- すべての処理が終わったら、png_image_free関数で解放
png_image_begin_read_from_file関数には、png_image_begin_read_from_memory関数というメモリを対象にした関数もありますので、必要に応じて使い分けます。
サンプルコード
// 宣言と初期化 png_image png; memset(&png, 0, sizeof(png); png.version = PNG_IMAGE_VERSION; // これを忘れずに! // 読み出したいpngの基本情報を取得する png_image_begin_read_from_file(&png, "yukikaze.png"); // エラーメッセージなどはpng_image構造体に設定されるので、それをチェック // 次からは省略します if(PNG_IMAGE_FAILED(png)) { std::cout << png.message << endl; return; } // 読み出した情報に合わせて、データ部を格納するバッファを確保 uint32_t stride = PNG_IMAGE_ROW_STRIDE(png); uint8_t buf = new uint8_t[PNG_IMAGE_BUFFER_SIZE(png,stride)]; // データ部を取得 png_image_finish_read(&png, NULL, buf, stride, NULL); // bufを使って色々する // 使い終わったら解放 delete[] buf; png_image_free(&png);
PNG_IMAGE_で始まるのはすべてマクロです。1ピクセル当たりのバイト数とか、必要なバッファサイズなどを計算してくれます。
バッファには、png_image構造体のformatフラグに合わせたフォーマットで、左上から右下に向かってベタデータが書き込まれます。
フォーマットフラグは、PNG_FORMAT_で始まるマクロとして定義されています。
png形式が対応するすべてのフォーマットが扱えますが、ここでは一番使うであるRGB/RGBAを紹介します。
format | 意味 |
---|---|
PNG_FORMAT_RGB | 1ピクセルごとに、RGBの巡に1バイトずつ並ぶ。値の範囲は0~255 |
PNG_FORMAT_RGBA | 1ピクセルごとに、RGBAの巡に1バイトずつ並ぶ。値の範囲は0~255 |
書き出し
手順
- png_image構造体初期化
- png_image構造体に書き出すための情報(幅・高さ・フォーマットなど)を設定
- 設定した情報に合わせたデータを書き込んだバッファを用意
- png_image_write_to_file関数で、書き込む
- png_image_freeで後始末
サンプルコード
BMPをpngに変換します。
bitmap bmp; bmp.load("kaga.bmp"); // png_image構造体初期化 png_image png; memset(&png, 0, sizeof(png)); png.version = PNG_IMAGE_VERSION; // 必要な情報を設定 png.width = bmp.width(); png.height = bmp.height(); png.format = PNG_FORMAT_RGB; uint32_t stride = PNG_IMAGE_ROW_STRIDE(png); uint8_t buf[/*イメージサイズ*/]; // bmpのデータを左上から右下RGBの並びに変換したとする // pngファイルに変換 png_image_write_to_file(&png, "kaga.png", 0, buf, stride, NULL);
png_image_write_to_file関数の第5引数のstrideを負にして渡すと上下反転されます。
もちろん、png_image_write_to_file関数には、png_image_write_to_memory関数というメモリに書き出すバージョンも用意されています。