CanvasのdrawImageで画像の縮小を行なう際に、一気にサイズを小さくするとジャギーがひどいことになってしまうことがあったので、段階的に小さくしていくためのClassをつくりました。
インターフェイスとしては、
var obj = SmoothResize.resize(img, zoom);
という感じで、画像と倍率を渡すと、オブジェクトが同期的に返ってくる感じとなっており、
オブジェクトの中身は、
{ elm : _elm, // canvas width : _elm.width, // canvasの幅 height : _elm.height // canvasの高さ };
という感じです。
いまとなっては、canvasをそのまま返しても良かった気がしています。
Javascript
// 画像をギザつかせずにリサイズする class SmoothResize { // 変数節約のために引数を実際よりも多めに取る static resize(img, zoom, _elm, _ctx, _elm2, _elm2Ctx, _zoom) { _elm = doc.createElement("canvas"); _elm2 = doc.createElement("canvas"); _ctx = _elm.getContext("2d"); _elm2Ctx = _elm2.getContext("2d"); _zoom = 1; if (zoom >= 1) { _elm.width = img.width * zoom; _elm.height = img.height * zoom; _ctx.drawImage(img, 0, 0, _elm.width, _elm.height); } else { _elm.width = img.width; _elm.height = img.height; _ctx.drawImage(img, 0, 0); while (_zoom > zoom) { _zoom /= 2; if (_zoom / 2 < zoom) { _zoom = zoom; } _elm2.width = img.width * _zoom; _elm2.height = img.height * _zoom; _elm2Ctx.drawImage(_elm, 0, 0, _elm2.width, _elm2.height); _elm.width = _elm2.width; _elm.height = _elm2.height; _ctx.drawImage(_elm2, 0, 0, _elm.width, _elm.height); } _elm.width = img.width * zoom; _elm.height = img.height * zoom; _ctx.drawImage(_elm2, 0, 0, _elm.width, _elm.height); } return { elm : _elm, width : _elm.width, height : _elm.height }; } }
変数を節約するところ以外はかなり愚直に書きました。
DEMO
左が普通に縮小したとき、右が段階的に縮小した時です。
若干きれいに縮小できています。
JavaScript
var img = new Image(), zoom = 0.05; img.onload = () => { (() => { // 普通に縮小 var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d"); canvas.width = img.width * zoom; canvas.height = img.height * zoom; ctx.drawImage(img, 0, 0, img.width * zoom, img.height * zoom); })(); (() => { // 段階的に縮小 var obj = SmoothResize.resize(img, zoom); doc.body.appendChild(obj.elm); })(); }; img.src = "https://dl.dropboxusercontent.com/u/325592/IMG_0029.JPG";