123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import pixelmatch from 'pixelmatch';
-
- import {
- CLEAR_TIMEOUT,
- MAX_FILE_SIZE,
- PERCENTAGE_LOWER_BOUND,
- SET_TIMEOUT,
- TIMEOUT_TICK
- } from './constants';
-
-
- let timer: ReturnType<typeof setTimeout>;
- const canvas = new OffscreenCanvas(0, 0);
- const ctx = canvas.getContext('2d');
- let storedImageData: ImageData | undefined;
-
- /**
- * Sends Blob with the screenshot to main thread.
- *
- * @param {ImageData} imageData - The image of the screenshot.
- * @returns {void}
- */
- async function sendBlob(imageData: ImageData) {
- let imageBlob = await canvas.convertToBlob({ type: 'image/jpeg' });
-
- if (imageBlob.size > MAX_FILE_SIZE) {
- const quality = Number((MAX_FILE_SIZE / imageBlob.size).toFixed(2)) * 0.92;
-
- imageBlob = await canvas.convertToBlob({ type: 'image/jpeg',
- quality });
- }
-
- storedImageData = imageData;
-
- postMessage({
- id: TIMEOUT_TICK,
- imageBlob
- });
- }
-
- /**
- * Sends empty message to main thread.
- *
- * @returns {void}
- */
- function sendEmpty() {
- postMessage({
- id: TIMEOUT_TICK
- });
- }
-
- /**
- * Draws the image bitmap on the canvas and checks the difference percent with the previous image
- * if there is no previous image the percentage is not calculated.
- *
- * @param {ImageBitmap} imageBitmap - The image bitmap that is drawn on canvas.
- * @returns {void}
- */
- function checkScreenshot(imageBitmap: ImageBitmap) {
- const { height, width } = imageBitmap;
-
- if (canvas.width !== width) {
- canvas.width = width;
- }
-
- if (canvas.height !== height) {
- canvas.height = height;
- }
-
- ctx?.drawImage(imageBitmap, 0, 0, width, height);
- const imageData = ctx?.getImageData(0, 0, width, height);
-
- imageBitmap.close();
-
- if (!imageData) {
- sendEmpty();
-
- return;
- }
-
- if (!storedImageData || imageData.data.length !== storedImageData.data.length) {
- sendBlob(imageData);
-
- return;
- }
-
- let numOfPixels = 0;
-
- try {
- numOfPixels = pixelmatch(
- imageData.data,
- storedImageData.data,
- null,
- width,
- height);
- } catch {
- sendEmpty();
-
- return;
- }
-
- const percent = numOfPixels / imageData.data.length * 100;
-
- if (percent >= PERCENTAGE_LOWER_BOUND) {
- sendBlob(imageData);
- } else {
- sendEmpty();
- }
- }
-
- onmessage = function(request) {
- switch (request.data.id) {
- case SET_TIMEOUT: {
- timer = setTimeout(async () => {
- const imageBitmap = request.data.imageBitmap;
-
- if (imageBitmap) {
- checkScreenshot(imageBitmap);
- } else {
- sendEmpty();
- }
- }, request.data.timeMs);
- break;
- }
- case CLEAR_TIMEOUT: {
- if (timer) {
- clearTimeout(timer);
- }
- break;
- }
- }
- };
|