(page: Page, png: Buffer)
| 726 | } |
| 727 | |
| 728 | async function getScreenshotStats(page: Page, png: Buffer): Promise<ScreenshotStats> { |
| 729 | return page.evaluate(async (base64) => { |
| 730 | const image = new Image(); |
| 731 | const loaded = new Promise<void>((resolve, reject) => { |
| 732 | image.onload = () => resolve(); |
| 733 | image.onerror = () => reject(new Error('Failed to decode screenshot')); |
| 734 | }); |
| 735 | image.src = `data:image/png;base64,${base64}`; |
| 736 | await loaded; |
| 737 | |
| 738 | const canvas = document.createElement('canvas'); |
| 739 | canvas.width = image.naturalWidth; |
| 740 | canvas.height = image.naturalHeight; |
| 741 | const context = canvas.getContext('2d'); |
| 742 | if (!context) throw new Error('Failed to create screenshot stats canvas context'); |
| 743 | context.drawImage(image, 0, 0); |
| 744 | const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data; |
| 745 | let visiblePixelCount = 0; |
| 746 | let nonBlackPixelCount = 0; |
| 747 | let lumaSum = 0; |
| 748 | for (let index = 0; index < pixels.length; index += 4) { |
| 749 | const alpha = pixels[index + 3]; |
| 750 | if (alpha === 0) continue; |
| 751 | visiblePixelCount += 1; |
| 752 | const red = pixels[index]; |
| 753 | const green = pixels[index + 1]; |
| 754 | const blue = pixels[index + 2]; |
| 755 | const luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue; |
| 756 | lumaSum += luma; |
| 757 | if (red + green + blue > 8) { |
| 758 | nonBlackPixelCount += 1; |
| 759 | } |
| 760 | } |
| 761 | |
| 762 | return { |
| 763 | width: canvas.width, |
| 764 | height: canvas.height, |
| 765 | visiblePixelCount, |
| 766 | nonBlackPixelCount, |
| 767 | meanLuma: visiblePixelCount > 0 ? lumaSum / visiblePixelCount : 0, |
| 768 | }; |
| 769 | }, png.toString('base64')); |
| 770 | } |
| 771 | |
| 772 | async function captureNonBlankSceneCenterSamplesUntilWebGpu( |
| 773 | page: Page, |
no test coverage detected