105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
class Content {
|
|
private width : number = 19;
|
|
private height : number = 14;
|
|
|
|
private x : number;
|
|
private y : number;
|
|
private i : number;
|
|
private val : number;
|
|
|
|
private displayCanvas : HTMLCanvasElement;
|
|
private videoCanvas : HTMLCanvasElement;
|
|
|
|
private displayCtx : CanvasRenderingContext2D;
|
|
private videoCtx : CanvasRenderingContext2D;
|
|
|
|
private video : HTMLVideoElement;
|
|
|
|
constructor () {
|
|
const dpr : number = window.devicePixelRatio;
|
|
|
|
this.displayCanvas = document.getElementById('display') as HTMLCanvasElement;
|
|
this.displayCtx = this.displayCanvas.getContext('2d');
|
|
|
|
this.displayCanvas.height = this.height;
|
|
this.displayCanvas.width = this.width;
|
|
//
|
|
this.videoCanvas = document.getElementById('video') as HTMLCanvasElement; //document.createElement('canvas') as HTMLCanvasElement;
|
|
this.videoCtx = this.videoCanvas.getContext('2d');
|
|
|
|
this.startCamera();
|
|
}
|
|
|
|
async startCamera () {
|
|
const constraints : MediaStreamConstraints = {
|
|
video : {
|
|
width: { ideal: 4096 },
|
|
height: { ideal: 2160 },
|
|
facingMode: 'environment'
|
|
},
|
|
audio: false
|
|
}
|
|
try {
|
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
|
|
this.video = document.createElement('video') as HTMLVideoElement;
|
|
|
|
this.video.srcObject = stream;
|
|
this.video.height = stream.getVideoTracks()[0].getSettings().height;
|
|
this.video.width = stream.getVideoTracks()[0].getSettings().width;
|
|
this.video.play();
|
|
|
|
this.videoCanvas.height = this.video.height;
|
|
this.videoCanvas.width = this.video.width;
|
|
|
|
(document.querySelector('#data') as HTMLDivElement).innerText = `${this.video.width}x${this.video.height}`;
|
|
|
|
this.video.addEventListener('play', this.drawCanvas.bind(this));
|
|
} catch (error) {
|
|
console.error('Error accessing camera:', error);
|
|
}
|
|
}
|
|
|
|
private drawCanvas () {
|
|
this.videoCtx.drawImage(this.video, 0, 0, this.videoCanvas.width, this.videoCanvas.height);
|
|
this.parse();
|
|
requestAnimationFrame(this.drawCanvas.bind(this));
|
|
}
|
|
|
|
private parse () {
|
|
const rgba : ImageData = this.videoCtx.getImageData(
|
|
0, 0, this.videoCanvas.width, this.videoCanvas.height
|
|
).data as any;
|
|
|
|
let code : any = null
|
|
|
|
try {
|
|
//@ts-ignore
|
|
code = jsQR(rgba, this.videoCanvas.width, this.videoCanvas.height);
|
|
} catch (err) {
|
|
//
|
|
}
|
|
|
|
if (code !== null && code.binaryData.length === 266) {
|
|
(document.querySelector('#data') as HTMLDivElement).innerText = code.binaryData.toString();
|
|
console.dir(code);
|
|
this.display(code.binaryData);
|
|
} else {
|
|
console.log('No QR')
|
|
}
|
|
}
|
|
|
|
display (data : any[]) {
|
|
for (this.i = 0; this.i < data.length; this.i++) {
|
|
this.val = data[this.i];
|
|
this.x = this.i % this.width;
|
|
this.y = Math.floor(this.i / this.width);
|
|
this.displayCtx.fillStyle = `rgba(${this.val},${this.val},${this.val},1.0)`;
|
|
this.displayCtx.fillRect(this.x, this.y, 1, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
(function main () {
|
|
new Content();
|
|
})(); |