猫の手ツール

Algorithm & UI/UX

ユークリッドの互除法と許容誤差を用いた「直感的なアスペクト比判定」の仕組み

本ツールでは、アップロードされた画像のピクセルサイズから、単なる除算結果だけでなく「4:3」や「16:9」といった人間が理解しやすい規格を導き出しています。その核となる計算処理と、ストレスのない入力UIを実現するための状態管理について解説します。

このツールの入力から出力まで

現行コードの確認日:

入力
画像の元寸法を読み取り、新しい幅または高さを入力します。
処理
最大公約数で簡約比を求め、片方の変更からもう片方を四捨五入で計算します。確認用プレビューと出力画像は別の寸法です。
出力
出力は指定寸法の JPEG(品質指定 0.95)です。

まず確認する点:1px単位の丸めで比率にわずかな差が出ます。各辺6000px以内・合計1600万画素以内という保存条件と元寸法表示を区別します。

仕上がりの例

縦横の比率を保ち、猫の写真を800×1066pxから600×800pxに縮小した例です。

加工前・加工後
左は緑のかぶりものを着けた愛猫の元写真。右は同じ構図と縦横比を保って縮小した写真。

加工前・加工後

左は緑のかぶりものを着けた愛猫の元写真。右は同じ構図と縦横比を保って縮小した写真。

掲載画像はサイトにある既存の公開作例です。保存済みの資料では運営者の愛猫の写真を使用しています。今回の確認日が、この作例を実行した日を表すわけではありません。

保存済み検証記録の条件を見る

資料の種類は「ツールの出力画像を保存した記録」です。公開作例と保存済み記録で素材や色などが異なる場合があるため、下の数値は保存済み検証記録の条件として読んでください。

記録の入力画像
800×1066px (JPEG)
記録の出力画像
600×800px (JPEG)
保存済み記録の主な操作・出力条件
画面の項目記録の値現行コードの初期値・範囲
記録の出力寸法600×800px—

資料ファイルの作成日は実行日として扱っていません。個別端末の処理速度や、ほかの写真に対する検出・加工の精度を測定した資料でもありません。

実装の確認箇所:src/pages/tool/aspect-ratio/index.astro。以下のコード抜粋と出力条件は、この本番実装に基づいて説明します。

仕組みを読み進めるときは、メモリ管理と画像処理(画素バッファ、縮小と容量予算)、Canvas APIと画像処理(画像寸法、drawImage、画素と透明度の扱い)が参考になります。

1. 最大公約数(GCD)による最小整数比の算出

画像サイズが「4000x3000」であっても、ユーザーが知りたいのは「4:3」という比率です。本実装では、ユークリッドの互除法を用いて横幅と高さの最大公約数を求め、それぞれの値をその公約数で割ることで、最小の整数比を算出しています。

ただし、デジタル写真ではごく稀に数ピクセルの誤差が含まれることがあります。そのため、簡約後の横の値が 50 を超えるケースは、あえて小数2桁の「横/縦 : 1」のような小数表記に切り替える処理を加え、情報の有用性を担保しています。

4000×3000 を 4:3 にする最大公約数の計算です。正の整数の幅と高さを渡します。

function reducedRatio(width, height) {
  let a = width, b = height;
  while (b !== 0) [a, b] = [b, a % b];
  return [width / a, height / a];
}

2. 許容誤差(Tolerance)を用いた規格マッチングアルゴリズム

世の中の画像には、厳密には「16:9」ではないものの、実質的にその規格として扱いたい画像が多く存在します。例えば、1ピクセルの計算誤差やトリミングミスがある場合です。

本ツールでは、各有名比率に対して「許容誤差(Tolerance)」を定義しています。計算されたアスペクト比と規格値の差分がこの閾値以内であれば「16:9 です」と断定的に表示する仕組みを採用し、UXを向上させています。

3. 循環更新を防ぐ「isUpdating」フラグによる双方向バインディング

「横幅を変えたら高さも変わる、高さを変えたら横幅も変わる」というリサイズ計算では、変更された側を基準にもう一方を計算します。

実装には更新中であることを示す内部フラグがあり、更新処理中の再入を避けるためのガードにしています。ただし通常の input.value 代入だけで input イベントが自動発火するわけではありません。これにより、計算機のスムーズな操作感を実現しています。

出力の仕様と確認する点

規格名は幅/高さと候補比率の差が許容値以内なら表示する近似判定です。「16:9 です」と表示されても完全一致とは限りません。厳密な確認には表示されるピクセル寸法と簡約比を使います。

幅を変えると元の比率から高さを、逆なら幅を計算し四捨五入します。1px 単位に丸めるため、変更後の比率が厳密に同じにならない場合があります。出力は指定寸法の JPEG(品質指定 0.95)です。

寸法表示と比率計算には読み込んだ画像の元の幅・高さを使います。確認用プレビューだけは長辺600px・36万画素以内へ縮小します。保存寸法は正の整数、各辺6000px以内、合計1600万画素以内という条件を満たす必要があります。この範囲でも端末のメモリにより失敗する場合があり、拡大しても元の写真の細部は増えません。