PNG Decoder in C++

ysflight.com

はじめに


上のリンクから商品をご購入いただけると、少しの紹介料が作者に入ります。よかったら、サイト運営にご協力ください。

このページでは、趣味で書いたPNGデコーダを公開しています。今まで、自作ソフトで(仕事でも趣味でも)ビットマップの読み込みといえば、必ずBMPを使っていたんですが、そうするとプロジェクト全体のファイルのサイズがすぐ膨れてしまって、さらに、芸が無いのが気になって、それなりの圧縮ができるフォーマットに対応しようと一念発起して、PNG Decoderを書きました。せっかくなので、他にも同じような問題を持っている人がいると思うので、公開することにしました。まだ未対応のBit Depthもありますが、一応、普通に使う分はすべてカバーしたつもりです。

PNGファイルは、どっちかというと、手書き絵向けで、(可逆圧縮だけに)写真などはJPEGほど圧縮率は良くありませんが、しかし、PNGを作るソフトの性能によって、サイズが結構違ってくるようです。僕はPaint Shop Pro を使っていますが、このPNG Optimizerというのをかけてやると、MS OfficeについてくるMicrosoft Photo EditorでPNGを作るよりも、20〜30%自然がのサイズが小さくなります。自分のプログラムに絵を追加したい、けれどもビットマップファイルを展開して置いておくのもあまり芸が無い、という方は、PNGを利用してみてはどうでしょうか?

なお、YSFLIGHTプロジェクトは、慢性的にぎりぎり予算が続いています。よかったら、以下のリンクでサイト運営にご協力いただけると大変ありがたく思います。ご協力感謝します。

http://supportysflight.jp.ysflight.com

このページからダウンロードできるコードの利用について

このページからダウンロードできるコード(yspng.zipに含まれるファイル)は、とくにどのような目的に利用していただいても構いません。その目的がフリーソフトでも、商用ソフトでもどちらの場合でも、とくに作者に連絡しなくても使っていただいて結構です。それから、利用するプログラムがオープンソースでも、プロプライエタリでも、どちらでもいいです。なお、利用する場合、とくに出展の記述などは入れていただかなくても構いませんが、もちろん、入れていただければその方がうれしいです。

ただし、このコードを利用した結果について、作者は一切責任を負いませんので、利用する方ご自身の責任でご利用ください。

ダウンロード

[ダウンロード] yspng.zip (sample.cpp, yspng.h, yspng.cpp, win32sampleを含みます)

更新履歴

2005/05/15
Linux (GLX) サンプルの簡単なコマンドラインPNGビューアを追加しました。yspng.zipに一緒に入ってます。

2005/05/07
Win32サンプル(簡単なPNGビューア)を追加しました。yspng.zip に一緒に入ってます。

2005/04/08
公開。まだとても強力にテスト済みという状態ではないので、バグってる可能性大です。

対応コンパイラ

Visual C++ 6.0とVisual C++ .NETとg++で確認しました。

対応Bit Depth

Bit Depthって日本語になんて訳すんでしたっけ?ビット深度?

Non-Interlace Interlace
1bit Grayscale (Black & White) △ (Alpha未対応) ×
4bit Indexed Color ×
8bit Grayscale
8bit Grayscale with Alpha
8bit Indexed Color
24bit True Color (*1)
24bit True Color with Alpha (*1)
48bit True Color (*2)

(*1) PNGのSpecificationでは、24bit True Colorのことを8 bit True Colorと表記していますが(8bit per component)一般的には24bitと書くと思うので、ここではそのように書きます。

(*2) 24bit True Colorと同じ理屈で、R,G,Bそれぞれ16ビットをここでは、48bit True Colorと書きます。

PNG Decoder Classの使い方

PNG Decoderクラスを利用するには、利用するソースコードにyspng.hをincludeして、プロジェクトにyspng.cppを追加してください。

yspng.h, yspng.cppは、ふたつのクラス、YsGenericPngDecoderとYsRawPngDecoder、を含みます。YsGenericPngDecoderは、ヘッダの読み込みと圧縮データの展開をしますが、ピクセルデータを並べて表示可能な状態にする機能はありません。

YsRawPngDecoderは、PNGファイルを読み込んで、とにかくどの対応Bit DepthでもR,G,B,Aそれぞれ8ビットの配列に並べます。なので、その配列へのポインタは、例えばglDrawPixelsに直接渡して描画することができます。ただし、そのままでは上下反転しているので、表示前にいったん反転しておく必要がありますが、それは、YsRawPngDecoderのFlip関数でできます。それについては、sample.cppを参照してください。YsRawPngDecoderがあれば実用的には困らないのではないかと思います。

以下にそれぞれの使い方を書きます。すべての関数と変数は書いてないですが、大体使うのに十分程度なものだけ書きます。

使い方のサンプルは、sample.cppも参照してください。

YsGenericPngDecoder

YsGenericPngDecoderは、そのままでは、事実上何もしません。YsGenericPngDecoderを継承したクラスがPrepareOutput, Output, EndOutputの3関数をオーバーライドすることで、機能するPNGデコーダになります。手っ取り早く展開したビットマップが欲しいだけの場合は、YsRawPngDecoderクラスを参照してください。

関数

  • void Initialize(void);
    読み込み前にクラスの中身を初期化します。
  • int Decode(const char fn[]);
    fnで与えられたファイル名の.PNGファイルをデコードします。
  • virtual int PrepareOutput(void);
    Decode関数が、最初にこの関数を呼び出します。
  • virtual int Output(unsigned char dat);
    Decode関数が、圧縮されたビットマップデータを展開して、一バイト分だけ出力するためにこの関数を呼び出します。その他のヘッダ情報はDecode関数の中で処理するので、hdr, plt, trns, gammaなどのメンバ変数を参照することでヘッダ情報を見ることができます。
  • virtual int EndOutput(void);
    Decode関数が、読み込み終了後にこの関数を呼びます。

変数

  • YsPngHeader hdr;
    ヘッダ情報です。hdr.width, hdr.heightが横と縦のピクセル数です。
  • YsPngPalette plt;
    パレット情報です。
  • YsPngTransparency trns;
    透明色です。
  • unsigned int gamma;
    ガンマです。詳しくは、参考文献[1]を参照してください。

YsRawPngDecoder

YsRawPngDecoderは、PNGファイルを読み込んで、R,G,B,Aそれぞれ8ビットのピクセル情報を配列に展開します。とりあえず、手っ取り早くPNGを読み込んで表示したい場合は、このクラスが便利です。

関数

  • int Decode(const char fn[]);
    fnで与えられたファイル名の.PNGファイルをデコードして、メンバwid, heiにピクセル数を、rgbaにビットマップの配列へのポインタをセットします。読み込みに成功したときは、マクロYSOKを、失敗したときはマクロYSERRを返します。なお、このクラスで読み込んだビットマップの配列を、このクラスのライフタイム後に利用したい場合(例えば、YsRawPngDecoderクラスをローカル変数として定義して、読み込んだビットマップはその関数が終わった後も利用したいような場合)、メンバautoDeleteRgbaBufferにゼロをセットしてください。そうでないと、YsRawPngDecoderは、終了時に自動的にrgbaが指すメモリブロックを解放してしまいます。
  • void Flip(void);
    読み込んだビットマップの上下を反転します。このクラスは、とりあえず僕はOpenGLでPNG形式のビットマップを表示したかったとかいう目的で作ったのですが、そのままだとOpenGLは上下さかさまの絵を描いてしまうので、上下反転する関数を追加しました。

変数

  • int wid,hei;
    読み込んだPNGファイルのピクセル数です。
  • unsigned char *rgba;
    読み込んだPNGのビットマップのR,G,B,A値がストアしてある配列へのポインタです。
  • int autoDeleteRgbaBuffer;
    これがゼロでない場合、ポインタrgbaが指すメモリブロックを、YsRawPngDecoderが終了するとき、またはDecode関数が二度目以降呼ばれたとき、自動的に解放します。もしも、読み込んだビットマップをこのクラス外部で利用したい場合は、この値にゼロをセットしてください。なお、その場合、rgbaが指すメモリブロックを、delete [] rgba;みたいな形で解放しないと、メモリリークになるので気をつけてください。

References

[1] W3C, Portable Network Graphics (PNG) Specification (Second Edition),  http://www.w3.org/TR/PNG/

 

Comments are welcome.  Send E-Mail to: 

Back to http://www.ysflight.com