From 6d9c826b1d7be74403763d0e040f47891afebab5 Mon Sep 17 00:00:00 2001 From: Alikia2x Date: Thu, 2 May 2024 15:48:26 +0800 Subject: [PATCH] fix: background zoom mismatch between cached and real-time calculated result --- src/components/background.svelte | 37 ++++++++++++-------- src/lib/graphics/blob2imageData.ts | 17 +++++++++ src/lib/graphics/imageData2blob.ts | 11 ++++++ src/lib/graphics/index.ts | 55 ++++++++++++------------------ src/lib/storage.ts | 8 +++++ src/routes/+page.svelte | 1 - 6 files changed, 81 insertions(+), 48 deletions(-) create mode 100644 src/lib/graphics/blob2imageData.ts create mode 100644 src/lib/graphics/imageData2blob.ts create mode 100644 src/lib/storage.ts diff --git a/src/components/background.svelte b/src/components/background.svelte index 9b59aeb..2e96f35 100644 --- a/src/components/background.svelte +++ b/src/components/background.svelte @@ -1,20 +1,29 @@ @@ -37,8 +46,8 @@ } canvas { position: relative; - width: 110%; - height: 110%; object-fit: cover; + width: 100%; + height: 100%; } diff --git a/src/lib/graphics/blob2imageData.ts b/src/lib/graphics/blob2imageData.ts new file mode 100644 index 0000000..2383be8 --- /dev/null +++ b/src/lib/graphics/blob2imageData.ts @@ -0,0 +1,17 @@ +export default function blobToImageData(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (event) => { + const arrayBuffer = event.target?.result as ArrayBuffer; + const dataView = new DataView(arrayBuffer); + const width = dataView.getUint32(0, true); // Read width from little-endian bytes + const height = dataView.getUint32(4, true); // Read height from little-endian bytes + const byteArray = new Uint8ClampedArray(arrayBuffer, 8); // Skip the header + resolve(new ImageData(byteArray, width, height)); + }; + reader.onerror = () => { + reject(new Error("Failed to read Blob as ArrayBuffer")); + }; + reader.readAsArrayBuffer(blob); + }); +} diff --git a/src/lib/graphics/imageData2blob.ts b/src/lib/graphics/imageData2blob.ts new file mode 100644 index 0000000..3b41feb --- /dev/null +++ b/src/lib/graphics/imageData2blob.ts @@ -0,0 +1,11 @@ +export default function imageDataToBlob(imageData: ImageData): Blob { + const width = imageData.width; + const height = imageData.height; + const data = new Uint8ClampedArray(imageData.data); + const header = new Uint8Array(8); // 4 bytes for width, 4 bytes for height + const dataView = new DataView(header.buffer); + dataView.setUint32(0, width, true); // Store width in little-endian + dataView.setUint32(4, height, true); // Store height in little-endian + const blob = new Blob([header, data], { type: 'image/png' }); + return blob; +} \ No newline at end of file diff --git a/src/lib/graphics/index.ts b/src/lib/graphics/index.ts index 148b4df..1380196 100644 --- a/src/lib/graphics/index.ts +++ b/src/lib/graphics/index.ts @@ -1,46 +1,34 @@ -import { gaussianBlurHorizontal, gaussianBlurVertical, applyFilter } from "./utils"; +import { gaussianBlurHorizontal, gaussianBlurVertical, applyFilter } from './utils'; -export async function processImage(blockSize: number, resolutionFactor:number, radius:number, path: string, canvas: HTMLCanvasElement) { - const ctx = canvas.getContext("2d")!; +export function processImage( + blockSize: number, + resolutionFactor: number, + radius: number, + path: string, + canvas: HTMLCanvasElement, + callback: (resultImageData: ImageData) => void +) { + const ctx = canvas.getContext('2d')!; const image = new Image(); image.src = path; // Replace with your image path image.onload = function () { // Resize image to 1/9 of the original resolution + const width = image.width; + const height = image.height; const resizedWidth = image.width / resolutionFactor; const resizedHeight = image.height / resolutionFactor; - const num_blocks_x = Math.floor(resizedWidth / blockSize); - const num_blocks_y = Math.floor(resizedHeight / blockSize); - canvas.width = resizedWidth; canvas.height = resizedHeight; - - for (let i = 0; i < num_blocks_y; i++) { - for (let j = 0; j < num_blocks_x; j++) { - const block = document.createElement("canvas"); - block.width = blockSize; - block.height = blockSize; - - const blockCtx = block.getContext("2d")!; - blockCtx.drawImage( - image, - j * blockSize * resolutionFactor, - i * blockSize * resolutionFactor, - blockSize * resolutionFactor, - blockSize * resolutionFactor, - 0, - 0, - blockSize, - blockSize - ); - - applyFilter(block); - - ctx.drawImage(block, j * blockSize, i * blockSize); - } - } + const block = document.createElement('canvas'); + const blockCtx = block.getContext('2d')!; + block.width = image.width; + block.height = image.height; + blockCtx.drawImage(image, 0, 0, width, height, 0, 0, resizedWidth, resizedHeight); + applyFilter(block); + ctx.drawImage(block, 0, 0); // Horizontal Gaussian blur const imageDataHorizontal = ctx.getImageData(0, 0, canvas.width, canvas.height); @@ -50,6 +38,7 @@ export async function processImage(blockSize: number, resolutionFactor:number, r const imageDataVertical = blurredImageDataHorizontal; const blurredImageData = gaussianBlurVertical(imageDataVertical, radius); - ctx.putImageData(blurredImageData, 0, 0); + ctx.putImageData(blurredImageData, 0, 0, 0, 0, width, height); + callback(blurredImageData); }; -} \ No newline at end of file +} diff --git a/src/lib/storage.ts b/src/lib/storage.ts new file mode 100644 index 0000000..0424ae6 --- /dev/null +++ b/src/lib/storage.ts @@ -0,0 +1,8 @@ +import localforage from "localforage"; + +localforage.config({ + driver: localforage.INDEXEDDB, + name: 'audioDB' +}); + +export default localforage; \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index d846875..d02c9a7 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -15,7 +15,6 @@ // Handle audio input change audioInput.addEventListener('change', function (e: any) { const file: File = e.target.files[0]; - console.log(file.size); if (file) { localforage.setItem(audioId + '-file', file); }