angularjs - Rgba to basic matrix (0 for white pixel, 1 for anything else) transformation with BufferedImage -
i'm working on optical character recognition school project.
at step, have draw character apply freeman chain code it.
i'm drawing on canvas using sketch.js
front end code handled angularjs, end spring & bufferedimage
based on 2 tutorials :
for canvas drawing : https://developer.mozilla.org/en-us/docs/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas#grayscaling_and_inverting_colors
for sketch.js : https://intridea.github.io/sketch.js/docs/sketch.html
i wrote client code :
... <div class="container"> <div ng-controller="ctrl"> <canvas ng-model="canvas" ng-click="enablesave()" class="panel panel-default" width="200" height="200"></canvas> <form class="form-horizontal" enctype="multipart/form-data"> <div class="input-group col-md-4"> <span class="input-group-btn"> <button ng-click="clear()" id="clear" type="button" class="btn btn-default">clear</button> </span> <input ng-model="num" type="number" id="num" class="form-control" type="text"> <span class="input-group-btn"> <button ng-click="save()" ng-disabled="modif == false" type="button" class="btn btn-success">save</button> </span> </div> </form> </div> </div> <script type="text/javascript" src="assets/js/jquery-2.2.0.min.js"></script> <script type="text/javascript" src="assets/js/sketch.min.js"></script> <script type="text/javascript" src="assets/js/angular.min.js"></script> <script type="text/javascript"> var app = angular.module('app', []); app.controller('ctrl', ['$scope', '$log', '$http', function($scope, $log, $http) { // init $scope.modif = false; $scope.canvas = angular.element('canvas'); $scope.context = $scope.canvas[0].getcontext('2d'); $scope.canvas.sketch({ defaultcolor: "#000000", defaultsize: 2 }); // enable save button if user draw on canvas $scope.enablesave = function() { $scope.modif = true; }; // convert image blob : https://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata $scope.toblob = function(datauri) { var bytestring; if (datauri.split(',')[0].indexof('base64') >= 0) bytestring = atob(datauri.split(',')[1]); else bytestring = unescape(datauri.split(',')[1]); var mimestring = datauri.split(',')[0].split(':')[1].split(';')[0]; var ia = new uint8array(bytestring.length); (var = 0; < bytestring.length; i++) ia[i] = bytestring.charcodeat(i); return new blob([ia], { type: mimestring }); }; // send user's input server $scope.save = function() { var img = $scope.canvas[0].todataurl('image/png'); $log.info(img); var fd = new formdata(); var blob = $scope.toblob(img); fd.append('img', blob); $http.post('add.html', fd, { withcredentials: true, headers: { 'content-type': undefined }, transformrequest: angular.identity }) .success(function(result) { $log.info(result); }) .error(function(data, status) {}); // clear canvas img = null; $scope.clear(); // disable save button $scope.modif = false; }; // clear canvas $scope.clear = function() { $scope.context.clearrect(0, 0, $scope.canvas[0].width, $scope.canvas[0].height); $scope.canvas.sketch('actions', []); } }]); $(document).ready(function() {}); </script> </body> </html>
spring controller :
@requestmapping(value = "/add", method = requestmethod.post) @responsebody public string add(@requestparam("img") multipartfile image) throws ioexception { log.info("add : post"); log.info("bytes image : " + image.getbytes().length); bufferedimage original = imageio.read(image.getinputstream()); bufferedimage non_transparent = new bufferedimage(original.getwidth(), original.getheight(), bufferedimage.type_int_rgb); bufferedimage black_white = new bufferedimage(non_transparent.getwidth(), non_transparent.getheight(), bufferedimage.type_byte_binary); non_transparent.getgraphics().drawimage(original, 0, 0, null); non_transparent.getgraphics().dispose(); black_white.getgraphics().drawimage(non_transparent, 0, 0, null); black_white.getgraphics().dispose(); byte[] original_pixels = ((databufferbyte) original.getraster().getdatabuffer()).getdata(); log.info("original pixels : " + original_pixels.length); int[] non_transparent_pixels = ((databufferint) non_transparent.getraster().getdatabuffer()).getdata(); log.info("non transparent pixels : " + non_transparent_pixels.length); byte[] black_white_pixels = ((databufferbyte) black_white.getraster().getdatabuffer()).getdata(); log.info("black white pixels : " + black_white_pixels.length); fileoutputstream fos_original = new fileoutputstream("original.txt"); fos_original.write(original_pixels); fos_original.close(); file f_original = new file("original.png"); imageio.write(original, "png", f_original); file f_non_transparent = new file("non_transparent.png"); imageio.write(non_transparent, "png", f_non_transparent); fileoutputstream fos_black_white = new fileoutputstream("black_white.txt"); fos_black_white.write(black_white_pixels); fos_black_white.close(); file f_black_white = new file("black_white.png"); imageio.write(black_white, "png", f_black_white); return status; }
whatever picture format choose in var img = $scope.canvas[0].todataurl('image/png');
the picture sent transparent except drawn on pixels.
i want transform sent picture rgba basic (0 white pixel, 1 else) matrix.
i started testing bufferedimage class transformation, because i've read creating new bufferedimage image type of type_byte_binary original bufferedimage
but method produces totally black image bytes set 0.
so have 2 question ? there way prevent transparency on canvas ? & there built in way rgba 0/1 matrix transformation ?
thanks.
for question 1 :
is there way prevent transparency on canvas ?
there several actually.
you can pass
{alpha: false}
objectcanvas.getcontext('2d')
method.
disable default transparency of context, setting black rectangle. note won't disable transparency of further drawn objects (ctx.globalalpha
,rgba
colors still honored, calculated on black background). because default, transparency on canvasrgba(0,0,0,0)
, removing alpha value leavergb(0,0,0)
.an other solution, fill rectangle, act background, in solid color want.
var img = new image(); img.onload = function(){ //_____option 1______// // #noalpha canvas' 2d context, alpha parameter set false var nactx = noalpha.getcontext('2d', {alpha:false}); // can draw partially transparent image , have black background nactx.drawimage(img, 20,20); //_____option 2______// // #whitefill canvas' 2d context var wfctx = whitefill.getcontext('2d'); // set context' fill color white // can css color argument wfctx.fillstyle = 'white'; // fill rectangle big canvas wfctx.fillrect(0,0, whitefill.width, whitefill.height); // you've got white background // can draw partially transparent image , have white background wfctx.drawimage(img, 20,20); }; img.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png"
body{background-color: ivory;}
<canvas id="noalpha" width="70" height="70"></canvas> <canvas id="whitefill" width="70" height="70"></canvas>
for second question,
is there built in way rgba 0/1 matrix transformation ?
no, or @ least, not in knowledge.
what : keep transparency of images, except if need consider white transparent, in case, see last snippet of answer.
then it's quite easy use ctx.getimagedata()
method, loop through data
property , check alpha values. (getimagedata.data
typedarray representing rgba values of requested part of canvas (red, green, blue , alpha channels)).
var img = new image(); // able use getimagedata method, have sure don't taint canvas // see http://stackoverflow.com/questions/34743987/canvas-image-crossplatform-insecure-error/34755162#34755162 more info img.crossorigin = 'anonymous'; img.onload = function(){ var ctx = source.getcontext('2d'); // draw image , keep transparency ctx.drawimage(img, 0,0); var yourarray = []; // canvas' imagedata position 0,0 , of ful size of canvas var imagedata = ctx.getimagedata(0,0, source.width, source.height); // rgba array of imagedata var data = imagedata.data; // loop through pixels, checking alpha value for(var i=3; i<data.length-3; i+=4){ // non-transparent pixel if(data[i] > 0) { yourarray.push(1); // set r,g,b values 0 (black) data[i-3] = data[i-2] = data[i-1] = 0; // set alpha value 255 data[i] = 255; } else{ yourarray.push(0); } } console.log(yourarray); // draw new image on export canvas (could alos first 1 output.getcontext('2d').putimagedata(imagedata, 0,0); }; img.src = "https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png"
body{background-color: ivory;}
<canvas id="source" width="32" height="32"></canvas> <canvas id="output" width="32" height="32"></canvas>
here how loop through pixels values if need see white ones transparent :
var img = new image(); img.crossorigin = 'anonymous'; img.onload = function(){ var ctx = source.getcontext('2d'); ctx.drawimage(img, 0,0); var imagedata = ctx.getimagedata(0,0, source.width, source.height); var data = imagedata.data; var yourarray = []; // loop through pixels, checking every rgba value for(var i=0; i<data.length; i+=4){ // non-white pixel if( data[i]+data[i+1]+data[i+2]+data[i+3] < 255*4 ) { yourarray.push(1); // set r,g,b values 0 (black) data[i] = data[i+1] = data[i+2] = 0; // set alpha value 255 data[i+3] = 255; }else{ yourarray.push(0); // set alpha value 0 data[i+3] = 0; } } console.log(yourarray); output.getcontext('2d').putimagedata(imagedata, 0,0); }; // image white background img.src = "https://dl.dropboxusercontent.com/s/iac97oiynwthrg5/somewhite.png"
body{background-color: ivory;}
<canvas id="source" width="284" height="383"></canvas> <canvas id="output" width="284" height="383"></canvas>
Comments
Post a Comment