あるプログラムを書いていて、
指定の枠(mm)に、指定の解像度(dpi)で
ヨコ幅(pt)、タテ幅(pt)のサイズがわかっている画像を置く場合、
その画像に必要な解像度(dpi)が知りたい
これを計算してくれる関数を、 javascript で作りたい。
画像の縦幅と横幅、どちらを比較するか?
これは、画像枠と画像の比率を比較してフラグにすればいいので
var frameMmW = 80; // 枠ヨコ幅
var frameMmH = 60; // 枠タテ幅
var imagePtW = 142; // 画像ヨコ幅
var imagePtH = 64; // 画像タテ幅
とすると、
// 画像の[横/縦]が枠の[横/縦]より大きければ、横幅を使用する
var useWidth = (imagePtW / imagePtH >= frameMmW / frameMmH);
みたいな感じに書ける。
ちょっと RunJS を使って試してみる。
RunJS - A playground for JavaScript and TypeScript
試しに、画像のヨコ幅とタテ幅を変えてみると、
画像枠にタテを合わせたいサイズでちゃんと false
になる。
mm と pt を inch に再計算する
単位 mm
と pt
だと比較しづらい。
dpi
は dot per inch
なので、それぞれ inch
に直す。
72ポイント = 1インチ = 25.4ミリ だから……。
var unitToInch = function (size, unit) {
var perUnit = {
'in': 1,
'pt': 72,
'mm': 25.4
};
return size / perUnit[unit];
}
var frameInW = unitToInch(frameMmW, 'mm');
var frameInH = unitToInch(frameMmH, 'mm');
var imageInW = unitToInch(imagePtW, 'pt');
var imageInH = unitToInch(imagePtH, 'pt');
Adobe のソフトで見ても、上手く計算できているように見える。
画像の解像度を出す
さて、画像の解像度を出すとして、
dpi
は dot per inch
だから
ピクセル数 ÷ 幅(inch) = 解像度 (dpi)
ということは
枠のピクセル数 ÷ 枠のサイズ(inch) = 枠の解像度 (dpi)
画像のピクセル数 ÷ 画像のサイズ(inch) = 画像の解像度 (dpi)
で、 二次連立方程式 の形になる。
枠のピクセル数 = 画像のピクセル数
となるようにしたいわけだから、
画像or枠のピクセル数 ÷ 枠のサイズ(inch) = 枠の解像度 (dpi)
画像or枠のピクセル数 ÷ 画像のサイズ(inch) = 画像の解像度 (dpi)
ええと、両辺にサイズをかけて
画像or枠のピクセル数 = 枠の解像度 (dpi) × 枠のサイズ(inch)
画像or枠のピクセル数 = 画像の解像度 (dpi) × 画像のサイズ(inch)
左辺が同じになったから、下を左辺に、上を右辺にして
画像の解像度 (dpi) × 画像のサイズ(inch)= 枠の解像度 (dpi) × 枠のサイズ(inch)
欲しいのは画像の解像度だから、両辺を画像のサイズで割れば
画像の解像度 (dpi) = 枠の解像度 (dpi) × 枠のサイズ(inch)÷ 画像のサイズ (inch)
できた。これを関数に落とし込む。
var getImageDpi = function getImageDpi(frameDpi, frameInchSize, imageInchSize) {
return frameDpi * frameInchSize / imageInchSize;
}
えっこんな簡単な計算?
試してみる。
/**
* 他の単位のサイズをインチに直す
* @param {number} size - サイズ
* @param {string} unit - 単位(in,pt,mm)
* @return {number} - インチサイズ
*/
var unitToInch = function (size, unit) {
var perUnit = {
'in': 1,
'pt': 72,
'mm': 25.4
};
return size / perUnit[unit];
}
/**
* 画像のdpiを計算する
* @param {number} frameDpi - 枠の解像度 (dpi)
* @param {number} frameInchSize - 枠のサイズ (inch)
* @param {number} imageInchSize - 画像のサイズ (inch)
* @return {number} - 画像の解像度 (dpi)
*/
var getImageDpi = function getImageDpi(frameDpi, frameInchSize, imageInchSize) {
return frameDpi * frameInchSize / imageInchSize;
}
var frameDpi = 300; // 枠の解像度
var frameMmW = 80; // 枠ヨコ幅
var frameMmH = 60; // 枠タテ幅
var imagePtW = 142; // 画像ヨコ幅
var imagePtH = 64; // 画像タテ幅
// 幅と高さどちらを使うか
var useWidth = (imagePtW / imagePtH >= frameMmW / frameMmH);
// 枠のinchサイズ
var frameInchSize = unitToInch((useWidth? frameMmW: frameMmH), 'mm');
// 画像のinchサイズ
var imageInchSize = unitToInch((useWidth? imagePtW: imagePtH), 'pt');
// 画像の解像度
var imageDpi = getImageDpi(frameDpi,frameInchSize,imageInchSize);
console.log('imageDpi: ' + imageDpi);
約 479dpi と出た。
Photoshopで画像を開けて、解像度を479dpiで再サンプル実行
保存後、再サンプルなしで、幅を80mmに変えてみる。
ピクセル数が変わるのでぴったりとはいかないが、
だいたいOKみたい。
まとめ
こんな感じで連立方程式を解く感じで、
自分が欲しい機能の関数を書くことができます。
自分の場合、どうしても欲しい関数が(あちこちググっても)見つからない場合、
- 公式をググる
- 現状取れるパラメータを、公式にあてはめて方程式を作る
- 欲しいパラメータが左辺に来るように式を解く
- 関数に落とし込む
とかもやります。アフィン変換系とか。
以上、プログラムと連立方程式の話でした。