www.imagemagick.orgからソースを入手できる.
debianなら
# apt-get -f install imagemagick
とすれば勝手にダウンロードしてインストールしてくれる.
なお現時点のバージョンは5.4.8.2であった.
ちなみにwindowsバイナリも上記サイトからダウンロードできる.詳しくは後述.
標準画像として有名なLena(lena_std.tif)をwww.lena.orgからダウンロードして使うことにする.
べつに他の画像でも全然問題ない.
拡張子をeps2, eps3にすると,それぞれlevel2, level3のpostscriptになる.level2, level3だと画像の圧縮ができるので,ラスタ画像をepsに変換したときなどに結構意味を持つ.
$ convert lena_std.tif lena_std.eps $ convert lena_std.tif lena_std.eps2 $ convert lena_std.tif lena_std.eps3 $ convert -compress ZIP lena_std.tif lena_std.zip.eps2 $ convert -compress ZIP lena_std.tif lena_std.zip.eps3
大きさを比較すると,表2.1.1[圧縮されたepsの大きさ]のようになる.
| オリジナルTIFF | 776KB |
| eps2(オプション無し) | 984KB |
| eps3(オプション無し) | 1304KB |
| eps2(オプション-compress ZIP) | 784KB |
| eps3(オプション-compress ZIP) | 784KB |
となった.(1)
IllustratorやTgifなどで描いたベクタ画像についても圧縮できた.
32000個の三角形を描画するepsファイルで試すと,1500KBから90KBになった.しかし
を考えると,
プレビュー画像を用意した上で圧縮した
のではなく,
単に低解像度のレンダリングに差し替えられてしまった
と考えるのが妥当か?
Jpeg2000を使うとロスレス圧縮が可能になる(ホントはJpegにもその規格はある).
これを使うには,まずjasperライブラリをインストールし,その後ImageMagickを再コンパイルする必要がある.
$ wget \
http://www.ece.uvic.ca/~mdadams/jasper/software/jasper-1.600.0.zip \
$ unzip jasper-1.600.0.zip
ソースを修正
困ったことに,オリジナルのソースでは一時ファイルの作成にtmpnam関数を使用している.これははっきり言ってマズイので,修正してしまう.なおこれは次のパッケージ作成パッチに含まれているので,パッケージを作るときには飛ばして構わない.
--- jasper-1.600.0.orig/src/libjasper/base/jas_stream.c
+++ jasper-1.600.0/src/libjasper/base/jas_stream.c
@@ -386,7 +386,7 @@
{
jas_stream_t *stream;
int *obj;
- char filename[L_tmpnam + 1];
+ char filename[14];
if (!(stream = jas_stream_create())) {
return 0;
@@ -404,11 +404,11 @@
stream->obj_ = obj;
/* Choose a file name. */
- tmpnam(filename);
+ snprintf( filename, sizeof(filename), "jasper_XXXXXX" );
/* Open the underlying file. */
- if ((*obj = open(filename, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | \
O_BINARY,
- JAS_STREAM_PERMS)) < 0) {
+ if((*obj = mkstemp(filename)))
+ {
jas_stream_destroy(stream);
return 0;
}
debパッケージ化
make & make installは気持ち悪いので,パッケージにする.ソースディレクトリで以下のパッチをあてる.
--- jasper-1.600.0.orig/src/libjasper/base/jas_stream.c
+++ jasper-1.600.0/src/libjasper/base/jas_stream.c
@@ -386,7 +386,7 @@
{
jas_stream_t *stream;
int *obj;
- char filename[L_tmpnam + 1];
+ char filename[14];
if (!(stream = jas_stream_create())) {
return 0;
@@ -404,11 +404,11 @@
stream->obj_ = obj;
/* Choose a file name. */
- tmpnam(filename);
+ snprintf( filename, sizeof(filename), "jasper_XXXXXX" );
/* Open the underlying file. */
- if ((*obj = open(filename, O_CREAT | O_EXCL | O_RDWR | O_TRUNC | \
O_BINARY,
- JAS_STREAM_PERMS)) < 0) {
+ if((*obj = mkstemp(filename)))
+ {
jas_stream_destroy(stream);
return 0;
}
--- jasper-1.600.0.orig/debian/README.debian
+++ jasper-1.600.0/debian/README.debian
@@ -0,0 +1,6 @@
+jasper for Debian
+----------------------
+
+Comments regarding the Package
+
+Shohei Nobuhara <>, Sat, 27 Apr 2002 17:06:55 +0900
--- jasper-1.600.0.orig/debian/changelog
+++ jasper-1.600.0/debian/changelog
@@ -0,0 +1,15 @@
+jasper (1.600.0-1) unstable; urgency=low
+
+ * new upstream
+
+ -- Shohei Nobuhara <> Wed, 6 Jan 2003 17:06:55 +0900
+
+jasper (1.500.4-1) unstable; urgency=low
+
+ * Initial release.
+
+ -- Shohei Nobuhara <> Sat, 27 Apr 2002 17:06:55 +0900
+
+Local variables:
+mode: debian-changelog
+End:
--- jasper-1.600.0.orig/debian/copyright
+++ jasper-1.600.0/debian/copyright
@@ -0,0 +1,8 @@
+This package was debianized by Shohei Nobuhara on
+Sat, 27 Apr 2002 17:06:55 +0900.
+
+It was downloaded from \
http://www.ece.uvic.ca/~mdadams/jasper/software/jasper-1.600.0.zip
+
+Copyright:
+
+Copyright 1999-2003 Michael D. Adams
+
--- jasper-1.600.0.orig/debian/dirs
+++ jasper-1.600.0/debian/dirs
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
--- jasper-1.600.0.orig/debian/control
+++ jasper-1.600.0/debian/control
@@ -0,0 +1,15 @@
+Source: jasper
+Section: unknown
+Priority: optional
+Maintainer: Shohei Nobuhara <>
+Standards-Version: 3.2.1
+
+Package: jasper
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: JPEG-2000 Part-1 standard (i.e., ISO/IEC 15444-1) codec \
library
+ JasPer is a software-based implementation of the codec specified in the
+ emerging JPEG-2000 Part-1 standard (i.e., ISO/IEC 15444-1).
+ The JasPer software is written in the C programming language.
+ .
+ see also http://www.ece.ubc.ca/~mdadams/jasper/
--- jasper-1.600.0.orig/debian/rules
+++ jasper-1.600.0/debian/rules
@@ -0,0 +1,50 @@
+#!/usr/bin/make -f
+# Made with the aid of debmake, by Christoph Lameter,
+# based on the sample debian/rules file for GNU hello by Ian Jackson.
+
+package=jasper
+
+build:
+ $(checkdir)
+ ./configure --prefix=/usr
+ $(MAKE) CFLAGS="-O2 -g -Wall"
+ touch build
+
+clean:
+ $(checkdir)
+ -rm -f build
+ -$(MAKE) distclean
+ -rm -f `find . -name "*~"`
+ -rm -rf debian/tmp debian/files* core debian/substvars
+
+binary-indep: checkroot build
+ $(checkdir)
+# There are no architecture-independent files to be uploaded
+# generated by this package. If there were any they would be
+# made here.
+
+binary-arch: checkroot build
+ $(checkdir)
+ -rm -rf debian/tmp
+ install -d debian/tmp
+ cd debian/tmp && install -d `cat ../dirs`
+ $(MAKE) install prefix=`pwd`/debian/tmp/usr
+# Must have debmake installed for this to work. Otherwise please copy
+# /usr/bin/debstd into the debian directory and change debstd to \
debian/debstd
+ debstd ChangeLog NEWS README
+ dpkg-gencontrol -isp
+ chown -R root.root debian/tmp
+ chmod -R go=rX debian/tmp
+ dpkg --build debian/tmp ..
+
+define checkdir
+ test -f debian/rules
+endef
+
+binary: binary-indep binary-arch
+
+checkroot:
+ $(checkdir)
+ test root = "`whoami`"
+
+.PHONY: binary binary-arch binary-indep clean checkroot
--- jasper-1.600.0.orig/debian/docs
+++ jasper-1.600.0/debian/docs
@@ -0,0 +1,2 @@
+doc/
+images/
パッチ後,
$ dpkg-buildpackage -us -uc -rfakeroot
として,できあがったパッケージをインストール.
そして次にImageMagickの再コンパイルを行う.
$ apt-get source imagemagick $ cd imagemagick-5.4.9.1 $ dpkg-buildpackage -us -uc -rfakeroot
できあがったパッケージをインストールして準備完了.
なおconfigure時にjasperを認識しない場合,
$ export CFLAGS=-I/usr/local/include $ export CXXFLAGS=-I/usr/local/include $ export LDFLAGS=-L/usr/local/lib $ ./configure
のように
どこにjasperがあるのか
をconfigure前に設定しておく必要があるかもしれない(これは/usr/local/以下の例).configureスクリプトを読めばわかることだが,要するに
#include <jasper/jasper.h>
というソース(test.c)をコンパイルできて,かつ
$ gcc test.c -ljasper
のように,libjasper.soがリンクできればどこにインストールしてあっても構わない.
こうしてできあがったimagemagickを使ってJpeg2000にするには
$ convert lena_std.tif lena.jp2
とし,特にロスレス圧縮であることを指定するには
$ convert -compress Lossless lena_std.tif lena.jp2
とする.
できあがったサイズを比較すると,表2.2.1[Jpeg2000のサイズ比較]のようになった.
| オリジナルTIFF | 776KB | |
| Jpeg(オプション無し) | 40KB | |
| Jpeg(-compress Lossless) | 212KB | 全然ロスレスではない! |
| Jpeg2000(オプション無し) | 440KB | デフォルトでLosslessっぽい.しかし画素値1のずれが数カ所起きる? |
| Jpeg2000(-compress Lossless) | 440KB | 画素値1のずれが数カ所起きる? |
画像の比較は,jasperに含まれるimgcmpを用いて
$ convert lena_std.tif lena_std.ppm $ imgcmp -f lena_std.ppm -F lena.jp2 -m pae
などとして行うことができる.また別の方法として,
$ convert +compress lena_std.tif lena_std.ppm $ convert +compress lena.jp2 lena_jp2.ppm $ diff lena_std.ppm lena_jp2.ppm
のように,P3形式(テキスト形式)に変換し,diffをとるというのもある.
当たり前のことだが,jasperを使って再コンパイルしたimagemagickのdisplayコマンドを使えば問題なく表示できる.
またwindowsではIrfanView (日本語版)に公式ページにあるプラグインを追加すれば表示できる.
importを使うとXの画面をキャプチャできる.
シンプルに
$ import
とするとマウスのカーソルが変化するので,取り込みたいウィンドウをクリックする.取り込み完了を示すbeepが鳴り,magick.miffができているはず.あとはこれをconvertで変換すればよい.
最初から出力ファイル名を指定することもできる.
$ import a.ppm
また画面全体をキャプチャするには,
$ import -window root
とする.
libmagickを使うと,自分のプログラムの中でImageMagickの機能を使うことができる.特に様々なフォーマットのファイル入出力は便利.
ファイル名を指定して画像をunsigned charの1次元配列として読み込むにはリスト4.1.1[読み込み関数]のようにする.
#include <magick/api.h>
/**
* たいていの画像を読み込んでしまう関数
*
* - 結果は unsigned char の1次元配列
* - 結果配列は使用者側で解放すること
* - 画素のフォーマットを colormap で指定する必要がある
* - colormap は R,G,B,A,C,Y,M,K,I の任意の組み合わせ
* - ふつう,PPM ファイルなら colormap = "RGB"
* - R だけほしければ colormap = "R" とすればよい
*
* @param filename [in] ファイル名
* @param width [out] 読み込んだ画像の横サイズ
* @param height [out] 読み込んだ画像の縦サイズ
* @param colormap [in] 取得する画素形式
* @return 成功したときは得られた1次元配列の先頭へのポインタを,失敗したときはNULLを返す
*/
unsigned char * magick_read(const char * filename, int * width, int * \
height, const char * colormap)
{
ExceptionInfo exception;
Image * image;
ImageInfo * image_info;
unsigned char * data;
int n_pixels;
int colors;
GetExceptionInfo(&exception);
image_info=CloneImageInfo((ImageInfo *)NULL);
strncpy(image_info->filename, filename, MaxTextExtent-1);
image=ReadImage(image_info, &exception);
if (image == (Image *)NULL)
{
MagickWarning(exception.severity,exception.reason,exception.description);
return NULL;
}
*width = image->columns;
*height = image->rows;
colors = strlen(colormap);
n_pixels = image->columns * image->rows;
data = (unsigned char *)malloc( n_pixels * (colors) * sizeof(unsigned \
char));
if( ! DispatchImage(image, 0, 0, *width, *height, colormap, CharPixel, \
(void *)(data), &exception) )
{
MagickWarning(exception.severity,exception.reason,exception.description);
return NULL;
}
DestroyImage(image);
DestroyImageInfo(image_info);
return data;
}
unsigned charの1次元配列として表された画像をファイルに保存するにはリスト4.2.1[書き込み関数]のようにする.
/**
* たいていの画像形式で書き込んでしまう関数
*
* - 渡すデータは unsigned char の1次元配列
* - 渡すデータのフォーマットを colormap で指定する必要がある
* - colormap は R,G,B,A,C,Y,M,K,I の任意の組み合わせ
* - R,G,B 8bit ずつのデータなら colormap = "RGB"
*
* @param filename [in] ファイル名
* @param data [in] 画像データ
* @param width [in] 画像の横サイズ
* @param height [in] 画像の縦サイズ
* @param colormap [in] 渡したデータの画素形式
* @return 成功したときは0を返す
*/
int magick_write(const char * filename, const unsigned char * data, int \
width, int height, const char * colormap)
{
Image * image;
ExceptionInfo exception;
ImageInfo * image_info;
CompressionType comp;
int quality;
comp = UndefinedCompression; /* ほかには LZWCompression など */
quality = 0;
GetExceptionInfo(&exception);
image_info=CloneImageInfo((ImageInfo *)NULL);
image = ConstituteImage( width, height, colormap, CharPixel, (const void \
*)data, &exception );
if (image == (Image *)NULL)
{
MagickWarning(exception.severity,exception.reason,exception.description);
return 1;
}
strncpy(image->filename, filename, MaxTextExtent-1);
if( quality > 0 && quality <= 100 )
{
image_info->quality = quality;
}
image->compression = comp;
image_info->compression = comp;
/*
* char で渡すので, 8 bits per color とする (デフォルトは16っぽい).
*
* if( ( (image_info->compression == NoCompression) || (image->depth > 8) ) \
) が,
* PNM で ASCII フォーマットになる条件らしい.
*
* see imagemagick/coders/pnm.c
*/
image->depth = 8;
if( 0 == WriteImage(image_info, image) )
{
MagickWarning(image->exception.severity,image->exception.reason,exception.description);
return 1;
}
DestroyImage(image);
DestroyImageInfo(image_info);
return 0;
}
CFLAGS += `Magick-config --cppflags` CXXFLAGS += `Magick-config --cppflags` LFLAGS += `Magick-config --ldflags --libs`
とする.
Windows版のimagemagickも,開発元からダウンロードできる.なおそのページに書いてあるように,Postscript関係のファイル(ps, eps, pdf)を扱うにはghostscriptが必要となる.ghostscriptのwindows版のインストールに関しては,TeX関係のページに詳しく記載されていることが多いので,そちらを参考のこと.
適当なミラーサイトを選択すると,binaries/ディレクトリの下に
のようにQ8とQ16,dllとstaticの計4つのバージョンが存在するので,自分に必要なものを選んでインストールする.
ここでQ8とQ16は,1チャネルのビット数を表し,たとえばQ8ではRGBそれぞれ8bitで扱う.通常の画像であればこれで全く問題ないが,PPMなどで48bit画像を使う場合などはQ16を使用する.またdllとstaticの違いは単にリンク方法が違うだけなので,特に理由がなければdllでかまわない.
なお開発元のページにはVC.netからlibmagickを使う方法が紹介されている.