Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

worker.ts 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import pixelmatch from 'pixelmatch';
  2. import {
  3. CLEAR_TIMEOUT,
  4. MAX_FILE_SIZE,
  5. PERCENTAGE_LOWER_BOUND,
  6. SET_TIMEOUT,
  7. TIMEOUT_TICK
  8. } from './constants';
  9. let timer: ReturnType<typeof setTimeout>;
  10. const canvas = new OffscreenCanvas(0, 0);
  11. const ctx = canvas.getContext('2d');
  12. let storedImageData: ImageData | undefined;
  13. /**
  14. * Sends Blob with the screenshot to main thread.
  15. *
  16. * @param {ImageData} imageData - The image of the screenshot.
  17. * @returns {void}
  18. */
  19. async function sendBlob(imageData: ImageData) {
  20. let imageBlob = await canvas.convertToBlob({ type: 'image/jpeg' });
  21. if (imageBlob.size > MAX_FILE_SIZE) {
  22. const quality = Number((MAX_FILE_SIZE / imageBlob.size).toFixed(2)) * 0.92;
  23. imageBlob = await canvas.convertToBlob({ type: 'image/jpeg',
  24. quality });
  25. }
  26. storedImageData = imageData;
  27. postMessage({
  28. id: TIMEOUT_TICK,
  29. imageBlob
  30. });
  31. }
  32. /**
  33. * Sends empty message to main thread.
  34. *
  35. * @returns {void}
  36. */
  37. function sendEmpty() {
  38. postMessage({
  39. id: TIMEOUT_TICK
  40. });
  41. }
  42. /**
  43. * Draws the image bitmap on the canvas and checks the difference percent with the previous image
  44. * if there is no previous image the percentage is not calculated.
  45. *
  46. * @param {ImageBitmap} imageBitmap - The image bitmap that is drawn on canvas.
  47. * @returns {void}
  48. */
  49. function checkScreenshot(imageBitmap: ImageBitmap) {
  50. const { height, width } = imageBitmap;
  51. if (canvas.width !== width) {
  52. canvas.width = width;
  53. }
  54. if (canvas.height !== height) {
  55. canvas.height = height;
  56. }
  57. ctx?.drawImage(imageBitmap, 0, 0, width, height);
  58. const imageData = ctx?.getImageData(0, 0, width, height);
  59. imageBitmap.close();
  60. if (!imageData) {
  61. sendEmpty();
  62. return;
  63. }
  64. if (!storedImageData || imageData.data.length !== storedImageData.data.length) {
  65. sendBlob(imageData);
  66. return;
  67. }
  68. let numOfPixels = 0;
  69. try {
  70. numOfPixels = pixelmatch(
  71. imageData.data,
  72. storedImageData.data,
  73. null,
  74. width,
  75. height);
  76. } catch {
  77. sendEmpty();
  78. return;
  79. }
  80. const percent = numOfPixels / imageData.data.length * 100;
  81. if (percent >= PERCENTAGE_LOWER_BOUND) {
  82. sendBlob(imageData);
  83. } else {
  84. sendEmpty();
  85. }
  86. }
  87. onmessage = function(request) {
  88. switch (request.data.id) {
  89. case SET_TIMEOUT: {
  90. timer = setTimeout(async () => {
  91. const imageBitmap = request.data.imageBitmap;
  92. if (imageBitmap) {
  93. checkScreenshot(imageBitmap);
  94. } else {
  95. sendEmpty();
  96. }
  97. }, request.data.timeMs);
  98. break;
  99. }
  100. case CLEAR_TIMEOUT: {
  101. if (timer) {
  102. clearTimeout(timer);
  103. }
  104. break;
  105. }
  106. }
  107. };