LoginSignup
10

ImageMagick の Geometry 仕様

Last updated at Posted at 2019-11-25

はじめに

引数で 640x480+200+100 のようにサイズや位置を指定する記法を ImageMagick では Image Geometry と呼びます。この記事では主にリサイズでの使い方を例にして紹介します。

% convert rose: rose.png
% identify rose.png
rose.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
% convert rose.png -resize 100x100 rose-resized.png
% identify rose-resized.png
rose-resized.png PNG 100x66 100x66+0+0 8-bit sRGB 11687B 0.000u 0:00.000
rose.png rose-resized.png
rose.png (70x46) rose-resized.png (100x66)

ImageMagick 初心者がはじめに引っかかるであろう -resize 100x100 を指定したのに出力画像が 100x100 サイズにならない現象を解決するヒントにもなるかもしれません。

Geometry と合わせて指定する事の多い Gravity は別エントリにしました。

あと、ついでにリサイズの詳細はこちらです。

Geometry の概要

以下の指定ができます。

  • サイズ/面積/アスペクト比(←縦横比)
  • オフセット
  • リサイズ前後でアスペクト比が変わる場合に、どう対応するか
  • その他、オプションによっては独自

画像をリサイズする際に、アスペクト比が変わると見た目が変わってしまうので、基本はアスペクト維持で動作するものだと考えると分かりやすいです。
アスペクト比無視での変換は例外的な使い方になります。

general description

公式ドキュメントの表の順番で解説します。

size General description (実際の動作はオプションや設定によって変わり得ます)
scale% 縦幅(height)横幅(width)まとめてパーセント指定.
scale-x%xscale-y% 縦幅(height)と横幅(width)を別々にパーセント指定。アスペクト比は維持しない
width 横幅(width)を指定。縦幅(height)はアスペクト比を保つよう自動で決まる
xheight 縦幅(height)を指定。横幅(width)はアスペクト比を保つよう自動で決まる
widthxheight 縦幅(height)と横幅(width)の最大値を指定する。アスペクト比は保つ
widthxheight^ 縦幅(height)と横幅(width)の最小値を指定する。アスペクト比は保つ
widthxheight! 縦幅(height)と横幅(width)ズバリのサイズになる。アスペクト比は維持しない
widthxheight> 横幅(width) と縦幅(height) の引数よりも画像の大きい方を縮小する
widthxheight< 横幅(width) と縦幅(height) の引数よりも画像の小さい方を拡大する
area@ 指定した面積になるようリサイズする。幅(height)と横幅(width)の最小値を指定する。アスペクト比は保つ
x:y x と y はアスペクト比を表す (例 3:2 = 1.5).
x:y^ 指定したアスペクト比になるよう行または列を削る (外接クリップ)
x:y# 指定したアスペクト比になるよう行または列を足す (内接マージン) (2021年11月13日 7.1.0-14 追加)
{size}{offset} オフセットの指定 (デフォルトは +0+0). {size} は上記の形式に従う
{size}{+-}x{+-}y ピクセル中の横方向と縦方向のオフセット x と y 、両方共 +- 符号が必要. オフセットは -gravity 設定に影響される。% やその他 size の演算子は影響しない。

scale%

縦幅(height)横幅(width)まとめてパーセント指定します。要するに倍率指定です。

% convert rose: rose.png
% convert rose: -resize 200% rose-200p.png
% convert rose: -resize 50% rose-50p.png
% identify rose.png rose-200percent.png rose-50percent.png
rose.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
rose-200p.png PNG 140x92 140x92+0+0 8-bit sRGB 19686B 0.000u 0:00.000
rose-50p.png PNG 35x23 35x23+0+0 8-bit sRGB 2213B 0.000u 0:00.009
rose.png 200% 50%
rose.png (70x46) rose-200p.png (140x92) rose-50p.png (35x23)

scale-x%xscale-y%

縦幅(height)と横幅(width)を別々にパーセント指定

% convert rose.png -resize 200%x300% rose-200px300p.png
% identify rose.png rose-200px300p.png
rose.png PNG 70x46 70x46+0+0 8-bit Gray 4c 502B 0.000u 0:00.000
rose-200px300p.png PNG 140x138 140x138+0+0 8-bit Gray 256c 4287B 0.000u 0:00.000
rose.png 200%x300%
rose.png (70x46) rose-200px300p.png (140x138)

width

横幅(width)を指定。縦幅(height)はアスペクト比を保つよう自動で決まる

% convert rose.png -resize 200 rose-200.png
% identify  rose-200.png
rose-200.png PNG 200x131 200x131+0+0 8-bit sRGB 34012B 0.000u 0:00.000
rose.png 200
rose.png (70x46) rose-200.png (200x131)

xheight

縦幅(height)を指定。横幅(width)はアスペクト比を保つよう自動で決まる。尚、x〜% のようにパーセント単位だと縦だけ伸ばす。

% convert rose.png -resize x200 rose-x200.png
% identify  rose-x200.png
rose-x200.png PNG 304x200 304x200+0+0 8-bit sRGB 63862B 0.000u 0:00.000
rose.png x200
rose.png (70x46) rose-x200.png(302x200)

widthxheight

縦幅(height)と横幅(width)の最大値を指定する。アスペクト比は保つ

% convert rose.png -resize 200x200 rose-200x200.png
% identify  rose-200x200.png
rose-200x200.png PNG 200x131 200x131+0+0 8-bit sRGB 34012B 0.000u 0:00.000
rose.png 200x200
rose.png (70x46) rose-200x200.png (200x131)

widthxheight^

縦幅(height)と横幅(width)の最小値を指定する。アスペクト比は保つ。

% convert rose.png -resize 200x200^ rose-200x200min.png
% identify rose-200x200min.png
rose-200x200min.png PNG 304x200 304x200+0+0 8-bit sRGB 63862B 0.000u 0:00.000
rose.png 200x200^
rose.png (70x46) rose-200x200min.png (304x200)

widthxheight!

縦幅(height)と横幅(width)ズバリのサイズになる。アスペクト比は維持しない。

% convert rose.png -resize '200x200!' rose-200x200fix.png
% identify  rose-200x200fix.png
rose-200x200fix.png PNG 200x200 200x200+0+0 8-bit sRGB 46490B 0.000u 0:00.000
rose.png '200x200!'
rose.png (70x46) rose-200x200fix.png (200x200)

widthxheight>

横幅(width) と縦幅(height) の引数よりも画像の大きい方を縮小する。
要するに、拡大はしない。縮小のみ実行してかつアスペクト比を保つ指定です。

% convert rose.png -resize '100x100>' rose-100x100gt.png
% convert rose.png -resize '50x50>' rose-50x50gt.png
% convert rose.png -resize '80x40>' rose-80x40gt.png
% convert rose.png -resize '20x20>' rose-20x20gt.png
% identify rose-100x100gt.png rose-50x50gt.png rose-80x40gt.png rose-20x20gt.png
rose-100x100gt.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
rose-50x50gt.png PNG 50x33 50x33+0+0 8-bit sRGB 3976B 0.000u 0:00.000
rose-80x40gt.png PNG 61x40 61x40+0+0 8-bit sRGB 5531B 0.000u 0:00.000
rose-20x20gt.png PNG 20x13 20x13+0+0 8-bit sRGB 256c 1311B 0.000u 0:00.000
rose.png '100x100>' '50x50>' '80x40>' '20x20>'
rose.png (70x46) rose-100x100gt.png (70x46) rose-50x50gt.png (50x33) rose-80x40gt.png (61x40) rose-20x20gt.png (20x13)

widthxheight<

横幅(width) と縦幅(height) の引数よりも画像の小さい方を拡大する。
要するに、縮小はしない。拡大だけ実行してかつアスペクト比を保つ指定です。

% convert rose.png -resize '100x100<' rose-100x100lt.png
% convert rose.png -resize '50x50<' rose-50x50lt.png
% convert rose.png -resize '20x20<' rose-20x20lt.png
% identify rose-100x100lt.png rose-50x50lt.png rose-40x40lt.png rose-20x20lt.png
rose-100x100lt.png PNG 100x66 100x66+0+0 8-bit sRGB 11687B 0.000u 0:00.000
rose-50x50lt.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
rose-40x40lt.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
rose-20x20lt.png PNG 70x46 70x46+0+0 8-bit sRGB 6975B 0.000u 0:00.000
rose.png '100x100<' '50x50<' '40x40<'
rose.png (70x46) rose-100x100lt.png (100x66) rose-50x50lt.png (70x46) rose-40x40lt.png (70x46)

area@

指定した面積になるようリサイズする。幅(height)と横幅(width)の最小値を指定する。アスペクト比は保つ

% convert rose.png -resize 10000@  rose-10000a.png
% convert rose.png -resize 100@ rose-100a.png
% identify  rose-10000a.png rose-100a.png
rose-10000a.png PNG 123x81 123x81+0+0 8-bit sRGB 16147B 0.000u 0:00.000
rose-100a.png PNG 12x8 12x8+0+0 8-bit sRGB 97c 662B 0.000u 0:00.000
rose.png 10000@ 100@
rose.png (70x46) rose-10000a.png (123x81) rose-100a.png (12x8)
123 x 81 = 9963 (<= 10000)
12 x 8 = 96     (<=100)

指定した面積か、面積を超えないギリギリのサイズで拡大縮小します。

x:y

アスペクト比を変更する。

% convert rose.png -resize 1:1 rose-1-1.png
% convert rose.png -resize 2:1 rose-2-1.png
% identify  rose-1-1.png rose-2-1.png
rose-1-1.png PNG 46x46 46x46+0+0 8-bit sRGB 4868B 0.000u 0:00.000
rose-2-1.png PNG 70x35 70x35+0+0 8-bit sRGB 5548B 0.000u 0:00.000
rose.png 1:1 2:1
rose.png (70x46) rose-1-1.png (46x46) rose-2-1.png (70x35)
46:46 = 1:1
70:35 = 2:1

元の大きさを超えないよう基準の尺を選ぶようです。

{size}{offset}

オフセットの指定 (デフォルトは +0+0). 以下の {size} は上記の形式に従う

offset の記法は {+-}x{+-}y です。{size}{+-}x{+-}y の項に説明を譲ります。

{size}{+-}x{+-}y

ピクセル中の横方向と縦方向のオフセット x と y 、両方共 +- 符号が必要. オフセットは -gravity 設定に影響される。% やその他 size の演算子は影響しない。

region 指定の例です。特定の場所にエフェクトをかけられます。

% convert rose.png -region 40x20+20+15 -negate  rose-negate.png
% convert rose.png -region 40x20+20+15 -modulate 120,100,240 rose-modulate.png
rose.png -negate -modulate 120,100,240
rose.png rose-negate.png rose-modulate.png

尚、この offset は gravity 指定の影響を受けます。

% convert rose.png -gravity center -region 40x20 -negate  rose-nagate-center.png
% convert rose.png -gravity center -region 40x20+10+10 -negate  rose-nagate-center+10+10.png
rose.png -negate -modulate 120,100,240
rose.png rose-nagate-center.png rose-nagate-center+10+10.png

Gravity との関連は以下のエントリをご参照ください。

ソースコード

Geometry 文字列のパース関数は MagickCore/geometry.c 内に2つあります。

ParseRegionGeometry

Geometry 文字列を width, height, x, y に分解するのに加えて、>, < @ 等の修飾からフラグを得る関数です。

MagickCore/geometry.c
MagickExport MagickStatusType ParseRegionGeometry(const Image *image,
  const char *geometry,RectangleInfo *region_info,ExceptionInfo *exception)
{
  MagickStatusType
    flags;

  SetGeometry(image,region_info);
  flags=ParseMetaGeometry(geometry,&region_info->x,&region_info->y,
    &region_info->width,&region_info->height);
  if (flags == NoValue)
    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
      "InvalidGeometry","`%s'",geometry);
  return(flags);
}

この通り、実質的な処理は ParseMetaGeometry 任せです。>, < @ 等の修飾からフラグに応じて、x, y, width, height を確定させるお仕事をします。

MagickCore/geometry.c
MagickExport MagickStatusType ParseMetaGeometry(const char *geometry,ssize_t *x\
,
  ssize_t *y,size_t *width,size_t *height)
<>
  flags=GetGeometry(geometry,x,y,width,height);
  if ((flags & PercentValue) != 0)
    {
      MagickStatusType
        percent_flags;

      PointInfo
        scale;

      /*
        Geometry is a percentage of the image size.
      */
      percent_flags=ParseGeometry(geometry,&geometry_info);
      scale.x=geometry_info.rho;
<略>
  if ((flags & AspectRatioValue) != 0)
    {
      double
        geometry_ratio,
        image_ratio;

      /*
        Geometry is a relative to image size and aspect ratio.
      */
      (void) ParseGeometry(geometry,&geometry_info);
      geometry_ratio=geometry_info.rho;
      image_ratio=(double) former_width*

そして、文字列の分解はGetGeometry 関数です。x, y, width, height や >, < @ 等のフラグを拾い出します。

MagickCore/geometry.c
MagickExport MagickStatusType GetGeometry(const char *geometry,ssize_t *x,
  ssize_t *y,size_t *width,size_t *height)
<略>
  for (p=pedantic_geometry; *p != '\0'; )
  {
    if (isspace((int) ((unsigned char) *p)) != 0)
      {
        (void) CopyMagickString(p,p+1,MagickPathExtent);
        continue;
      }
    c=(int)*p;
    switch (c)
    {
      case '%':
      {
        flags|=PercentValue;
        (void) CopyMagickString(p,p+1,MagickPathExtent);
        break;

ParseGeometry

ユーザ的に Geometry と言えるか微妙ですが "," で区切ったより汎用的に使える書式も内部では Geometry と呼びます。
Geometry 文字列を rho(ロー、ρ), sigma(シグマ、σ) xi(クサイ、ξ), psi(プサイ、ψ), chi(カイ、χ) の5つの変数に分離します。

MagickCore/geometry.c
MagickExport MagickStatusType ParseGeometry(const char *geometry,
  GeometryInfo *geometry_info)
<略>
  c=sscanf(geometry,"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf",&coordinate.rho,
    &coordinate.sigma,&coordinate.xi,&coordinate.psi);
  if (c == 4)
    {
      /*
        Special case: coordinate (e.g. 0,0 255,255).
      */
      geometry_info->rho=coordinate.rho;
      geometry_info->sigma=coordinate.sigma;
      geometry_info->xi=coordinate.xi;
      geometry_info->psi=coordinate.psi;
      flags|=RhoValue | SigmaValue | XiValue | PsiValue;
      return(flags);
    }

例えば、-modulate ,, といったオプションは以下のように処理します。

MagickCore/enhance
  flags=ParseGeometry(modulate,&geometry_info);
  percent_brightness=geometry_info.rho;
  percent_saturation=geometry_info.sigma;
  if ((flags & SigmaValue) == 0)
    percent_saturation=100.0;
  percent_hue=geometry_info.xi;
  if ((flags & XiValue) == 0)
    percent_hue=100.0;

X11 (X Window system) の影響

UNIX 系の GUI システムのベースになる X Window System (以下X11 と呼ぶ) というものがありまして(今も勿論ある)。
実は ImageMagick 3 まで X11 ライブラリの XParseGeometry を使っていました。つまり、ImageMagick の Geometry 記法の元は X11 です。

% man XParseGeometry
XParseGeometry(3)               XLIB FUNCTIONS               

NAME
       XParseGeometry, XWMGeometry - parse window geometry
(略)
       [=][<width>{xX}<height>][{+-}<xoffset>{+-}<yoffset>]

ImageMagick 4 から ParseGeometry を自前実装して、convert,mogrify等の X11 を使わないコマンドはそちらを使うようになっています。(X11 を使うコマンド例: display, animate, import)

Canvas と Page

% identify crop.png
crop.png PNG 200x200 640x480+100+100 8-bit sRGB 183c 4344B 0.000u 0:00.000

上記のように画像に関するサイズが2種類表示される件は、 Geometry 解説から逸脱する為、別エントリにしました。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10