Last active
August 29, 2015 14:03
-
-
Save cuter44/fe256687b9bcd6e65c14 to your computer and use it in GitHub Desktop.
Parse ISBN-13 from image taken by camera, with pure js.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<script src="ISBN13Parser.js"></script> | |
</head> | |
<body> | |
<input type="file" accept="image/*" onchange="loadAndParse(this);"/> | |
<script> | |
var parser = new ISBN13Parser(); | |
function loadAndParse(input) | |
{ | |
console.log(input.value); | |
var reader = new window.FileReader(); | |
reader.onloadend = function(){ | |
var img = new Image(); | |
img.src = this.result; | |
alert(parser.parseImage(img)); | |
}; | |
reader.readAsDataURL(input.files[0]); | |
} | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** ISBN-13 decoder | |
* author by galin<[email protected]> | |
* free to use if reserve the author info. | |
*/ | |
function ISBN13Parser(){ | |
this.sResult = null; | |
this.iaResult = null; | |
this.baResult = null; | |
this.thresold = 80; | |
this.cb = (function (){ | |
var a = new Array(); | |
a[13]=0; a[39]=0; a[114]=0; | |
a[25]=1; a[51]=1; a[102]=1; | |
a[19]=2; a[27]=2; a[108]=2; | |
a[61]=3; a[33]=3; a[ 66]=3; | |
a[35]=4; a[29]=4; a[ 92]=4; | |
a[49]=5; a[57]=5; a[ 78]=5; | |
a[47]=6; a[ 5]=6; a[ 80]=6; | |
a[59]=7; a[17]=7; a[ 68]=7; | |
a[55]=8; a[ 9]=8; a[ 72]=8; | |
a[11]=9; a[23]=9; a[116]=9; | |
return(a); | |
})(); | |
this.parseImage = function (img) | |
{ | |
return( | |
this.parseCanvas(this.img2Canvas(img)) | |
); | |
} | |
this.parseCanvas = function (cvs) | |
{ | |
this.baResult = | |
this.parseBits(this.binarize(this.discolor(cvs))); | |
this.iaResult = this.decodeBits(this.baResult); | |
var sResult = ""; | |
for (var i=0; i<13; i++) | |
sResult = sResult.concat(this.iaResult[i]); | |
this.sResult = sResult; | |
return(this.sResult); | |
} | |
this.decodeBits = function (bits) | |
{ | |
var offset = 3, | |
decoded = new Array(13); | |
for (var i=1; i<=6; i++) | |
{ | |
var b = 0; | |
for (var j=0; j<7; j++) | |
b = (b<<1)+bits[offset++]; | |
decoded[i]=this.cb[b]; | |
//console.log(b.toString(2) + " -> " + decoded[i]); | |
} | |
offset = 50; | |
for (var i=7; i<=12; i++) | |
{ | |
var b = 0; | |
for (var j=0; j<7; j++) | |
b = (b<<1)+bits[offset++]; | |
decoded[i]=this.cb[b]; | |
//console.log(b.toString(2) + " -> " + decoded[i]); | |
} | |
decoded[0] = 9; | |
return(decoded); | |
} | |
this.parseBits = function (cvs) | |
{ | |
var w = cvs.width, | |
h = cvs.height, | |
w_mid = Math.floor(w/2), | |
h_mid = Math.floor(h/2), | |
ctx = cvs.getContext("2d"), | |
data = ctx.getImageData(0, h_mid, w, 1).data, | |
edge_l, edge_r, wh_l, wh_r, ln_found; | |
wh_l = wh_r = 0; | |
edge_l = edge_r = w_mid*4; | |
ln_found = (data[4*w_mid]==0) ? -1 : 0; | |
while (ln_found<30) | |
{ | |
if (wh_l<wh_r) | |
{ | |
var p = data[edge_l]; | |
edge_l -= 4; | |
if (edge_l<0) | |
throw("左边缘溢出"); | |
if (data[edge_l]-p==255) | |
ln_found++; | |
wh_l += (data[edge_l]==255) ? 1 : -wh_l; | |
} | |
else | |
{ | |
var p = data[edge_r]; | |
edge_r += 4; | |
if (edge_r>(w-1)*4) | |
throw("右边缘溢出"); | |
if (data[edge_r]-p==255) | |
ln_found++; | |
wh_r += (data[edge_r]==255) ? 1 : -wh_r; | |
} | |
} | |
// shrink | |
while (data[edge_l]==255) | |
edge_l+=4; | |
while (data[edge_r]==255) | |
edge_r-=4; | |
var l=edge_l/4, r=edge_r/4, p=l, s=(r-l)/95; | |
var bits = new Array(95); | |
for (var i=0; i<95; i++) | |
{ | |
var p_l = Math.ceil(p), p_r = Math.floor(p+s); | |
c = 0; | |
for (var j=p_l; j<=p_r; j++) | |
c += (data[j*4]==0)?1:0; | |
bits[i] = Math.round(c/(p_r-p_l+1)); | |
//console.log(p_l+" -> "+p_r+", "+c+"/"+(p_r-p_l+1)+"="+bits[i]); | |
ctx.fillStyle = (i%2==0)? "rgba(255,0,0,0.5)" : "rgba(0,255,0,0.5)"; | |
ctx.fillRect(p_l, h_mid-1, p_r-p_l+1, 3); | |
p+=s; | |
} | |
this.dump(cvs); | |
return(bits); | |
} | |
this.binarize = function (cvs) | |
{ | |
var w = cvs.width, h = cvs.height, | |
ctx = cvs.getContext("2d"), | |
imgd = ctx.getImageData(0, 0, w, h), | |
data = imgd.data, | |
px_count = w*h, | |
b_count = new Array(256), | |
b_convert = new Array(256), | |
pr_accel = 0; | |
for (var i=0; i<px_count; i++) | |
b_count[data[i*4]] = (b_count[data[i*4]]===undefined) ? 1 : b_count[data[i*4]]+1; | |
for (var i=0; i<256; i++) | |
{ | |
var pr = (b_count[i]===undefined) ? 0 : b_count[i]/px_count; | |
pr_accel += pr; | |
b_convert[i] = Math.round(pr_accel*256); | |
} | |
for (var i=0; i<px_count; i++) | |
data[i*4] = data[i*4+1] = data[i*4+2] = | |
((b_convert[data[i*4]]<this.thresold)?0:255); | |
ctx.putImageData(imgd, 0, 0); | |
this.dump(cvs); | |
return(cvs); | |
} | |
this.discolor = function (cvs) | |
{ | |
var w = cvs.width, h = cvs.height, | |
ctx = cvs.getContext("2d"), | |
imgd = ctx.getImageData(0, 0, w, h), | |
data = imgd.data, | |
px_count = w*h; | |
for (var i=0; i<px_count; i++) | |
{ | |
var b = Math.round((data[i*4]*299+data[i*4+1]*587+data[i*4+2]*114)/1000); | |
data[i*4] = data[i*4+1] = data[i*4+2] = b; | |
} | |
ctx.putImageData(imgd, 0, 0); | |
this.dump(cvs); | |
return(cvs); | |
} | |
this.img2Canvas = function (img) | |
{ | |
var cvs = document.createElement("canvas"); | |
cvs.width = img.width; | |
cvs.height = img.height; | |
var ctx = cvs.getContext("2d"); | |
ctx.drawImage(img, 0, 0); | |
this.dump(cvs); | |
return(cvs); | |
}; | |
this.dump = function (cvs) | |
{ | |
var c = document.createElement("canvas"); | |
c.width = cvs.width; | |
c.height = cvs.height; | |
c.getContext("2d").drawImage(cvs, 0, 0); | |
document.body.appendChild(c); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment