本ライブラリは次に挙げる項目を行うために作成されたものである。
BMP)と
JPEG, PNG, Windows BMP画像形式との相互変換CBMP)と
TADの画像セグメント(IMAGESEG)との相互変換《R4 で追加された機能》
BMP構造体とWindows BMPとの相互変換に対応CBMP構造体とTADのIMAGESEGとの相互変換対応
これらのコードを、Bright/V開発環境において動作させるべく、 一部のコードを改変している。その理由を以下に挙げる。
fprintf使用時のstderrが存在しないため、printfに切り替えた。gmtimeが存在しないため、該当個所をコメントアウトした。
本ライブラリを使用して PNG形式やJPEG形式の画像を読み込む/書き込む アプリケーションを構築した場合、 該当ライブラリのライセンス条項に基づいて配布すること。
画像形式 使用ライブラリ PNG zlib v1.1.3(README), libpng v1.0.9(LICENSE) JPEG jpeg-6b(README) BMP (独自実装につきライセンス不要)
本項目で使用する構造体の形式を以下に示す。
IMG_BMP
typedef struct _libimg_bmp {
CSPEC* color_spec;
BMP* bmap;
ERR (*funcptr)();
VOID (*flushptr)();
VOID *io_src;
} IMG_BMP;
color_specには BTRON3仕様で示された CSPEC構造体を指定すること。
このエントリは読み込みと書き込みのいずれの場合にも参照される。
bmapには BTRON3仕様で示された BMP構造体を指定する。
書き込み時には BMP構造体中の全てのエントリが使用される。
ただし、このときプレーン数は現在のところ 1のみに対応している。
読み込み時には BMP構造体のpixbitsエントリのみを使用する。
後述する関数を実行後、全てのエントリが記述されている。
アプリケーション処理によって、ここで生成した BMP構造体を使用しなくなった時点で
BMP構造体のbaseaddr[]領域を解放し忘れないようにすること(単純に free(baseaddr[0])等を呼べば良い)。
funcptrには以下の引数の並びをもつ関数へのポインタを設定する。| 書き込み時 | (VOID* io_src, UB* bytes, UW size) |
| 読み込み時 | (UB* bytes, UW reqsize, VOID* io_src) |
flushptrには以下の引数の並びをもつ関数へのポインタを設定する。
なお、このエントリは書き込み時のみ使用される。
| 書き込み時 | (VOID* io_src) |
io_ptrは読み書き対象へのポインタを指定する。
このエントリはfuncptrやflushptrからそのまま渡される。
IMG_COMPACT
typedef struct _libimg_compact {
H method;
H opt;
} IMG_COMPACT;
methodには読み書きする画像形式を示す。
optには読み書きする画像形式に依存したオプションを指定する。
例を次に示す。
ERR write_fn(VOID* io_src, UB* bytes, UW size);
ERR flush_fn(VOID* io_src);
...
ERR
draw_func()
{
W gid0;
CSPEC cspec;
IMG_COMPACT compact = { LIBIMG_METHOD_PNG, LIBIMG_PNG_OPT_DEFAULT };
IMG_BMP img_bmp;
W so0; /* socketの場合 */
/* ここでCSPECの設定 */
gid0 = gopn_mem(NULL, &bmp, (VOID*)&cspec);
/* ここで描画処理 */
gcls_env(gid0);
img_bmp.color_spec = &cspec;
img_bmp.bmap = &bmp;
img_bmp.funcptr = write_fn; /* 書き込み用コールバックへのポインタ */
img_bmp.flushptr = flush_fn; /* flush用コールバックへのポインタ */
img_bmp.io_src = &so0; /* 入力ソース(ファイルやソケットディスクリプタ等) */
err = libimg_wri_bmp(&img_bmp, &compact);
return err;
}
ERR
write_fn(VOID* io_src, UB* bytes, UW size)
{
/*
* 書き込み時に呼び出されるコールバックルーチン
* io_src(入力) IMG_BMP.io_srcと同じ
* bytes(入力) 書き込むデータ
* size(入力) 領域 bytes の長さ
* 返値 ( >=0 ) 実際に書き込んだバイト数
* ( < 0 ) エラー
*/
W* socket_descriptor = (W*)io_src;
so_send(*socket_descriptor, bytes, size, 0);
return size;
}
VOID
flush_fn(VOID* io_src)
{
/*
* flush時に呼び出されるコールバックルーチン
* io_src(入力) IMG_BMP.io_srcと同じ
*/
/* no operation */
}
ERR read_fn(UB* bytes, UW reqsize, VOID* io_src);
...
ERR
draw_func()
{
CSPEC cspec;
BMP bmap;
IMG_COMPACT compact = { LIBIMG_METHOD_PNG, LIBIMG_PNG_OPT_DEFAULT };
IMG_BMP img_bmp;
W so0; /* socketの場合 */
/* CSPECの設定 */
cspec = { 1, { 0x1008, 0x0808, 0x0008, 0 }, NULL };
/* BMPの設定 */
bmap.pixbits = 0x2018;
img_bmp.color_spec = &cspec;
img_bmp.bmap = &bmap;
img_bmp.funcptr = read_fn; /* 読み込み用コールバックへのポインタ */
img_bmp.flushptr = NULL; /* 読み込み時には flushは使わない */
img_bmp.io_src = &so0; /* 入力ソース(ファイルやソケットディスクリプタ等) */
err = libimg_rea_bmp(&img_bmp, &compact);
#if 0
#error この間に BMP関係の処理を行う。
#error しかし、BMP等をグローバルで持つ場合はここで処理する必要はない。
#error いずれにせよ。処理終了後に bmap.baseaddr[0]を解放し忘れないこと。
#error 解放するには、free(bmap.baseaddr[0]); とすれば良い
#endif
return err;
}
ERR
read_fn(UB* bytes, UW reqsize, VOID* io_src)
{
/*
* 読み込み時に呼び出されるコールバックルーチン
* bytes(出力) 読み込んだデータを格納する領域へのポインタ
* reqsize(入力) 要求されたバイト数
* io_src(入力) IMG_BMP.io_srcと同じ
* 返値 ( >=0 ) 実際に読み込んだバイト数
* ( < 0 ) エラー
*/
return so_read(*((W*)io_src), bytes, reqsize);
}
|
ERR libimg_rea_bmp( IMG_BMP *dst, IMG_COMPACT *compact ) ERR libimg_rea_bmp_jpeg( IMG_BMP *dst, IMG_COMPACT *compact ) ERR libimg_rea_bmp_png( IMG_BMP *dst, IMG_COMPACT *compact ) ERR libimg_rea_bmp_bmp( IMG_BMP *dst, IMG_COMPACT *compact )
IMG_BMP *dst IMG_BMP構造体 IMG_COMPACT *compact DEV_SPEC データ
≧ 0 正常 < 0 エラー(エラーコード) (形式共通) LIBIMG_ERR_READ_WRITE_ERROR 読み込みエラー(不正なバイト列であった場合も含む) LIBIMG_ERR_NO_MEMORY 作業用メモリの確保に失敗した LIBIMG_ERR_ILLEGAL_PARAMETER サポートされないパラメータが与えられた (以下はPNG形式の場合のみ) LIBIMG_PNG_ERR_CANNOT_CREATE_STRUCT libpngで使用する構造体が生成できなかった
指定された形式の画像を読み込んで BMP構造体データに変換する。
compactのmethodエントリには以下の値を使用できる。
LIBIMG_METHOD_JPEG JPEG形式の画像読み込み LIBIMG_METHOD_PNG PNG形式の画像読み込み LIBIMG_METHOD_BMP Windows BMP形式の画像読み込み
compactのoptエントリに指定する値は、以下の関数を用いた場合と同じ値を指定する。
compactのmethod | 関数名 |
|---|---|
LIBIMG_METHOD_JPEG | libimg_rea_bmp_jpeg |
LIBIMG_METHOD_PNG | libimg_rea_bmp_png |
LIBIMG_METHOD_BMP | libimg_rea_bmp_bmp |
JPEG形式の画像を読み込んで BMP構造体データに変換する。
compactのoptエントリには以下の値を使用できる。
LIBIMG_JPEG_READ_OPT_1_8_SIZE 元画像の 1/8の大きさで BMPを取得する LIBIMG_JPEG_READ_OPT_1_4_SIZE 元画像の 1/4の大きさで BMPを取得する LIBIMG_JPEG_READ_OPT_1_2_SIZE 元画像の 1/2の大きさで BMPを取得する LIBIMG_JPEG_READ_OPT_1_1_SIZE 元画像と同じ大きさで BMPを取得する
PNG形式の画像を読み込んで BMP構造体データに変換する。
compactのoptエントリの値にはLIBIMG_PNG_OPT_DEFAULTを指定しておくことが望ましい。
compactのoptエントリには以下の値の ORを取る。
LIBIMG_PNG_OPT_DEFAULTLIBIMG_PNG_READ_OPT_SAVE_ALPHAIMG_BMP->bmap->baseaddr[1]に保存する。
(bmapの大きさに注意すること)。baseaddr[1]に確保される
メモリ量はbaseaddr[0]に確保されるメモリ量に等しい。
IMG_BMP->bmap->planes == 2
LIBIMG_PNG_READ_OPT_OVERWRITABLE_COLMAPIMG_BMP->cspec->colmapを元画像のパレットで上書きする。
このとき、システムから得られる標準カラーマップの判定は行わない。
(IMG_BMP->cspec->attr & 8)
Windows BMP形式の画像を読み込んで BMP構造体データに変換する。
compactのoptエントリの値にはLIBIMG_PNG_OPT_DEFAULTを指定しておくことが望ましい。
compactのoptエントリには以下の値の ORを取る。
LIBIMG_BMP_OPT_DEFAULTLIBIMG_BMP_READ_OPT_OVERWRITABLE_COLMAPIMG_BMP->cspec->colmapを元画像のパレットで上書きする。
このとき、システムから得られる標準カラーマップの判定は行わない。
(IMG_BMP->cspec->attr & 8)
|
ERR libimg_wri_bmp( IMG_BMP *src, IMG_COMPACT *compact ) ERR libimg_wri_bmp_jpeg( IMG_BMP *src, IMG_COMPACT *compact ) ERR libimg_wri_bmp_png( IMG_BMP *src, IMG_COMPACT *compact ) ERR libimg_wri_bmp_bmp( IMG_BMP *src, IMG_COMPACT *compact )
IMG_BMP *src IMG_BMP構造体 IMG_COMPACT *compact DEV_SPEC データ
≧ 0 正常 < 0 エラー(エラーコード) (形式共通) LIBIMG_ERR_READ_WRITE_ERROR 読み込みエラー(不正なバイト列であった場合も含む) LIBIMG_ERR_NO_MEMORY 作業用メモリの確保に失敗した LIBIMG_ERR_ILLEGAL_PARAMETER サポートされないパラメータが与えられた (以下はPNG形式の場合のみ) LIBIMG_PNG_ERR_CANNOT_CREATE_STRUCT libpngで使用する構造体が生成できなかった
BMP構造体のデータから指定された形式の画像に変換する。
compactのmethodエントリには以下の値を使用できる。
LIBIMG_METHOD_JPEG JPEG形式の画像書き込み LIBIMG_METHOD_PNG PNG形式の画像書き込み LIBIMG_METHOD_BMP Windows BMP形式の画像書き込み
compactのoptエントリに指定する値は、以下の関数を用いた場合と同じ値を指定する。
compactのmethod | 関数名 |
|---|---|
LIBIMG_METHOD_JPEG | libimg_wri_bmp_jpeg |
LIBIMG_METHOD_PNG | libimg_wri_bmp_png |
LIBIMG_METHOD_BMP | libimg_wri_bmp_bmp |
compactのoptエントリには以下の値を使用できる。
(all) LIBIMG_JPEG_OPT_NONE オプションを指定しない LIBIMG_JPEG_OPT_DEFAULT デフォルト値を指定 (quality parcentage) 1〜100 品質率(※この数字は10進数)。値が高い程品質は高い。 (dct tables) LIBIMG_JEPG_OPT_DCT_INT DCTで intを使用 LIBIMG_JPEG_OPT_DCT_SLOW LIBIMG_JPEG_OPT_DCT_INTと同 LIBIMG_JPEG_OPT_DCT_FAST DCTの高速版を使用 LIBIMG_JPEG_OPT_DCT_FLOAT DCTで floatを使用 (progression) LIBIMG_JPEG_OPT_PROGRESSION プログレッシブJPEG形式 (progression option) LIBIMG_JPEG_OPT_BASELINE LIBIMG_JPEG_OPT_PROGRESSION使用時にベースラインオプションを指定する
optに与える形式は次のとおり。opt := [ all || ( progression option | progression | dct tables | quality parcentage ) ]
compactのoptエントリには以下の値を使用できる。
LIBIMG_PNG_OPT_BEST 圧縮率最適 LIBIMG_PNG_OPT_DEFAULT デフォルト値を使用 LIBIMG_PNG_OPT_INTERLACE インタレース形式
optに与える形式は次のとおり。opt := [ LIBIMG_PNG_OPTDEFAULT || ( LIBIMG_PNG_OPT_INTERLACE | LIBIMG_PNG_OPT_BEST ) ]
compactのoptエントリには以下の値を使用できる。
LIBIMG_BMP_OPT_COMPRESS (8ビット)RLE圧縮の適用(カラーマップ使用時のみ)。
optに与える形式は次のとおり。opt := [ LIBIMG_BMP_OPT_DEFAULT || (LIBIMG_BMP_OPT_COMPRESS) ]
CBMPとIMAGESEGとの相互変換本項目で使用する構造体の形式を以下に示す。
IMG_TADINFO
typedef struct {
RECT view; /* 表示領域 */
RECT draw; /* 描画領域 */
UNITS h_unit; /* 座標単位(水平) */
UNITS v_unit; /* 座標単位(垂直) */
H slope; /* 傾き */
H rsrv1; /* 予約 */
CSPEC* cspec; /* カラー情報 */
CBMP* cbmp; /* 圧縮ビットマップ */
UB* mask; /* マスク */
W masksz; /* マスクのサイズ */
COLOR bgcolor; /* 背景色 */
Bool reverse; /* 色の反転表現 */
} IMG_TADINFO;
IMG_TADINFOの各エントリは、
IMAGESEGのエントリと対応している。
maskとmaskszはcbmpに示した画像の
マスクを設定するものだが、マスクが存在しない場合にはそれぞれ
NULLと0を設定する。
bgcolorは背景色を設定するものだが、
背景色を設定しない場合には、0xffffffffを設定する。
|
WERR libimg_rea_seg(IMAGESEG* imgseg, W imgsegsz, IMG_TADINFO* info)
IMAGESEG* imgseg 読み込み元の画像セグメント W imgsegsz 画像セグメントのサイズ IMG_TADINFO* info 読み込んだ画像セグメント情報
≧ 0 正常; 読み込んだプレーン番号(NULL指定時も含む) < 0 エラー(エラーコード) ER_PAR 指定した画像セグメントのサイズ(imgsegsz)が BASE_SIZE_IMAGESEGよりも少なかった
TAD画像セグメントを読みこんで、CBMP構造体データに格納しなおす。 格納先のメモリは予め用意しておかなければならない。
次のようにimgsegszを
BASE_SIZE_IMAGESEGに指定することにより、
必要なメモリ格納にデータが取得できる。
{
err = libimg_rea_seg(imageseg, BASE_SIZE_IMAGESEG, &info);
if(err < 0) return -1;
/* この間にメモリ確保 */
err = libimg_rea_seg(imageseg, sizeof(imageseg), &info);
if(err < 0) return -1;
/* CSPECと CBMPを用いて処理 */
}
|
WERR libimg_wri_seg(IMAGESEG* imgseg, IMG_TADINFO* info);
IMAGESEG* imgseg 書き込み先の画像セグメント。NULLのときは格納しない。 IMG_TADINFO* info 書き込む画像セグメント情報
≧ 0 正常; 画像セグメントのサイズ < 0 エラー(エラーコード) ER_PAR cspec, cbmpに NULLが指定された。
CBMP構造体から TAD画像セグメントに書き込む。 格納先のメモリは予め用意しておかなければならない。
必要なメモリを計算するには、次のようにimgsegに NULLを指定する。
{
W rec_offs; /* レコードオフセット */
W ofd; /* 出力先のファイルデスクリプタ */
/* 画像セグメントの書き出し */
{
LTADSEG ltadseg = { TC_SPEC | TS_IMAGE, 0, 0 };
IMAGESEG *imgseg;
W imgseg_size = libimg_wri_seg(NULL, cspec, dstcbmp, NULL, NULL);
if(imgseg_size > 65534)
{
ltadseg.len = 0xffff;
ltadseg.llen = imgseg_size;
wri_rec(ofd, rec_offs, (B*)<adseg, sizeof(LTADSEG), NULL, NULL, 0);
rec_offs += sizeof(LTADSEG);
}
else
{
ltadseg.len = imgseg_size;
wri_rec(ofd, rec_offs, (B*)<adseg, sizeof(TADSEG), NULL, NULL, 0);
rec_offs += sizeof(TADSEG);
}
imgseg = (IMAGESEG*)malloc(imgseg_size);
libimg_wri_seg(imgseg, cspec, dstcbmp, NULL, NULL);
wri_rec(ofd, rec_offs, (B*)imgseg, imgseg_size, NULL, NULL, 0);
free(imgseg);
rec_offs += imgseg_size;
}
}