WinJS Low Memory issue with ZXing - javascript

I am creating a Barcode scanner module for Windows 8 Metro App.
I some how success with my logic but suddenly I saw my application crash due to low memory issue.
<script>
var canvas = null;
var ctx = null;
var livePreview = null;
var count = 0,rescount=0;
function takepicture() {
var Capture = Windows.Media.Capture;
livePreview = document.getElementById("live-preview");
var mediaCapture = new Capture.MediaCapture();
canvas = document.getElementById("Vcanvas");
ctx=canvas.getContext('2d');
livePreview.addEventListener('play', function () { var i = window.setInterval(function () { ctx.drawImage(livePreview, 0, 0, canvas.width, canvas.height); scanCanvasEasy(); }, 20); }, false);
livePreview.addEventListener('pause', function () { window.clearInterval(i); }, false);
livePreview.addEventListener('ended', function () { clearInterval(i); }, false);
/*
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.videosLibrary;
openPicker.fileTypeFilter.replaceAll([".mp4", ".avi", ".ogg"]);
openPicker.pickSingleFileAsync()
.then(function (file) {
if (file) {
// draw the image
var img = new Image;
//img.onload = function () {
// canvas.width = img.width;
// canvas.height = img.height;
// ctx.drawImage(img, 0, 0, img.width, img.height);
// scanCanvasEasy();
//}
//img.src = URL.createObjectURL(file);
// open a stream from the image
livePreview.src = URL.createObjectURL(file);
livePreview.play();
}
})*/
mediaCapture.initializeAsync().then(function () {
livePreview.src = URL.createObjectURL(mediaCapture);
livePreview.play();
});
}
function scanCanvasEasy() {
var imgd = ctx.getImageData(0, 0,canvas.width,canvas.height);
var pix = imgd.data;
var reader = new ZXing.BarcodeReader();
reader.onresultpointfound = function (resultPoint) {
// do something with the resultpoint location
console.log(resultPoint.toString());
}
// try to decode the raw pixel data
var result = reader.decode(pix, canvas.width, canvas.height, ZXing.BitmapFormat.rgba32);
/*
The above line cause that memory issue, without that line there is no change in memory level.
*/
// show the result
if (result) {
document.getElementById("result").innerText ="Result(+"+rescount++ +")==>"+ result.text;
}
else {
document.getElementById("error").innerText = "no barcode found" + count++;
}
}
</script>
I posted the whole code i used here I Just called the takepicture() method from button click event.
var result = reader.decode(pix, canvas.width, canvas.height, ZXing.BitmapFormat.rgba32);
This line cause memory issue.
Thanks in advance.

var reader = new ZXing.BarcodeReader();
Multiple instance of reader cause this issue. Just created one instance of reader and use it for all subsequent scan will fixed that issue.

Related

Can't recognize image using OCR

I was trying to use ocrad.js to convert an image to a string, but I didn't get the result string. I was also previewing the image, the problem is only in the image recognition.
This is my code:
function pr_image(event) {
var reader = new FileReader();
reader.onload = function() {
var output = document.getElementById('output_image');
output.src = reader.result;
}
reader.readAsDataURL(event.target.files[0]);
var stringletter = OCRAD(event.target.files[0]);
document.getElementById('letter').value = stringletter;
}
and this is the browser's capture:
unchanged value
no error message in console
I've tried to change the recognition code into this one function, but i get . as the image recognition's result:
function str_img(event) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
context.drawImage(this, 0, 0);
}
var imageData = context.getImageData(0, 0, 100, 100);
var stringletter = OCRAD(imageData);
document.getElementById('letter').value = stringletter;
}
I suspect that I failed at converting the input file as image data. What should I do? Any help is appreciated!
Solved:
I've changed my code into this by Chris G and it works! Thank you
function preview_image(event)
{
var reader = new FileReader();
var output = document.getElementById('output_image');
reader.onload = function()
{
output.src = reader.result;
}
reader.readAsDataURL(event.target.files[0]);
output.onload = function()
{
var stringletter = OCRAD(output);
document.getElementById('letter').value = stringletter;
}
}

Esri Take Map Scrrenshots using Javascript

I am trying to generate a pdf report including current map screenshot of ESRI map using JavaScript. Here is my code.
var getCurrentMapScreenShot = function (success, error) {
esriLoader.Config.defaults.io.proxyUrl = myAppSettingsModel.SettingsModel.MapSettings.AGSProxyURL;
esriLoader.Config.defaults.io.alwaysUseProxy = true;
var printTask = new esriLoader.PrintTask("myexportUrl");
var template = new esriLoader.PrintTemplate();
template.exportOptions = {
width: 600,
height: 600,
dpi: 96
};
template.format = "image/png";
template.layout = "MAP_ONLY",
template.preserveScale = true;
template.layoutOptions = {
legendLayers: [], // empty array means no legend
scalebarUnit: "Miles"
};
var params = new esriLoader.PrintParameters();
params.map = map;
params.template = template;
printTask.execute(params, success, error);
}
This function will give you an event that contains a url , Then I am passing this url to get map base64 data.
Here is the function calling.
map.GetCurrentMapScreenShot(function (event) {
var mapScreenShotURL = event.url;
Factory.GetBase64ForImgUrl(mapScreenShotURL,
function (mapImageBase64Encoded) {});
and here is the function that converts url to base64image
function getBase64ForImgUrl(url, callback, outputFormat) {
console.log("#################### Summary Report Image " + url);
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function () {
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL(outputFormat || 'image/png');
callback.call(this, dataURL);
// Clean up
canvas = null;
};
img.src = url;
}
I am getting base64 image data of the map , But the problem is that, I am getting blurred image of the map with no feature layers and no icons..And also map contains some junk texts.
Thanks
I resolved the issue almost, Now I am getting the map image that contains map Icons and layer graphics, But unfortunately still getting some junk texts.
I have changed the code as follows.
template.format = "JPG";
template.layout = "A4 Landscape",
template.preserveScale = false;
template.layoutOptions = {
"legendLayers": [], // empty array means no legend
"scalebarUnit": "Miles"
}

Is it possible to cache canvas pages?

I am using the code in http://jsfiddle.net/epistemex/LUNaJ/
PDFJS.disableWorker = true; // due to CORS
var canvas = document.createElement('canvas'), // single off-screen canvas
ctx = canvas.getContext('2d'), // to render to
pages = [],
currentPage = 1,
url = 'http://www.corsproxy.com/www.ohio.edu/technology/training/upload/Java-Script-Reference-Guide.pdf';
PDFJS.getDocument(url).then(function (pdf) {
PROGRESS.max = pdf.numPages; // just for demo
PROGRESS.value = 1; // just for demo
// init parsing of first page
if (currentPage <= pdf.numPages) getPage();
// main entry point/function for loop
function getPage() {
// when promise is returned do as usual
pdf.getPage(currentPage).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
// now, tap into the returned promise from render:
page.render(renderContext).then(function() {
// store compressed image data in array
pages.push(canvas.toDataURL());
if (currentPage < pdf.numPages) {
currentPage++;
PROGRESS.value = currentPage; // just for demo
getPage(); // get next page
}
else {
done(); // call done() when all pages are parsed
}
});
});
}
});
function done() {
// NOTE: Just for demo - correct order is not guaranteed here
// as the drawPage is async. use same method as above to make
// sure the order is correct (not for-loop, but use the callback
// to get next page). To present a single page it won't be
// a problem though... (just use drawPage() directly)
for(var i = 0; i < pages.length; i++) {
drawPage(i, addPage);
}
}
function addPage(img) {
img.style.width = '100px';
img.style.height = '120px';
document.body.appendChild(img);
}
function drawPage(index, callback) {
var img = new Image;
img.onload = function() {
ctx.drawImage(this, 0, 0, ctx.canvas.width, ctx.canvas.height);
callback(this); // invoke callback when we're done
}
img.src = pages[index]; // start loading the data-uri as source
}
to render pdf pages to canvas. The problem with this is that it takes along time if the pdf file has large number of files. Is it possible to cache/save these generated files in the users computer/bowser so that if he runs the code a secondary time, he doesn't have to generate them again and instead they can be displayed immediately.
No, dataURI are not "cached" by browser since there is no download involved.
What you can do however, is to store all your pages into a globally accessible array, and check if you already have it before you call PDFJS.getDocument(url) :
PDFJS.disableWorker = true; // due to CORS
var canvas = document.createElement('canvas'), // single off-screen canvas
ctx = canvas.getContext('2d'), // to render to
docs = {}, // an object that will store our pdf documents
urls = ["https://www.ohio.edu/technology/training/upload/html-tag-reference-guide.pdf", "https://www.ohio.edu/technology/training/upload/Java-Script-Reference-Guide.pdf"];
btn0.onclick = getDoc;
btn1.onclick = getDoc;
function getDoc() {
// get the doc's url
var url = urls[+this.id.split('btn')[1]];
// clear the result div
result.innerHTML = '';
// we already have it
if (docs[url]) {
// simply call the callback
done(docs[url]);
}
else {
// create our array for this document
docs[url] = [];
// download and parse the doc
PDFJS.getDocument(url).then(function(pdf) {
PROGRESS.max = pdf.numPages; // just for demo
PROGRESS.value = 1; // just for demo
var currentPage = 1;
// init parsing of first page
if (currentPage <= pdf.numPages) getPage();
// main entry point/function for loop
function getPage() {
// when promise is returned do as usual
pdf.getPage(currentPage).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
// now, tap into the returned promise from render:
page.render(renderContext).then(function() {
// store compressed image data in array
docs[url].push(canvas.toDataURL());
if (currentPage < pdf.numPages) {
currentPage++;
PROGRESS.value = currentPage; // just for demo
getPage(); // get next page
} else {
done(docs[url]); // call done() when all pages are parsed
}
});
});
}
});
}
}
function done(pages) {
for (var i = 0; i < pages.length; i++) {
drawPage(pages[i], addPage);
}
}
function addPage(img) {
img.style.width = '100px';
img.style.height = '120px';
result.appendChild(img);
}
function drawPage(dataURI, callback) {
var img = new Image;
img.onload = function() {
ctx.drawImage(this, 0, 0, ctx.canvas.width, ctx.canvas.height);
callback(this); // invoke callback when we're done
}
img.src = dataURI; // start loading the data-uri as source
}
#PROGRESS {
width: 100%
}
<script src="https://rawgit.com/mozilla/pdf.js/gh-pages/build/pdf.js"></script>
<button id="btn0">1st Doc</button>
<button id="btn1">2nd Doc</button>
<progress id="PROGRESS" value=0></progress>
<div id="result"></div>

tick method in javascript for canvas

I'm trying to make a tick method for this code.
When I try to put a while loop or time interval it just goes blank.
I want the tick method to call this function without the canvas going blank.
How would i make that tick method
function setup(){
var canvas = document.getElementById('my_canvas');
var ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
var gun = new Image();
var badguy = new Image();
var wall1 = 200;
var ground = new Image();
var back = new Image();
var back2 = new Image();
var back3 = new Image();
var wall = new Image();
var wall2 = new Image();
back.onload = function() {
ctx.drawImage(back, 0, 0, 800, 300);
};
back2.onload = function() {
ctx.drawImage(back2, mountainplace, 0, mtnsize1, 300);
};
back3.onload = function() {
ctx.drawImage(back3, mountainplace2, 0, mtnsize2, 300);
};
ground.onload = function() {
ctx.drawImage(ground, groundplace, 300, 1980, 200);
};
wall.onload = function() {
ctx.drawImage(wall, place2, 250, size2, 100);
};
wall2.onload = function() {
ctx.drawImage(wall2, place, 250, size, 100);
};
badguy.onload = function() {
ctx.drawImage(badguy, badguyplace, 250, 100, 100);
};
gun.onload = function() {
ctx.drawImage(gun, 0, 100, 400, 400);
};
back2.src = "moutain1.png";
back3.src = "moutain2.png";
back.src = "backing.png";
ground.src = "ground1.jpg";
wall.src = "wall.png";
wall2.src = "wall2.png";
badguy.src = "santa2.png";
gun.src = "gun1.png";
};
You need to clarify the question because I'm not sure what exactly you are trying to achieve.
I assume you put some code at the end of your setup() function that performs some operations on the images. But before you can do it you need to wait for the images to load.
BTW: another problem with your code is that the images will be drawn on the canvas in the order in which they load, which may be unpredictable. You probably want to avoid this too.
A solution to your problem (or at least to what I think your problem is) is to first start loading the images and then only perform further operations after they have all been loaded.
You can use the following code to do this:
function makeAllLoadedHandler(image_files_count, on_all_loaded) {
return function() {
--image_files_count;
if (image_files_count == 0) {
// All images loaded, call the function.
on_all_loaded();
}
}
}
function loadAllImages(image_files, on_all_loaded) {
var images = {};
var callback = makeAllLoadedHandler(image_files.length, function() { on_all_loaded(images); } );
for (var i = 0; i < image_files.length; ++i) {
var image = new Image;
image.src = image_files[i];
image.onload = callback;
images[image_files[i]] = image;
}
}
The loadAllImages() function takes an array of image file names and a function to call when all the images have been loaded.
You can use it like this in your code:
function setup() {
var image_files = [
"mountain1.png",
"mountain2.png",
"backing.png",
"ground1.jpg",
"wall.png",
"wall2.png",
"santa2.png",
"gun1.png" ];
loadAllImages(image_files, onAllImagesLoaded);
}
function onAllImagesLoaded(images) {
// Draw your images and perform all the other tasks on them.
// The 'images' object stores each of the Image object under a key that is
// its file name.
ctx.drawImage(images['backing.png'], 0, 0, 800, 300);
// ...
// Do other stuff with the images.
}
You just call the setup() function like you used to and then the onAllImagesLoaded function will be called some time later when all the images are available. You continue your processing in there.
I hope this helps. Although it's possible that your problem is completely different ;)

WinJS barcode reader issues(Image not loading in canvas)

Am working on a winjs based barcode reader application. Initially I will capture the image using camera capture API and will pass that file object to a canvas element and read its barcode using ZXing library. But the image passed to the canvas is not getting rendered completely as follows.
Following is my html code
<body>
<p>Decoding test for static images</p>
<canvas id="canvasDecode" height="200" width="200"></canvas>
<h3 id="result"></h3>
<p>Put some content here and leave the text box</p>
<input id="input" class="win-textarea" onchange="generate_barcode()">
<h3 id="content"></h3>
<canvas id="canvasEncode" height="200" width="200"></canvas>
<img class="imageHolder" id="capturedPhoto" alt="image holder" />
</body>
following is my javascript code
(function () {
"use strict";
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 1, height: 1 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).then(function (file) {
if (file) {
// draw the image
var canvas = document.getElementById('canvasDecode')
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
}
img.src = URL.createObjectURL(file);
// open a stream from the image
return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
}
})
.then(function (stream) {
if (stream) {
// create a decoder from the image stream
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
}
})
.done(function (decoder) {
if (decoder) {
// get the raw pixel data from the decoder
decoder.getPixelDataAsync().then(function (pixelDataProvider) {
var rawPixels = pixelDataProvider.detachPixelData();
var pixels, format; // Assign these in the below switch block.
switch (decoder.bitmapPixelFormat) {
case Windows.Graphics.Imaging.BitmapPixelFormat.rgba16:
// Allocate a typed array with the raw pixel data
var pixelBufferView_U8 = new Uint8Array(rawPixels);
// Uint16Array provides a typed view into the raw 8 bit pixel data.
pixels = new Uint16Array(pixelBufferView_U8.buffer);
if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
format = ZXing.BitmapFormat.rgba32;
else
format = ZXing.BitmapFormat.rgb32;
break;
case Windows.Graphics.Imaging.BitmapPixelFormat.rgba8:
// For 8 bit pixel formats, just use the returned pixel array.
pixels = rawPixels;
if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
format = ZXing.BitmapFormat.rgba32;
else
format = ZXing.BitmapFormat.rgb32;
break;
case Windows.Graphics.Imaging.BitmapPixelFormat.bgra8:
// For 8 bit pixel formats, just use the returned pixel array.
pixels = rawPixels;
if (decoder.bitmapAlphaMode == Windows.Graphics.Imaging.BitmapAlphaMode.straight)
format = ZXing.BitmapFormat.bgra32;
else
format = ZXing.BitmapFormat.bgr32;
break;
}
// create a barcode reader
var reader = new ZXing.BarcodeReader();
reader.onresultpointfound = function (resultPoint) {
// do something with the resultpoint location
}
// try to decode the raw pixel data
var result = reader.decode(pixels, decoder.pixelWidth, decoder.pixelHeight, format);
// show the result
if (result) {
document.getElementById("result").innerText = result.text;
}
else {
document.getElementById("result").innerText = "no barcode found";
}
});
}
});
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. You might use the
// WinJS.Application.sessionState object, which is automatically
// saved and restored across suspension. If you need to complete an
// asynchronous operation before your application is suspended, call
// args.setPromise().
};
app.start();
})();
function generate_barcode() {
// get the content which the user puts into the textbox
var content = document.getElementById("input").value;
// create the barcode writer and set some options
var writer = new ZXing.BarcodeWriter();
writer.options = new ZXing.Common.EncodingOptions();
writer.options.height = 200;
writer.options.width = 200;
writer.format = ZXing.BarcodeFormat.qr_CODE;
// encode the content to a byte array with 4 byte per pixel as BGRA
var imagePixelData = writer.write(content);
// draw the pixel data to the canvas
var ctx = document.getElementById('canvasEncode').getContext('2d');
var imageData = ctx.createImageData(imagePixelData.width, imagePixelData.heigth);
var pixel = imagePixelData.pixel
for (var index = 0; index < pixel.length; index++) {
imageData.data[index] = pixel[index];
}
ctx.putImageData(imageData, 0, 0);
}
The same code worked well when I was using the file picker API. Let me knew where I went wrong.
I think that you're running into some problems with asynchronicity here. I applaud your use of chained calls to then(), but there's a hidden problem - assignment to img.src begins an asynchronous operation while the image is loaded. Your code continues on BEFORE the img.onload event has been raised, and so the closure which img.onload reaches into for the img variable (the pointer to the file URL) changes before the image has fully loaded.
Here's some code that worked for me.
// Inside handler for app.activated ...
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 1, height: 1 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo)
.then(function (file) {
// draw the image
var canvas = document.getElementById('canvasDecode')
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
// open a stream from the image
decodePic(file);
}
img.onerror = function (err) {
WinJS.log && WinJS.log("Error loading image");
}
img.src = URL.createObjectURL(file);
});
And then I moved the file decoding / barcode reading stuff to a new function.
function decodePic(file) {
file.openAsync(Windows.Storage.FileAccessMode.readWrite)
.then(function (stream) {
if (stream) {
// create a decoder from the image stream
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(stream);
}
})
.done(function (decoder) {
if (decoder) {
// get the raw pixel data from the decoder
decoder.getPixelDataAsync().then(function (pixelDataProvider) {
// YOUR BARCODE READING CODE HERE.
});
}
});
}
I hope this helps!

Categories

Resources