📷
画像処理100本ノックに挑戦|最近傍補間(025/100)
これはなに?
画像処理100本ノックを、TypeScriptとlibvipsで挑戦してみる記事の25本目です。
前回
実装
お題
最近傍補間により画像を1.5倍に拡大せよ。
最近傍補間(Nearest Neighbor)は画像の拡大時に最近傍にある画素をそのまま使う手法である。 シンプルで処理速度が速いが、画質の劣化は著しい。
次式で補間される。 I' ... 拡大後の画像、 I ... 拡大前の画像、a ... 拡大率、[ ] ... 四捨五入
https://github.com/minido/Gasyori100knock-1/tree/master/Question_21_30#q24-ガンマ補正
Coding
import sharp from 'sharp';
export async function nearestNeighbor(
inputPath: string,
outputPath: string,
scaleX: number = 1.5,
scaleY: number = 1.5
): Promise<void> {
try {
const image = await sharp(inputPath)
.raw()
.toBuffer({ resolveWithObject: true });
const { data, info } = image;
const { width, height, channels } = info;
// 新しいサイズを計算
const newWidth = Math.round(width * scaleX);
const newHeight = Math.round(height * scaleY);
const newData = Buffer.alloc(newWidth * newHeight * channels);
// 各ピクセルについて最近傍を計算
for (let y = 0; y < newHeight; y++) {
for (let x = 0; x < newWidth; x++) {
// 元の座標を計算
const srcX = Math.round(x / scaleX);
const srcY = Math.round(y / scaleY);
// 範囲内に収める
const origX = Math.min(width - 1, Math.max(0, srcX));
const origY = Math.min(height - 1, Math.max(0, srcY));
// 各チャネルをコピー
for (let c = 0; c < channels; c++) {
const origPos = (origY * width + origX) * channels + c;
const newPos = (y * newWidth + x) * channels + c;
newData[newPos] = data[origPos];
}
}
}
await sharp(newData, {
raw: {
width: newWidth,
height: newHeight,
channels
}
})
.toFile(outputPath);
console.log('最近傍補間による拡大が完了しました');
} catch (error) {
console.error('画像処理中にエラーが発生しました:', error);
throw error;
}
}
結果
入力 | 出力 |
---|---|
![]() |
![]() |
Discussion