SDL_image を用いて画像ファイルを読み込むサンプルプログラム(Ubuntu 上)
SDL_image は,BMP, JPEG, PNG, PNM などの画像ファイルを読み書きする機能を持ったライブラリ.現在の版は SDL2 用の SDL2_image である.
このページでは,SDL2_image を用いて画像ファイルを読み込み,各画素の R, G, B 値を表示するプログラムを示す.
前準備
Ubuntu のシステム更新
Ubuntu で OS のシステム更新を行うときは, 端末で,次のコマンドを実行する。これは、パッケージ情報を最新の状態に保ち、インストール済みのパッケージをセキュリティアップデートやバグ修正を含めて更新するためである。
# パッケージリストの情報を更新
sudo apt update
# インストール済みのパッケージを包括的に更新 (依存関係も考慮)
sudo apt full-upgrade
# カーネル更新等で実際に再起動が必要な場合のみ実行を推奨
# sudo shutdown -r now
C/C++ コンパイラー,pkg-config のインストール
端末で,次のコマンドを実行する.
# パッケージリストの情報を更新
sudo apt update
sudo apt -y install build-essential pkg-config
SDL2, SDL2_image のインストール(Ubuntu 上)
端末で,次のコマンドを実行する. -dev の付いたパッケージには,コンパイルに必要なヘッダファイルと pkg-config 用の設定ファイルが含まれる.
# パッケージリストの情報を更新
sudo apt update
sudo apt -y install libsdl2-dev libsdl2-image-dev
プログラム例
画像ファイルにはヘッダが付いており,圧縮されていることも多い.また,画像ファイルの形式は複数ある. SDL2_image の IMG_Load を使うと,ファイル形式の判別,ヘッダの解析,展開の処理を自分で書く必要がない.
IMG_Load が返す SDL_Surface の画素形式は,読み込んだファイルによって異なる(パレット形式,1画素4バイト,B, G, R の順など). そこで,次のプログラムでは SDL_ConvertSurfaceFormat により SDL_PIXELFORMAT_RGB24(1画素3バイト,R, G, B の順)へ変換し,画素の並びを一定にしている.
1行分のデータの後ろには詰め物(パディング)が入ることがあるため,行の先頭アドレスは幅 w ではなく pitch(1行あたりのバイト数)を用いて求める.
/* SDL2, SDL2_image を用いた画像ファイル読み込みのサンプルプログラム */
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
int main(int argc, char *argv[])
{
SDL_Surface *image;
SDL_Surface *rgb;
int i, j;
/* コマンドラインの確認 */
if (argc < 2) {
fprintf(stderr, "Usage: %s <image_file>\n", argv[0]);
return 1;
}
/* 画像ファイルの読み込み.ファイル形式は内容から判別される */
image = IMG_Load(argv[1]);
if (image == NULL) {
fprintf(stderr, "Couldn't load %s: %s\n", argv[1], SDL_GetError());
return 1;
}
/* 1画素3バイト,R, G, B の順の形式に変換 */
rgb = SDL_ConvertSurfaceFormat(image, SDL_PIXELFORMAT_RGB24, 0);
SDL_FreeSurface(image);
if (rgb == NULL) {
fprintf(stderr, "SDL_ConvertSurfaceFormat failed: %s\n", SDL_GetError());
return 1;
}
fprintf(stderr, "w = %d, h = %d, pitch = %d, BytesPerPixel = %d\n",
rgb->w, rgb->h, rgb->pitch, rgb->format->BytesPerPixel);
for (i = 0; i < rgb->h; i++) {
/* 行の先頭アドレスは pitch (1行のバイト数) から求める */
unsigned char *row = (unsigned char *)rgb->pixels + (size_t)i * rgb->pitch;
for (j = 0; j < rgb->w; j++) {
int r = row[j * 3];
int g = row[j * 3 + 1];
int b = row[j * 3 + 2];
printf("%d, %d = (%d, %d, %d)\n", i, j, r, g, b);
}
}
SDL_FreeSurface(rgb);
SDL_Quit();
return 0;
}
ビルド手順
view.c のところは実際のファイル名に読み替えること. コンパイルオプションとリンクするライブラリは pkg-config で取得する.
gcc -o view view.c $(pkg-config --cflags --libs sdl2 SDL2_image)
実行
画素ごとに1行を出力するため,出力行数は「幅×高さ」になる. 出力を確認するときは,ファイルへリダイレクトするか head と組み合わせる.
./view sample.png | head -n 20