I'm working on an optical character recognition school project.
At this step, I have to draw a character then apply Freeman Chain Code to it.
I'm drawing on a canvas using sketch.js
Front end code is handled with angularjs, back end with Spring & BufferedImage
Based on those two 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 this 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 to 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);
for (var i = 0; i < byteString.length; i++)
ia[i] = byteString.charCodeAt(i);
return new Blob([ia], {
type: mimeString
});
};
// send user's input to 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 I choose in var img = $scope.canvas[0].toDataURL('image/png');
the picture is always sent all transparent except the drawn on pixels.
I want to transform the sent picture from rgba to a basic (0 for white pixel, 1 for anything else) matrix.
I started testing with BufferedImage class to do this transformation, because i've read that you could do it by creating a new BufferedImage with an image type of TYPE_BYTE_BINARY from the original BufferedImage
But this method always produces a totally black image with all bytes set to 0.
So i have two question ? Is there a way to prevent transparency on the canvas ? & Is there a built in way to do rgba to 0/1 matrix transformation ?
Thanks.