first commit
This commit is contained in:
352
JOB.js
Normal file
352
JOB.js
Normal file
@@ -0,0 +1,352 @@
|
||||
/**
|
||||
* CallBacks:
|
||||
* __________________________________________________________________________________
|
||||
* All the callback function should have one parameter:
|
||||
* function(result){};
|
||||
* And the result parameter will contain an array of objects that look like JOB.
|
||||
* result = [{Format: the barcode type, Value: the value of the barcode}];
|
||||
* __________________________________________________________________________________
|
||||
*
|
||||
* You can use either the set functions or just access the properties directly to set callback or
|
||||
* other properties. Just always remember to call Init() before starting to decode something never mess
|
||||
* around with the SupportedFormats property.
|
||||
*
|
||||
*/
|
||||
JOB = {
|
||||
Config : {
|
||||
// Set to false if the decoder should look for one barcode and then stop. Increases performance.
|
||||
Multiple : true,
|
||||
|
||||
// The formats that the decoder will look for.
|
||||
DecodeFormats : ["Code128","Code93","Code39","EAN-13", "2Of5", "Inter2Of5", "Codabar"],
|
||||
|
||||
// ForceUnique just must makes sure that the callback function isn't repeatedly called
|
||||
// with the same barcode. Especially in the case of a video stream.
|
||||
ForceUnique: true,
|
||||
|
||||
// Set to true if information about the localization should be recieved from the worker.
|
||||
LocalizationFeedback: false,
|
||||
|
||||
// Set to true if checking orientation of the image should be skipped.
|
||||
// Checking orientation takes a bit of time for larger images, so if
|
||||
// you are sure that the image orientation is 1 you should skip it.
|
||||
SkipOrientation : false
|
||||
},
|
||||
SupportedFormats : ["Code128","Code93","Code39","EAN-13", "2Of5", "Inter2Of5", "Codabar"],// Don't touch.
|
||||
ScanCanvas : null, // Don't touch the canvas either.
|
||||
ScanContext : null,
|
||||
SquashCanvas : document.createElement("canvas"),
|
||||
ImageCallback : null, // Callback for the decoding of an image.
|
||||
StreamCallback : null, // Callback for the decoding of a video.
|
||||
LocalizationCallback : null, // Callback for localization.
|
||||
Stream : null, // The actual video.
|
||||
DecodeStreamActive : false, // Will be set to false when StopStreamDecode() is called.
|
||||
Decoded : [], // Used to enfore the ForceUnique property.
|
||||
DecoderWorker : new Worker("DecoderWorker.js"),
|
||||
OrientationCallback : null,
|
||||
// Always call the Init().
|
||||
Init : function() {
|
||||
JOB.ScanCanvas = JOB.FixCanvas(document.createElement("canvas"));
|
||||
JOB.ScanCanvas.width = 640;
|
||||
JOB.ScanCanvas.height = 480;
|
||||
JOB.ScanContext = JOB.ScanCanvas.getContext("2d");
|
||||
var script = document.createElement('script');
|
||||
script.src = "exif.js";
|
||||
script.type = 'text/javascript';
|
||||
document.getElementsByTagName('head').item(0).appendChild(script);
|
||||
},
|
||||
|
||||
// Value should be true or false.
|
||||
SetRotationSkip : function(value) {
|
||||
JOB.Config.SkipOrientation = value;
|
||||
},
|
||||
// Sets the callback function for the image decoding.
|
||||
SetImageCallback : function(callBack) {
|
||||
JOB.ImageCallback = callBack;
|
||||
},
|
||||
|
||||
// Sets the callback function for the video decoding.
|
||||
SetStreamCallback : function(callBack) {
|
||||
JOB.StreamCallback = callBack;
|
||||
},
|
||||
|
||||
// Sets callback for localization, the callback function should take one argument.
|
||||
// This will be an array with objects with format.
|
||||
// {x, y, width, height}
|
||||
// This represents a localization rectangle.
|
||||
// The rectangle comes from a 320, 240 area i.e the search canvas.
|
||||
SetLocalizationCallback : function(callBack) {
|
||||
JOB.LocalizationCallback = callBack;
|
||||
JOB.Config.LocalizationFeedback = true;
|
||||
},
|
||||
|
||||
// Set to true if LocalizationCallback is set and you would like to
|
||||
// receive the feedback or false if
|
||||
SwitchLocalizationFeedback : function(bool) {
|
||||
JOB.Config.LocalizationFeedback = bool;
|
||||
},
|
||||
|
||||
// Switches for changing the Multiple property.
|
||||
DecodeSingleBarcode : function() {
|
||||
JOB.Config.Multiple = false;
|
||||
},
|
||||
DecodeMultiple : function() {
|
||||
JOB.Config.Multiple = true;
|
||||
},
|
||||
|
||||
// Sets the formats to decode, formats should be an array of a subset of the supported formats.
|
||||
SetDecodeFormats : function(formats) {
|
||||
JOB.Config.DecodeFormats = [];
|
||||
for(var i = 0; i < formats.length; i++) {
|
||||
if(JOB.SupportedFormats.indexOf(formats[i]) != -1) {
|
||||
JOB.Config.DecodeFormats.push(formats[i]);
|
||||
}
|
||||
}
|
||||
if(JOB.Config.DecodeFormats.length == 0) {
|
||||
JOB.Config.DecodeFormats = JOB.SupportedFormats.slice();
|
||||
}
|
||||
},
|
||||
|
||||
// Removes a list of formats from the formats to decode.
|
||||
SkipFormats : function(formats) {
|
||||
for(var i = 0; i < formats.length; i++) {
|
||||
var index = JOB.Config.DecodeFormats.indexOf(formats[i]);
|
||||
if(index >= 0) {
|
||||
JOB.Config.DecodeFormats.splice(index,1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Adds a list of formats to the formats to decode.
|
||||
AddFormats : function(formats) {
|
||||
for(var i = 0; i < formats.length; i++) {
|
||||
if(JOB.SupportedFormats.indexOf(formats[i]) != -1) {
|
||||
if(JOB.Config.DecodeFormats.indexOf(formats[i]) == -1) {
|
||||
JOB.Config.DecodeFormats.push(formats[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// The callback function for image decoding used internally by JOB.
|
||||
JOBImageCallback : function(e) {
|
||||
if(e.data.success == "localization") {
|
||||
if(JOB.Config.LocalizationFeedback) {
|
||||
JOB.LocalizationCallback(e.data.result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(e.data.success == "orientationData") {
|
||||
JOB.OrientationCallback(e.data.result);
|
||||
return;
|
||||
}
|
||||
var filteredData = [];
|
||||
for(var i = 0; i < e.data.result.length; i++) {
|
||||
if(JOB.Decoded.indexOf(e.data.result[i].Value) == -1 || JOB.Config.ForceUnique == false) {
|
||||
filteredData.push(e.data.result[i]);
|
||||
if(JOB.Config.ForceUnique) JOB.Decoded.push(e.data.result[i].Value);
|
||||
}
|
||||
}
|
||||
JOB.ImageCallback(filteredData);
|
||||
JOB.Decoded = [];
|
||||
},
|
||||
|
||||
// The callback function for stream decoding used internally by JOB.
|
||||
JOBStreamCallback : function(e) {
|
||||
if(e.data.success == "localization") {
|
||||
if(JOB.Config.LocalizationFeedback) {
|
||||
JOB.LocalizationCallback(e.data.result);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(e.data.success && JOB.DecodeStreamActive) {
|
||||
var filteredData = [];
|
||||
for(var i = 0; i < e.data.result; i++) {
|
||||
if(JOB.Decoded.indexOf(e.data.result[i].Value) == -1 || JOB.ForceUnique == false) {
|
||||
filteredData.push(e.data.result[i]);
|
||||
if(JOB.ForceUnique) JOB.Decoded.push(e.data.result[i].Value);
|
||||
}
|
||||
}
|
||||
if(filteredData.length > 0) {
|
||||
JOB.StreamCallback(filteredData);
|
||||
}
|
||||
}
|
||||
if(JOB.DecodeStreamActive) {
|
||||
JOB.ScanContext.drawImage(JOB.Stream,0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height);
|
||||
JOB.DecoderWorker.postMessage({
|
||||
scan : JOB.ScanContext.getImageData(0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height).data,
|
||||
scanWidth : JOB.ScanCanvas.width,
|
||||
scanHeight : JOB.ScanCanvas.height,
|
||||
multiple : JOB.Config.Multiple,
|
||||
decodeFormats : JOB.Config.DecodeFormats,
|
||||
cmd : "normal",
|
||||
rotation : 1,
|
||||
});
|
||||
|
||||
}
|
||||
if(!JOB.DecodeStreamActive) {
|
||||
JOB.Decoded = [];
|
||||
}
|
||||
},
|
||||
|
||||
// The image decoding function, image is a data source for an image or an image element.
|
||||
DecodeImage : function(image) {
|
||||
if(image instanceof Image || image instanceof HTMLImageElement)
|
||||
{
|
||||
image.exifdata = false;
|
||||
if(image.complete) {
|
||||
if(JOB.Config.SkipOrientation) {
|
||||
JOB.JOBDecodeImage(image,1,"");
|
||||
} else {
|
||||
EXIF.getData(image, function(exifImage) {
|
||||
var orientation = EXIF.getTag(exifImage,"Orientation");
|
||||
var sceneType = EXIF.getTag(exifImage,"SceneCaptureType");
|
||||
if(typeof orientation != 'number') orientation = 1;
|
||||
JOB.JOBDecodeImage(exifImage,orientation,sceneType);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
if(JOB.Config.SkipOrientation) {
|
||||
JOB.JOBDecodeImage(img,1,"");
|
||||
} else {
|
||||
EXIF.getData(this, function(exifImage) {
|
||||
var orientation = EXIF.getTag(exifImage,"Orientation");
|
||||
var sceneType = EXIF.getTag(exifImage,"SceneCaptureType");
|
||||
if(typeof orientation != 'number') orientation = 1;
|
||||
JOB.JOBDecodeImage(exifImage,orientation,sceneType);
|
||||
});
|
||||
}
|
||||
};
|
||||
img.src = image.src;
|
||||
}
|
||||
} else {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
if(JOB.Config.SkipOrientation) {
|
||||
JOB.JOBDecodeImage(img,1,"");
|
||||
} else {
|
||||
EXIF.getData(this, function(exifImage) {
|
||||
var orientation = EXIF.getTag(exifImage,"Orientation");
|
||||
var sceneType = EXIF.getTag(exifImage,"SceneCaptureType");
|
||||
if(typeof orientation != 'number') orientation = 1;
|
||||
JOB.JOBDecodeImage(exifImage,orientation,sceneType);
|
||||
});
|
||||
}
|
||||
};
|
||||
img.src = image;
|
||||
}
|
||||
},
|
||||
|
||||
// Starts the decoding of a stream, the stream is a video not a blob i.e it's an element.
|
||||
DecodeStream : function(stream) {
|
||||
JOB.Stream = stream;
|
||||
JOB.DecodeStreamActive = true;
|
||||
JOB.DecoderWorker.onmessage = JOB.JOBStreamCallback;
|
||||
JOB.ScanContext.drawImage(stream,0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height);
|
||||
JOB.DecoderWorker.postMessage({
|
||||
scan : JOB.ScanContext.getImageData(0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height).data,
|
||||
scanWidth : JOB.ScanCanvas.width,
|
||||
scanHeight : JOB.ScanCanvas.height,
|
||||
multiple : JOB.Config.Multiple,
|
||||
decodeFormats : JOB.Config.DecodeFormats,
|
||||
cmd : "normal",
|
||||
rotation : 1,
|
||||
});
|
||||
var onmessage = JOB.DecoderWorker.onmessage;
|
||||
JOB.DecoderWorker.onmessage = function (data) {
|
||||
onmessage(data);
|
||||
if (data.data.success !== 'localization') {
|
||||
console.log('onmessage', data);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// Stops the decoding of a stream.
|
||||
StopStreamDecode : function() {
|
||||
JOB.DecodeStreamActive = false;
|
||||
JOB.Decoded = [];
|
||||
},
|
||||
|
||||
JOBDecodeImage : function (image,orientation,sceneCaptureType) {
|
||||
if(orientation == 8 || orientation == 6) {
|
||||
if(sceneCaptureType == "Landscape" && image.width > image.height) {
|
||||
orientation = 1;
|
||||
JOB.ScanCanvas.width = 640;
|
||||
JOB.ScanCanvas.height = 480;
|
||||
} else {
|
||||
JOB.ScanCanvas.width = 480;
|
||||
JOB.ScanCanvas.height = 640;
|
||||
}
|
||||
} else {
|
||||
JOB.ScanCanvas.width = 640;
|
||||
JOB.ScanCanvas.height = 480;
|
||||
}
|
||||
JOB.DecoderWorker.onmessage = JOB.JOBImageCallback;
|
||||
JOB.ScanContext.drawImage(image,0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height);
|
||||
JOB.Orientation = orientation;
|
||||
JOB.DecoderWorker.postMessage({
|
||||
scan : JOB.ScanContext.getImageData(0,0,JOB.ScanCanvas.width,JOB.ScanCanvas.height).data,
|
||||
scanWidth : JOB.ScanCanvas.width,
|
||||
scanHeight : JOB.ScanCanvas.height,
|
||||
multiple : JOB.Config.Multiple,
|
||||
decodeFormats : JOB.Config.DecodeFormats,
|
||||
cmd : "normal",
|
||||
rotation : orientation,
|
||||
postOrientation : JOB.PostOrientation
|
||||
});
|
||||
},
|
||||
|
||||
DetectVerticalSquash : function (img) {
|
||||
var ih = img.naturalHeight;
|
||||
var canvas = JOB.SquashCanvas;
|
||||
canvas.width = 1;
|
||||
canvas.height = ih;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
try {
|
||||
var data = ctx.getImageData(0, 0, 1, ih).data;
|
||||
} catch (err) {
|
||||
console.log("Cannot check verticalSquash: CORS?");
|
||||
return 1;
|
||||
}
|
||||
var sy = 0;
|
||||
var ey = ih;
|
||||
var py = ih;
|
||||
while (py > sy) {
|
||||
var alpha = data[(py - 1) * 4 + 3];
|
||||
if (alpha === 0) {
|
||||
ey = py;
|
||||
} else {
|
||||
sy = py;
|
||||
}
|
||||
py = (ey + sy) >> 1;
|
||||
}
|
||||
var ratio = (py / ih);
|
||||
return (ratio===0)?1:ratio;
|
||||
},
|
||||
|
||||
FixCanvas : function (canvas)
|
||||
{
|
||||
var ctx = canvas.getContext('2d');
|
||||
var drawImage = ctx.drawImage;
|
||||
ctx.drawImage = function(img, sx, sy, sw, sh, dx, dy, dw, dh)
|
||||
{
|
||||
var vertSquashRatio = 1;
|
||||
if (!!img && img.nodeName == 'IMG')
|
||||
{
|
||||
vertSquashRatio = JOB.DetectVerticalSquash(img);
|
||||
sw || (sw = img.naturalWidth);
|
||||
sh || (sh = img.naturalHeight);
|
||||
}
|
||||
if (arguments.length == 9)
|
||||
drawImage.call(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
|
||||
else if (typeof sw != 'undefined')
|
||||
drawImage.call(ctx, img, sx, sy, sw, sh / vertSquashRatio);
|
||||
else
|
||||
drawImage.call(ctx, img, sx, sy);
|
||||
};
|
||||
return canvas;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user