久しぶりの投稿;
Demo: HTML5 Image Processing (Symmetric Nearest Neighbor)
(Firefox3.5とSafari4で動作確認しています)
HTML5でConvolutionFilterに続いて、簡単な画像処理を試してみます。
以前、ActionScriptで書いたSymmetric Nearest NeighborをJavaScriptで。
半径を大きくするとそれなりに絵画っぽくなってくれますが、やはり重いです;
・クライアント
1 2 3 4 |
var context = document.getElementById('Canvas').getContext('2d'); var bmp = new Bitmap('sample.jpg', context); var radius = 3; bmp.applyFilter(new SNNFilter(radius)); |
bitmap.js
(関係ある箇所だけ抜粋)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
var Class = { create : function() { var properties = arguments[0]; function self() { this.initialize.apply(this, arguments); } for(var i in properties) { self.prototype[i] = properties[i]; } if(!self.prototype.initialize) { self.prototype.initialize = function() {}; } return self; } }; var Bitmap = Class.create({ initialize : function(source, context) { this.bitmapData = new Image(); this.bitmapData.src = source; this.context = context; this.bitmapData.addEventListener('error', function() { alert("can't load image"); }, false); }, applyFilter : function(filter) { try { if(this.bitmapData.complete) { this.context.drawImage(this.bitmapData, 0, 0); var w = this.bitmapData.width, h = this.bitmapData.height; var src = this.context.getImageData(0, 0, w, h); var dst = this.context.createImageData(w, h); filter.apply(src, dst); this.context.putImageData(dst, 0, 0); }else { throw new Error("load image incomplete"); } }catch(e) { throw e; } } }); var SNNFilter = Class.create({ initialize : function(radius) { this.radius = radius; }, apply : function(src, dst) { var w = src.width, h = src.height; var srcData = src.data; var dstData = dst.data; var sumR, sumG, sumB; var rc, gc, bc, r1, g1, b1, r2, g2, b2; var cnt = 0; var xyPos, uvPos; for(var y=0;y<h;++y) { for(var x=0;x<w;++x) { xyPos = (w*y + x) << 2; sumR = 0, sumG = 0, sumB = 0; cnt = 0; rc = srcData[xyPos]; gc = srcData[xyPos + 1]; bc = srcData[xyPos + 2]; for(var v=-this.radius;v<=this.radius;++v) { for(var u=-this.radius;u<=this.radius;++u,++cnt) { uvPos = (w*v + u) << 2; try { r1 = srcData[xyPos + uvPos]; g1 = srcData[xyPos + uvPos + 1]; b1 = srcData[xyPos + uvPos + 2]; r2 = srcData[xyPos - uvPos]; g2 = srcData[xyPos - uvPos + 1]; b2 = srcData[xyPos - uvPos + 2]; }catch(e) { break; } if(this.delta.apply(this, [rc, gc, bc, r1, g1, b1]) < this.delta.apply(this, [rc, gc, bc, r2, g2, b2])) { sumR += r1; sumG += g1; sumB += b2; }else { sumR += r2; sumG += g2; sumB += b2; } } } dstData[xyPos] = sumR/cnt; dstData[xyPos + 1] = sumG/cnt; dstData[xyPos + 2] = sumB/cnt; dstData[xyPos + 3] = 255; } } }, delta : function(rc, gc, bc, r1, g1, b1) { return Math.sqrt((rc - r1)*(rc - r1) + (gc - g1)*(gc - g1) + (bc - b1)*(bc - b1)); } }); |
最近、HTML5とFlashの話題が盛んですね。
これまでは 主に canvas を利用したものしか試してないんですが、
業務で動画配信に携わっているので video に関することも調査中です。
技術の外側でH.264/Theoraを巡る政治的な争いを見守りつつ、
来年度からのスタートに出遅れないように今の内にしっかり勉強しておきたいです。
・関連記事
Symmetric Nearest Neighbor – Rest Term
HTML5の勉強 – Rest Term
One thought