LoginSignup
0
0

More than 3 years have passed since last update.

連立方程式を使ってプログラムを書く話

Last updated at Posted at 2020-11-01

あるプログラムを書いていて、

指定の枠(mm)に、指定の解像度(dpi)で
ヨコ幅(pt)、タテ幅(pt)のサイズがわかっている画像を置く場合、
その画像に必要な解像度(dpi)が知りたい

ということがあった。
ss_2020-11-01_11_07_31.png

これを計算してくれる関数を、 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

ss 2020-11-01 11.29.14.png

試しに、画像のヨコ幅とタテ幅を変えてみると、
画像枠にタテを合わせたいサイズでちゃんと false になる。

ss 2020-11-01 11.33.06.png

mm と pt を inch に再計算する

単位 mmpt だと比較しづらい。
dpidot 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');

ss 2020-11-01 12.09.10.png

Adobe のソフトで見ても、上手く計算できているように見える。

ss 2020-11-01 12.08.01.png

画像の解像度を出す

さて、画像の解像度を出すとして、

dpidot 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);

ss 2020-11-01 12.50.13.png

479dpi と出た。
Photoshopで画像を開けて、解像度を479dpiで再サンプル実行

ss_2020-11-01_13_13_54.png

保存後、再サンプルなしで、幅を80mmに変えてみる。

ss_2020-11-01_13_15_52.png

ピクセル数が変わるのでぴったりとはいかないが、
だいたいOKみたい。

まとめ

こんな感じで連立方程式を解く感じで、
自分が欲しい機能の関数を書くことができます。

自分の場合、どうしても欲しい関数が(あちこちググっても)見つからない場合、

  1. 公式をググる
  2. 現状取れるパラメータを、公式にあてはめて方程式を作る
  3. 欲しいパラメータが左辺に来るように式を解く
  4. 関数に落とし込む

とかもやります。アフィン変換系とか。

以上、プログラムと連立方程式の話でした。

0
0
0

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
0
0