Skip to content

Instantly share code, notes, and snippets.

@rsky
Created July 11, 2010 08:15
Show Gist options
  • Save rsky/471390 to your computer and use it in GitHub Desktop.
Save rsky/471390 to your computer and use it in GitHub Desktop.
HTML5 Canvasで画像をモザイク化してみた
body {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 14px;
line-height: 100%;
background-color: #fff;
color: #000;
}
form#ctl {
position: relative;
margin: 0;
padding: 24px 10px 10px 10px;
height: 25px;
background-color: #eee;
border-bottom: #000 solid 1px;
}
span#idc {
position: absolute;
top: 10px;
font-family: monospace;
font-weight: bold;
}
input#siz {
position: relative;
width: 120px;
vertical-align: middle;
}
span.num {
display: inline-block;
vertical-align: middle;
}
div#drp {
position: absolute;
top: 0;
right:0;
width: 175px;
height: 15px;
margin: 0;
padding: 22px 2px;
text-align: center;
vertical-align: middle;
background-color: #fff;
border-left: #000 solid 1px;
border-bottom: #000 solid 1px;
color: #000;
font-weight: bold;
}
div#drw {
margin-top: 10px;
text-align: center;
}
canvas#pat {
display: none;
}
img#img {
display: none;
}
<!DOCTYPE html>
<html>
<head>
<title>pixelate</title>
<script type="text/javascript" src="pixelate.js"></script>
<link rel="stylesheet" type="text/css" href="pixelate.css">
</head>
<body onload="activate()">
<form id="ctl" onsubmit="return false">
<span id="idc">16</span>
<span id="sld">
<span class="num">1</span>
<input id="siz" type="range" min="1" max="100" step="1" value="16">
<span class="num">100</span>
</span>
<input id="ccl" type="checkbox"><label for="ccl">Circle</label>
<input type="button" id="btn" value="OK">
<div id="drp">drop image here</div>
</form>
<div id="drw">
<canvas id="cnv"></canvas>
<canvas id="pat"></canvas>
<img id="img" src="example.jpg">
</div>
</body>
</html>
var btn, ccl, cnv, ctl, idc, img, pat, siz;
var tid = null;
var $ = function(id){
return document.getElementById(id);
};
var text = function(str){
return document.createTextNode(str);
};
var pixelate = function(ctx, x, y, width, height, fast){
var image, data, color;
if (fast) {
image = ctx.getImageData(x, y, 1, 1);
data = image.data;
color = 'rgb(' + data[0] + ',' +
data[1] + ',' +
data[2] + ')';
} else {
var r, g, b, a, i, l, n;
image = ctx.getImageData(x, y, width, height);
data = image.data;
l = data.length;
n = l / 4;
r = 0;
g = 0;
b = 0;
a = 0;
for (i = 0; i < l; i += 4) {
r += data[i];
g += data[i + 1];
b += data[i + 2];
//a += data[i + 3];
}
color = 'rgb(' + Math.round(r / n) + ',' +
Math.round(g / n) + ',' +
Math.round(b / n) + ')';
}
ctx.fillStyle = color;
ctx.fillRect(x, y, width, height);
};
var pixelateImage = function(){
try {
pixelateImageDo();
} catch (e) {
alert('Error: ' + e.toString());
}
};
var pixelateImageDo = function(){
var ctx, size, width, height;
var x, y, z, xlen, ylen, xmod, ymod;
ctx = cnv.getContext('2d');
width = img.width;
height = img.height;
cnv.width = width;
cnv.height = height;
ctx.drawImage(img, 0, 0);
size = Math.max(1, Math.min(100, parseInt(siz.value)));
if (size < 2) {
return;
}
xmod = width % size;
ymod = height % size;
xlen = width - xmod;
ylen = height - ymod;
for (x = 0; x < xlen; x += size) {
for (y = 0; y < ylen; y += size) {
pixelate(ctx, x, y, size, size);
}
if (ymod) {
pixelate(ctx, x, ylen, size, ymod);
}
}
if (xmod) {
for (y = 0; y < ylen; y += size) {
pixelate(ctx, xlen, y, xmod, size);
}
if (ymod) {
pixelate(ctx, xlen, ylen, xmod, ymod);
}
}
if (ccl.checked && size > 1) {
circularize(ctx, size, width, height);
}
};
var circularize = function(ctx, size, width, height){
var radius, patctx, patimage, patdata, i, l;
pat.width = size;
pat.height = size;
radius = size / 2;
patctx = pat.getContext('2d');
patctx.fillStyle = '#fff';
patctx.beginPath();
patctx.arc(radius, radius, radius, 0, Math.PI * 2, false);
patctx.closePath();
patctx.fill();
patimage = patctx.getImageData(0, 0, size, size);
patdata = patimage.data;
l = patdata.length;
for (i = 0; i < l; i += 4) {
patdata[i] = 255;
patdata[i + 1] = 255;
patdata[i + 2] = 255;
patdata[i + 3] = 255 - patdata[i + 3];
}
patctx.putImageData(patimage, 0, 0);
ctx.fillStyle = ctx.createPattern(pat, 'repeat');
ctx.fillRect(0, 0, width, height);
};
var finalizeImage = function(){
window.open(cnv.toDataURL('image/png'),
null,
'width=' + cnv.width + ',height=' + cnv.height);
};
var activate = function(){
var drp = $('drp');
btn = $('btn');
ccl = $('ccl');
cnv = $('cnv');
ctl = $('ctl');
idc = $('idc');
img = $('img');
pat = $('pat');
siz = $('siz');
idc.style.left = (siz.offsetLeft + parseInt(siz.value)) + 'px';
drp.addEventListener('dragenter', function(ev){
ev.preventDefault();
this.style.backgroundColor = '#ffa';
return false;
}, false);
drp.addEventListener('dragover', function(ev){
ev.preventDefault();
return false;
}, false);
drp.addEventListener('dragleave', function(ev){
ev.preventDefault();
this.style.backgroundColor = '#fff';
return false;
}, false);
drp.addEventListener('drop', function(ev){
var dt = ev.dataTransfer;
ev.stopPropagation();
if (dt.files && dt.files.length) {
var re, i, files, length;
re = /^image\/(gif|jpeg|png)$/;
files = dt.files;
length = files.length;
for (i = 0; i < length; i++) {
if (re.test(files[i].type)) {
try {
var reader = new FileReader();
reader.onloadend = function(){
img.src = reader.result;
img.onload = pixelateImage;
};
reader.readAsDataURL(files[i]);
} catch (e) {
alert('Error: ' + e.toString());
}
break;
}
}
}
this.style.backgroundColor = '#fff';
return false;
}, false);
btn.addEventListener('click', finalizeImage, true);
ccl.addEventListener('click', pixelateImage, true);
siz.addEventListener('change', function(){
var value, offset;
if (tid) {
clearTimeout(tid);
}
value = Math.max(1, Math.min(100, parseInt(this.value)));
if (value.toString() != this.value) {
this.value = value;
}
offset = this.offsetLeft + value
if (value < 10) {
offset += 3;
} else if (value < 100) {
offset += value / 25;
} else {
offset += 2;
}
idc.innerHTML = value;
idc.style.left = Math.round(offset) + 'px';
tid = setTimeout(function(){
pixelateImage();
tid = null;
}, 50);
}, true);
pixelateImage();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment