@zxing/library
Advanced tools
Comparing version 0.12.4 to 0.13.0
@@ -17,6 +17,16 @@ import { VideoInputDevice } from './VideoInputDevice'; | ||
/** | ||
* The HTML video element, used to display the camera stream. | ||
* If navigator is present. | ||
*/ | ||
protected videoElement: HTMLVideoElement; | ||
readonly hasNavigator: boolean; | ||
readonly isMediaDevicesSuported: boolean; | ||
readonly canEnumerateDevices: boolean; | ||
/** | ||
* The HTML canvas element, used to draw the video or image's frame for decoding. | ||
*/ | ||
protected captureCanvas: HTMLCanvasElement; | ||
/** | ||
* The HTML canvas element context. | ||
*/ | ||
protected captureCanvasContext: CanvasRenderingContext2D; | ||
/** | ||
* The HTML image element, used as a fallback for the video element when decoding. | ||
@@ -26,14 +36,18 @@ */ | ||
/** | ||
* The HTML canvas element, used to draw the video or image's frame for decoding. | ||
* Should contain the current registered listener for image loading, | ||
* used to unregister that listener when needed. | ||
*/ | ||
protected canvasElement: HTMLCanvasElement; | ||
protected imageLoadedEventListener: EventListener; | ||
/** | ||
* The HTML canvas element context. | ||
* The stream output from camera. | ||
*/ | ||
protected canvasElementContext: CanvasRenderingContext2D; | ||
protected stream: MediaStream; | ||
/** | ||
* Some timeout's Id. | ||
*/ | ||
protected timeoutHandler: number; | ||
/** | ||
* The stream output from camera. | ||
* The HTML video element, used to display the camera stream. | ||
*/ | ||
protected stream: MediaStream; | ||
protected videoElement: HTMLVideoElement; | ||
/** | ||
@@ -55,7 +69,2 @@ * Should contain the current registered listener for video loaded-metadata, | ||
/** | ||
* Should contain the current registered listener for image loading, | ||
* used to unregister that listener when needed. | ||
*/ | ||
protected imageLoadedEventListener: EventListener; | ||
/** | ||
* Creates an instance of BrowserCodeReader. | ||
@@ -69,2 +78,6 @@ * @param {Reader} reader The reader instance to decode the barcode | ||
/** | ||
* Lists all the available video input devices. | ||
*/ | ||
listVideoInputDevices(): Promise<MediaDeviceInfo[]>; | ||
/** | ||
* Obtain the list of available devices with type 'videoinput'. | ||
@@ -75,9 +88,15 @@ * | ||
* @memberOf BrowserCodeReader | ||
* | ||
* @deprecated Use `discoverVideoInputDevices` instead. | ||
*/ | ||
getVideoInputDevices(): Promise<VideoInputDevice[]>; | ||
/** | ||
* Let's you find a device using it's Id. | ||
*/ | ||
findDeviceById(deviceId: string): Promise<MediaDeviceInfo>; | ||
/** | ||
* Decodes the barcode from the device specified by deviceId while showing the video in the specified video element. | ||
* | ||
* @param {string} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. | ||
* @param {(string|HTMLVideoElement)} [videoElement] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. | ||
* @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. | ||
* @returns {Promise<Result>} The decoding result. | ||
@@ -87,3 +106,3 @@ * | ||
*/ | ||
decodeFromInputVideoDevice(deviceId?: string, videoElement?: string | HTMLVideoElement): Promise<Result>; | ||
decodeFromInputVideoDevice(deviceId?: string, videoSource?: string | HTMLVideoElement): Promise<Result>; | ||
/** | ||
@@ -93,8 +112,13 @@ * Sets the new stream and request a new decoding-with-delay. | ||
* @param stream The stream to be shown in the video element. | ||
* @param callbackFn A callback for the decode method. | ||
* @param decodeFn A callback for the decode method. | ||
* | ||
* @todo Return Promise<Result> | ||
*/ | ||
protected startDecodeFromStream(stream: MediaStream, callbackFn?: (...args: any[]) => any): void; | ||
protected attachStreamToVideo(stream: MediaStream, videoSource: string | HTMLVideoElement): Promise<HTMLVideoElement>; | ||
/** | ||
* | ||
* @param videoElement | ||
*/ | ||
playVideoAsync(videoElement: HTMLVideoElement): Promise<void>; | ||
/** | ||
* Binds listeners and callbacks to the videoElement. | ||
@@ -105,3 +129,3 @@ * | ||
*/ | ||
protected bindEvents(videoElement: HTMLVideoElement, listener: EventListener): void; | ||
protected playVideo(videoElement: HTMLVideoElement, playCallback: EventListener): void; | ||
/** | ||
@@ -118,9 +142,16 @@ * Decodes a barcode form a video url. | ||
/** | ||
* | ||
*/ | ||
private _decodeFromVideoSource; | ||
/** | ||
* Sets a HTMLVideoElement for scanning or creates a new one. | ||
* | ||
* @param videoElement The HTMLVideoElement to be set. | ||
* @param videoSrc The HTMLVideoElement to be set. | ||
*/ | ||
protected prepareVideoElement(videoElement?: HTMLVideoElement | string): void; | ||
protected getMediaElement(mediaElementId: string, type: string): HTMLElement; | ||
protected prepareVideoElement(videoSrc?: HTMLVideoElement | string): HTMLVideoElement; | ||
/** | ||
* Searches and validates a media element. | ||
*/ | ||
protected getMediaElement(mediaElementId: string, type: string): HTMLVisualMediaElement; | ||
/** | ||
* Decodes the barcode from an image. | ||
@@ -135,10 +166,27 @@ * | ||
decodeFromImage(imageElement?: string | HTMLImageElement, imageUrl?: string): Promise<Result>; | ||
/** | ||
* Decodes something from an image HTML element. | ||
*/ | ||
decodeFromImageElement(imageElement: string | HTMLImageElement, imageUrl: string): Promise<Result>; | ||
/** | ||
* Promise constructor. | ||
*/ | ||
private _decodeFromImageElement; | ||
/** | ||
* Decodes an image from a URL. | ||
*/ | ||
decodeFromImageUrl(imageUrl?: string): Promise<Result>; | ||
/** | ||
* Promise constructor. | ||
*/ | ||
private _decodeFromImageUrl; | ||
private _decodeOnLoadImage; | ||
protected isImageLoaded(img: HTMLImageElement): boolean; | ||
protected prepareImageElement(imageElement?: string | HTMLImageElement): void; | ||
protected decodeOnceWithDelay(resolve: (result: Result) => any, reject: (error: any) => any): void; | ||
protected decodeOnce(resolve: (result: Result) => any, reject: (error: any) => any, retryIfNotFound?: boolean, retryIfChecksumOrFormatError?: boolean): void; | ||
protected prepareImageElement(imageSrc?: HTMLImageElement | string): HTMLImageElement; | ||
private decodeWithRetryAndDelay; | ||
private decodeWithRetry; | ||
/** | ||
* Gets the BinaryBitmap for ya! (and decodes it) | ||
*/ | ||
protected decode(): Result; | ||
protected decode(element: HTMLVisualMediaElement): Result; | ||
/** | ||
@@ -151,2 +199,10 @@ * Creates a binaryBitmap based in some image source. | ||
/** | ||
* | ||
*/ | ||
protected getCaptureCanvasContext(): CanvasRenderingContext2D; | ||
/** | ||
* | ||
*/ | ||
protected getCaptureCanvas(): HTMLCanvasElement; | ||
/** | ||
* Ovewriting this allows you to manipulate the snapshot image in anyway you want before decode. | ||
@@ -162,3 +218,3 @@ */ | ||
*/ | ||
protected prepareCaptureCanvas(): void; | ||
protected createCaptureCanvas(): HTMLCanvasElement; | ||
/** | ||
@@ -174,3 +230,9 @@ * Stops the continuous scan and cleans the stream. | ||
reset(): void; | ||
private _destroyVideoElement; | ||
private _destroyImageElement; | ||
/** | ||
* Cleans canvas references π | ||
*/ | ||
private _destroyCaptureCanvas; | ||
/** | ||
* Defines what the videoElement src will be. | ||
@@ -181,3 +243,3 @@ * | ||
*/ | ||
bindVideoSrc(videoElement: HTMLVideoElement, stream: MediaStream): void; | ||
addVideoSource(videoElement: HTMLVideoElement, stream: MediaStream): void; | ||
/** | ||
@@ -188,4 +250,4 @@ * Unbinds a HTML video src property. | ||
*/ | ||
unbindVideoSrc(videoElement: HTMLVideoElement): void; | ||
cleanVideoSource(videoElement: HTMLVideoElement): void; | ||
} | ||
export {}; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -30,3 +65,63 @@ var HTMLCanvasElementLuminanceSource_1 = require("./HTMLCanvasElementLuminanceSource"); | ||
} | ||
Object.defineProperty(BrowserCodeReader.prototype, "hasNavigator", { | ||
/** | ||
* If navigator is present. | ||
*/ | ||
get: function () { | ||
return typeof navigator !== 'undefined'; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(BrowserCodeReader.prototype, "isMediaDevicesSuported", { | ||
get: function () { | ||
return this.hasNavigator && !!navigator.mediaDevices; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
Object.defineProperty(BrowserCodeReader.prototype, "canEnumerateDevices", { | ||
get: function () { | ||
return !!(this.isMediaDevicesSuported && navigator.mediaDevices.enumerateDevices); | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Lists all the available video input devices. | ||
*/ | ||
BrowserCodeReader.prototype.listVideoInputDevices = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var devices, videoDevices, _i, devices_1, device, kind, deviceId, label, groupId, videoDevice; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!this.hasNavigator) { | ||
throw new Error('Can\'t enumerate devices, navigator is not present.'); | ||
} | ||
if (!this.canEnumerateDevices) { | ||
throw new Error('Can\'t enumerate devices, method not supported.'); | ||
} | ||
return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()]; | ||
case 1: | ||
devices = _a.sent(); | ||
videoDevices = []; | ||
for (_i = 0, devices_1 = devices; _i < devices_1.length; _i++) { | ||
device = devices_1[_i]; | ||
kind = device.kind === 'video' ? 'videoinput' : device.kind; | ||
if (kind !== 'videoinput') { | ||
continue; | ||
} | ||
deviceId = device.deviceId || device.id; | ||
label = device.label || "Video device " + (videoDevices.length + 1); | ||
groupId = device.groupId; | ||
videoDevice = { deviceId: deviceId, label: label, kind: kind, groupId: groupId }; | ||
videoDevices.push(videoDevice); | ||
} | ||
return [2 /*return*/, videoDevices]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Obtain the list of available devices with type 'videoinput'. | ||
@@ -37,20 +132,15 @@ * | ||
* @memberOf BrowserCodeReader | ||
* | ||
* @deprecated Use `discoverVideoInputDevices` instead. | ||
*/ | ||
BrowserCodeReader.prototype.getVideoInputDevices = function () { | ||
return new Promise(function (resolve, reject) { | ||
navigator.mediaDevices.enumerateDevices() | ||
.then(function (devices) { | ||
var sources = new Array(); | ||
var c = 0; | ||
for (var i = 0, length_1 = devices.length; i !== length_1; i++) { | ||
var device = devices[i]; | ||
if (device.kind === 'videoinput') { | ||
sources.push(new VideoInputDevice_1.VideoInputDevice(device.deviceId, device.label || "Video source " + c)); | ||
c++; | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var devices; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.listVideoInputDevices()]; | ||
case 1: | ||
devices = _a.sent(); | ||
return [2 /*return*/, devices.map(function (d) { return new VideoInputDevice_1.VideoInputDevice(d.deviceId, d.label); })]; | ||
} | ||
resolve(sources); | ||
}) | ||
.catch(function (err) { | ||
reject(err); | ||
}); | ||
@@ -60,6 +150,25 @@ }); | ||
/** | ||
* Let's you find a device using it's Id. | ||
*/ | ||
BrowserCodeReader.prototype.findDeviceById = function (deviceId) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var devices; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.listVideoInputDevices()]; | ||
case 1: | ||
devices = _a.sent(); | ||
if (!devices) { | ||
return [2 /*return*/, null]; | ||
} | ||
return [2 /*return*/, devices.find(function (x) { return x.deviceId === deviceId; })]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Decodes the barcode from the device specified by deviceId while showing the video in the specified video element. | ||
* | ||
* @param {string} [deviceId] the id of one of the devices obtained after calling getVideoInputDevices. Can be undefined, in this case it will decode from one of the available devices, preffering the main camera (environment facing) if available. | ||
* @param {(string|HTMLVideoElement)} [videoElement] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. | ||
* @param {string|HTMLVideoElement} [video] the video element in page where to show the video while decoding. Can be either an element id or directly an HTMLVideoElement. Can be undefined, in which case no video will be shown. | ||
* @returns {Promise<Result>} The decoding result. | ||
@@ -69,24 +178,26 @@ * | ||
*/ | ||
BrowserCodeReader.prototype.decodeFromInputVideoDevice = function (deviceId, videoElement) { | ||
var _this = this; | ||
this.reset(); | ||
this.prepareVideoElement(videoElement); | ||
var constraints; | ||
if (undefined === deviceId) { | ||
constraints = { | ||
video: { facingMode: 'environment' } | ||
}; | ||
} | ||
else { | ||
constraints = { | ||
video: { deviceId: { exact: deviceId } } | ||
}; | ||
} | ||
return new Promise(function (resolve, reject) { | ||
var callback = function () { | ||
_this.decodeOnceWithDelay(resolve, reject); | ||
}; | ||
navigator.mediaDevices.getUserMedia(constraints) | ||
.then(function (stream) { return _this.startDecodeFromStream(stream, callback); }) | ||
.catch(function (error) { return reject(error); }); | ||
BrowserCodeReader.prototype.decodeFromInputVideoDevice = function (deviceId, videoSource) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var videoConstraints, constraints, stream, video; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
this.reset(); | ||
if (!deviceId) { | ||
videoConstraints = { facingMode: 'environment' }; | ||
} | ||
else { | ||
videoConstraints = { deviceId: { exact: deviceId } }; | ||
} | ||
constraints = { video: videoConstraints }; | ||
return [4 /*yield*/, navigator.mediaDevices.getUserMedia(constraints)]; | ||
case 1: | ||
stream = _a.sent(); | ||
return [4 /*yield*/, this.attachStreamToVideo(stream, videoSource)]; | ||
case 2: | ||
video = _a.sent(); | ||
return [2 /*return*/, new Promise(function (resolve, reject) { return _this.decodeWithRetryAndDelay(video, resolve, reject); })]; | ||
} | ||
}); | ||
}); | ||
@@ -98,15 +209,34 @@ }; | ||
* @param stream The stream to be shown in the video element. | ||
* @param callbackFn A callback for the decode method. | ||
* @param decodeFn A callback for the decode method. | ||
* | ||
* @todo Return Promise<Result> | ||
*/ | ||
BrowserCodeReader.prototype.startDecodeFromStream = function (stream, callbackFn) { | ||
this.stream = stream; | ||
if (!this.videoElement && this.stream.active) { | ||
return this.reset(); | ||
} | ||
this.bindVideoSrc(this.videoElement, stream); | ||
this.bindEvents(this.videoElement, callbackFn); | ||
BrowserCodeReader.prototype.attachStreamToVideo = function (stream, videoSource) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var videoElement; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
this.reset(); | ||
videoElement = this.prepareVideoElement(videoSource); | ||
this.addVideoSource(videoElement, stream); | ||
this.videoElement = videoElement; | ||
this.stream = stream; | ||
return [4 /*yield*/, this.playVideoAsync(videoElement)]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/, videoElement]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* | ||
* @param videoElement | ||
*/ | ||
BrowserCodeReader.prototype.playVideoAsync = function (videoElement) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { return _this.playVideo(videoElement, function () { return resolve(); }); }); | ||
}; | ||
/** | ||
* Binds listeners and callbacks to the videoElement. | ||
@@ -117,5 +247,4 @@ * | ||
*/ | ||
BrowserCodeReader.prototype.bindEvents = function (videoElement, listener) { | ||
this.videoPlayingEventListener = listener; | ||
videoElement.addEventListener('playing', this.videoPlayingEventListener); | ||
BrowserCodeReader.prototype.playVideo = function (videoElement, playCallback) { | ||
videoElement.addEventListener('playing', playCallback); | ||
this.videoLoadedMetadataEventListener = function () { return videoElement.play(); }; | ||
@@ -135,17 +264,20 @@ videoElement.addEventListener('loadedmetadata', this.videoLoadedMetadataEventListener); | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { return _this._decodeFromVideoSource(videoElement, reject, resolve, videoUrl); }); | ||
}; | ||
/** | ||
* | ||
*/ | ||
BrowserCodeReader.prototype._decodeFromVideoSource = function (videoSource, reject, resolve, videoUrl) { | ||
var _this = this; | ||
this.reset(); | ||
this.prepareVideoElement(videoElement); | ||
return new Promise(function (resolve, reject) { | ||
_this.videoPlayEndedEventListener = function () { | ||
_this.stopStreams(); | ||
reject(new NotFoundException_1.default()); | ||
}; | ||
_this.videoElement.addEventListener('ended', _this.videoPlayEndedEventListener); | ||
_this.videoPlayingEventListener = function () { | ||
_this.decodeOnceWithDelay(resolve, reject); | ||
}; | ||
_this.videoElement.addEventListener('playing', _this.videoPlayingEventListener); | ||
_this.videoElement.setAttribute('autoplay', 'true'); | ||
_this.videoElement.setAttribute('src', videoUrl); | ||
}); | ||
var videoElement = this.prepareVideoElement(videoSource); | ||
this.videoPlayEndedEventListener = function () { | ||
_this.stopStreams(); | ||
reject(new NotFoundException_1.default('Video stream has ended before any code could be detected.')); | ||
}; | ||
videoElement.addEventListener('ended', this.videoPlayEndedEventListener); | ||
this.videoPlayingEventListener = function () { return _this.decodeWithRetryAndDelay(videoElement, resolve, reject); }; | ||
videoElement.addEventListener('playing', this.videoPlayingEventListener); | ||
videoElement.setAttribute('src', videoUrl); | ||
this.videoElement = videoElement; | ||
}; | ||
@@ -155,6 +287,7 @@ /** | ||
* | ||
* @param videoElement The HTMLVideoElement to be set. | ||
* @param videoSrc The HTMLVideoElement to be set. | ||
*/ | ||
BrowserCodeReader.prototype.prepareVideoElement = function (videoElement) { | ||
if (!videoElement && typeof document !== 'undefined') { | ||
BrowserCodeReader.prototype.prepareVideoElement = function (videoSrc) { | ||
var videoElement; | ||
if (!videoSrc && typeof document !== 'undefined') { | ||
videoElement = document.createElement('video'); | ||
@@ -164,5 +297,8 @@ videoElement.width = 200; | ||
} | ||
if (typeof videoElement === 'string') { | ||
videoElement = this.getMediaElement(videoElement, 'video'); | ||
if (typeof videoSrc === 'string') { | ||
videoElement = this.getMediaElement(videoSrc, 'video'); | ||
} | ||
if (videoSrc instanceof HTMLVideoElement) { | ||
videoElement = videoSrc; | ||
} | ||
// Needed for iOS 11 | ||
@@ -172,8 +308,10 @@ videoElement.setAttribute('autoplay', 'true'); | ||
videoElement.setAttribute('playsinline', 'true'); | ||
videoElement.setAttribute('autofocus', 'true'); | ||
this.videoElement = videoElement; | ||
return videoElement; | ||
}; | ||
/** | ||
* Searches and validates a media element. | ||
*/ | ||
BrowserCodeReader.prototype.getMediaElement = function (mediaElementId, type) { | ||
var mediaElement = document.getElementById(mediaElementId); | ||
if (null === mediaElement) { | ||
if (!mediaElement) { | ||
throw new ArgumentException_1.default("element with id '" + mediaElementId + "' not found"); | ||
@@ -196,24 +334,59 @@ } | ||
BrowserCodeReader.prototype.decodeFromImage = function (imageElement, imageUrl) { | ||
var _this = this; | ||
this.reset(); | ||
if (undefined === imageElement && undefined === imageUrl) { | ||
throw new ArgumentException_1.default('either imageElement with a src set or an url must be provided'); | ||
} | ||
this.prepareImageElement(imageElement); | ||
return new Promise(function (resolve, reject) { | ||
if (undefined !== imageUrl) { | ||
_this.imageLoadedEventListener = function () { | ||
_this.decodeOnce(resolve, reject, false, true); | ||
}; | ||
_this.imageElement.addEventListener('load', _this.imageLoadedEventListener); | ||
_this.imageElement.src = imageUrl; | ||
} | ||
else if (_this.isImageLoaded(_this.imageElement)) { | ||
_this.decodeOnce(resolve, reject, false, true); | ||
} | ||
else { | ||
throw new ArgumentException_1.default("either src or a loaded img should be provided"); | ||
} | ||
}); | ||
if (imageUrl && !imageElement) { | ||
return this.decodeFromImageUrl(imageUrl); | ||
} | ||
return this.decodeFromImageElement(imageElement, imageUrl); | ||
}; | ||
/** | ||
* Decodes something from an image HTML element. | ||
*/ | ||
BrowserCodeReader.prototype.decodeFromImageElement = function (imageElement, imageUrl) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { return _this._decodeFromImageElement(imageElement, resolve, reject); }); | ||
}; | ||
/** | ||
* Promise constructor. | ||
*/ | ||
BrowserCodeReader.prototype._decodeFromImageElement = function (imageElement, resolve, reject) { | ||
if (!imageElement) { | ||
throw new ArgumentException_1.default('An image element must be provided.'); | ||
} | ||
this.reset(); | ||
var image = this.prepareImageElement(imageElement); | ||
if (this.isImageLoaded(image)) { | ||
this.decodeWithRetry(image, resolve, reject, false, true); | ||
} | ||
else { | ||
this._decodeOnLoadImage(image, resolve, reject); | ||
} | ||
this.imageElement = image; | ||
}; | ||
/** | ||
* Decodes an image from a URL. | ||
*/ | ||
BrowserCodeReader.prototype.decodeFromImageUrl = function (imageUrl) { | ||
var _this = this; | ||
return new Promise(function (resolve, reject) { return _this._decodeFromImageUrl(imageUrl, resolve, reject); }); | ||
}; | ||
/** | ||
* Promise constructor. | ||
*/ | ||
BrowserCodeReader.prototype._decodeFromImageUrl = function (imageUrl, resolve, reject) { | ||
if (!imageUrl) { | ||
throw new ArgumentException_1.default('An URL must be provided.'); | ||
} | ||
this.reset(); | ||
var image = this.prepareImageElement(); | ||
this._decodeOnLoadImage(image, resolve, reject); | ||
image.src = imageUrl; | ||
this.imageElement = image; | ||
}; | ||
BrowserCodeReader.prototype._decodeOnLoadImage = function (imageElement, resolve, reject) { | ||
var _this = this; | ||
this.imageLoadedEventListener = function () { return _this.decodeWithRetry(imageElement, resolve, reject, false, true); }; | ||
imageElement.addEventListener('load', this.imageLoadedEventListener); | ||
}; | ||
BrowserCodeReader.prototype.isImageLoaded = function (img) { | ||
@@ -235,4 +408,5 @@ // During the onload event, IE correctly identifies any images that | ||
}; | ||
BrowserCodeReader.prototype.prepareImageElement = function (imageElement) { | ||
if (typeof imageElement === 'undefined') { | ||
BrowserCodeReader.prototype.prepareImageElement = function (imageSrc) { | ||
var imageElement; | ||
if (typeof imageSrc === 'undefined') { | ||
imageElement = document.createElement('img'); | ||
@@ -242,28 +416,31 @@ imageElement.width = 200; | ||
} | ||
if (typeof imageElement === 'string') { | ||
imageElement = this.getMediaElement(imageElement, 'img'); | ||
if (typeof imageSrc === 'string') { | ||
imageElement = this.getMediaElement(imageSrc, 'img'); | ||
} | ||
this.imageElement = imageElement; | ||
if (imageSrc instanceof HTMLImageElement) { | ||
imageElement = imageSrc; | ||
} | ||
return imageElement; | ||
}; | ||
BrowserCodeReader.prototype.decodeOnceWithDelay = function (resolve, reject) { | ||
this.timeoutHandler = window.setTimeout(this.decodeOnce.bind(this, resolve, reject), this.timeBetweenScansMillis); | ||
BrowserCodeReader.prototype.decodeWithRetryAndDelay = function (element, resolve, reject) { | ||
var _this = this; | ||
this.timeoutHandler = window.setTimeout(function () { return _this.decodeWithRetry(element, resolve, reject); }, this.timeBetweenScansMillis); | ||
}; | ||
BrowserCodeReader.prototype.decodeOnce = function (resolve, reject, retryIfNotFound, retryIfChecksumOrFormatError) { | ||
BrowserCodeReader.prototype.decodeWithRetry = function (element, resolve, reject, retryIfNotFound, retryIfChecksumOrFormatError) { | ||
if (retryIfNotFound === void 0) { retryIfNotFound = true; } | ||
if (retryIfChecksumOrFormatError === void 0) { retryIfChecksumOrFormatError = true; } | ||
try { | ||
var result = this.decode(); | ||
var result = this.decode(element); | ||
resolve(result); | ||
} | ||
catch (re) { | ||
if (retryIfNotFound && re instanceof NotFoundException_1.default) { | ||
// Not found, trying again | ||
this.decodeOnceWithDelay(resolve, reject); | ||
catch (e) { | ||
var ifNotFound = retryIfNotFound && e instanceof NotFoundException_1.default; | ||
var isChecksumOrFormatError = e instanceof ChecksumException_1.default || e instanceof FormatException_1.default; | ||
var ifChecksumOrFormat = isChecksumOrFormatError && retryIfChecksumOrFormatError; | ||
if (ifNotFound || ifChecksumOrFormat) { | ||
// trying again | ||
this.decodeWithRetryAndDelay(element, resolve, reject); | ||
} | ||
else if (retryIfChecksumOrFormatError && (re instanceof ChecksumException_1.default || re instanceof FormatException_1.default)) { | ||
// checksum or format error, trying again | ||
this.decodeOnceWithDelay(resolve, reject); | ||
} | ||
else { | ||
reject(re); | ||
reject(e); | ||
} | ||
@@ -275,5 +452,5 @@ } | ||
*/ | ||
BrowserCodeReader.prototype.decode = function () { | ||
BrowserCodeReader.prototype.decode = function (element) { | ||
// get binary bitmap for decode function | ||
var binaryBitmap = this.createBinaryBitmap(this.videoElement || this.imageElement); | ||
var binaryBitmap = this.createBinaryBitmap(element); | ||
return this.decodeBitmap(binaryBitmap); | ||
@@ -287,7 +464,6 @@ }; | ||
BrowserCodeReader.prototype.createBinaryBitmap = function (mediaElement) { | ||
if (undefined === this.canvasElementContext) { | ||
this.prepareCaptureCanvas(); | ||
} | ||
this.drawImageOnCanvas(this.canvasElementContext, mediaElement); | ||
var luminanceSource = new HTMLCanvasElementLuminanceSource_1.HTMLCanvasElementLuminanceSource(this.canvasElement); | ||
var ctx = this.getCaptureCanvasContext(); | ||
this.drawImageOnCanvas(ctx, mediaElement); | ||
var canvas = this.getCaptureCanvas(); | ||
var luminanceSource = new HTMLCanvasElementLuminanceSource_1.HTMLCanvasElementLuminanceSource(canvas); | ||
var hybridBinarizer = new HybridBinarizer_1.default(luminanceSource); | ||
@@ -297,2 +473,23 @@ return new BinaryBitmap_1.default(hybridBinarizer); | ||
/** | ||
* | ||
*/ | ||
BrowserCodeReader.prototype.getCaptureCanvasContext = function () { | ||
if (!this.captureCanvasContext) { | ||
var elem = this.getCaptureCanvas(); | ||
var ctx = elem.getContext('2d'); | ||
this.captureCanvasContext = ctx; | ||
} | ||
return this.captureCanvasContext; | ||
}; | ||
/** | ||
* | ||
*/ | ||
BrowserCodeReader.prototype.getCaptureCanvas = function () { | ||
if (!this.captureCanvas) { | ||
var elem = this.createCaptureCanvas(); | ||
this.captureCanvas = elem; | ||
} | ||
return this.captureCanvas; | ||
}; | ||
/** | ||
* Ovewriting this allows you to manipulate the snapshot image in anyway you want before decode. | ||
@@ -312,7 +509,6 @@ */ | ||
*/ | ||
BrowserCodeReader.prototype.prepareCaptureCanvas = function () { | ||
BrowserCodeReader.prototype.createCaptureCanvas = function () { | ||
if (typeof document === 'undefined') { | ||
this.canvasElement = undefined; | ||
this.canvasElementContext = undefined; | ||
return; | ||
this._destroyCaptureCanvas(); | ||
return null; | ||
} | ||
@@ -334,4 +530,3 @@ var canvasElement = document.createElement('canvas'); | ||
canvasElement.height = height; | ||
this.canvasElement = canvasElement; | ||
this.canvasElementContext = canvasElement.getContext('2d'); | ||
return canvasElement; | ||
}; | ||
@@ -356,24 +551,47 @@ /** | ||
this.stopStreams(); | ||
if (undefined !== this.videoPlayEndedEventListener && undefined !== this.videoElement) { | ||
// clean and forget about HTML elements | ||
this._destroyVideoElement(); | ||
this._destroyImageElement(); | ||
this._destroyCaptureCanvas(); | ||
}; | ||
BrowserCodeReader.prototype._destroyVideoElement = function () { | ||
if (!this.videoElement) { | ||
return; | ||
} | ||
// first gives freedon to the element π | ||
if (typeof this.videoPlayEndedEventListener !== 'undefined') { | ||
this.videoElement.removeEventListener('ended', this.videoPlayEndedEventListener); | ||
} | ||
if (undefined !== this.videoPlayingEventListener && undefined !== this.videoElement) { | ||
if (typeof this.videoPlayingEventListener !== 'undefined') { | ||
this.videoElement.removeEventListener('playing', this.videoPlayingEventListener); | ||
} | ||
if (undefined !== this.videoElement) { | ||
this.unbindVideoSrc(this.videoElement); | ||
this.videoElement = undefined; | ||
if (typeof this.videoLoadedMetadataEventListener !== 'undefined') { | ||
this.videoElement.removeEventListener('loadedmetadata', this.videoLoadedMetadataEventListener); | ||
} | ||
if (undefined !== this.videoPlayEndedEventListener && undefined !== this.imageElement) { | ||
// then forgets about that element π’ | ||
this.cleanVideoSource(this.videoElement); | ||
this.videoElement = undefined; | ||
}; | ||
BrowserCodeReader.prototype._destroyImageElement = function () { | ||
if (!this.imageElement) { | ||
return; | ||
} | ||
// first gives freedon to the element π | ||
if (undefined !== this.imageLoadedEventListener) { | ||
this.imageElement.removeEventListener('load', this.imageLoadedEventListener); | ||
} | ||
if (undefined !== this.imageElement) { | ||
this.imageElement.src = undefined; | ||
this.imageElement.removeAttribute('src'); | ||
this.imageElement = undefined; | ||
} | ||
this.canvasElementContext = undefined; | ||
this.canvasElement = undefined; | ||
// then forget about that element π’ | ||
this.imageElement.src = undefined; | ||
this.imageElement.removeAttribute('src'); | ||
this.imageElement = undefined; | ||
}; | ||
/** | ||
* Cleans canvas references π | ||
*/ | ||
BrowserCodeReader.prototype._destroyCaptureCanvas = function () { | ||
// then forget about that element π’ | ||
this.captureCanvasContext = undefined; | ||
this.captureCanvas = undefined; | ||
}; | ||
/** | ||
* Defines what the videoElement src will be. | ||
@@ -384,3 +602,3 @@ * | ||
*/ | ||
BrowserCodeReader.prototype.bindVideoSrc = function (videoElement, stream) { | ||
BrowserCodeReader.prototype.addVideoSource = function (videoElement, stream) { | ||
// Older browsers may not have `srcObject` | ||
@@ -401,3 +619,3 @@ try { | ||
*/ | ||
BrowserCodeReader.prototype.unbindVideoSrc = function (videoElement) { | ||
BrowserCodeReader.prototype.cleanVideoSource = function (videoElement) { | ||
try { | ||
@@ -409,2 +627,3 @@ videoElement.srcObject = null; | ||
} | ||
this.videoElement.removeAttribute('src'); | ||
}; | ||
@@ -411,0 +630,0 @@ return BrowserCodeReader; |
@@ -6,11 +6,16 @@ /** | ||
*/ | ||
export declare class VideoInputDevice { | ||
export declare class VideoInputDevice implements MediaDeviceInfo { | ||
deviceId: string; | ||
label: string; | ||
/** @inheritdoc */ | ||
readonly kind = "videoinput"; | ||
/** @inheritdoc */ | ||
readonly groupId: string; | ||
/** | ||
* Creates an instance of VideoInputDevice. | ||
* | ||
* @param {string} deviceId the video input device id | ||
* @param {string} label the label of the device if available | ||
*/ | ||
constructor(deviceId: string, label: string); | ||
constructor(deviceId: string, label: string, groupId?: string); | ||
} |
@@ -11,8 +11,12 @@ "use strict"; | ||
* Creates an instance of VideoInputDevice. | ||
* | ||
* @param {string} deviceId the video input device id | ||
* @param {string} label the label of the device if available | ||
*/ | ||
function VideoInputDevice(deviceId, label) { | ||
function VideoInputDevice(deviceId, label, groupId) { | ||
this.deviceId = deviceId; | ||
this.label = label; | ||
/** @inheritdoc */ | ||
this.kind = 'videoinput'; | ||
this.groupId = groupId || undefined; | ||
} | ||
@@ -19,0 +23,0 @@ return VideoInputDevice; |
{ | ||
"name": "@zxing/library", | ||
"version": "0.12.4", | ||
"version": "0.13.0", | ||
"description": "TypeScript port of ZXing multi-format 1D/2D barcode image processing library.", | ||
@@ -41,2 +41,3 @@ "keywords": [ | ||
}, | ||
"homepage": "https://zxing-js.github.io/library/", | ||
"private": false, | ||
@@ -105,3 +106,3 @@ "main": "./umd/index.min.js", | ||
"tslint": "^5.13.1", | ||
"typescript": "^3.3.3333", | ||
"typescript": "~3.3.3333", | ||
"uglify-js": "^3.4.9", | ||
@@ -108,0 +109,0 @@ "uglifyjs-webpack-plugin": "^2.1.2", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
2669096
21928
1