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,rgbacolors 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