fix: background zoom mismatch between cached and real-time calculated result

This commit is contained in:
Alikia2x 2024-05-02 15:48:26 +08:00
parent 5afdaec8a0
commit 6d9c826b1d
6 changed files with 81 additions and 48 deletions

View File

@ -1,20 +1,29 @@
<script lang="ts">
import { processImage } from '$lib/graphics';
import localforage from 'localforage';
// Initialize IndexedDB
localforage.config({
driver: localforage.INDEXEDDB,
name: 'audioDB'
});
import blobToImageData from '$lib/graphics/blob2imageData';
import imageDataToBlob from '$lib/graphics/imageData2blob';
import localforage from '$lib/storage';
export let coverId: string;
let canvas: HTMLCanvasElement;
localforage.getItem(`${coverId}-cover`, function (err, file) {
console.log(file);
console.log(err);
let flag = false;
localforage.getItem(`${coverId}-cover-cache`, function (err, file) {
if (file) {
const path = URL.createObjectURL(file as File);
processImage(16, 4, 96, path, canvas);
const ctx = canvas.getContext('2d');
blobToImageData(file as Blob).then((imageData) => {
console.log(imageData);
ctx?.putImageData(imageData,0,0);
})
} else {
localforage.getItem(`${coverId}-cover`, function (err, file) {
if (file) {
const path = URL.createObjectURL(file as File);
processImage(16, 3, 96, path, canvas, (resultImageData: ImageData) => {
localforage.setItem(`${coverId}-cover-cache`, imageDataToBlob(resultImageData));
});
}
});
}
});
</script>
@ -37,8 +46,8 @@
}
canvas {
position: relative;
width: 110%;
height: 110%;
object-fit: cover;
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,17 @@
export default function blobToImageData(blob: Blob): Promise<ImageData> {
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);
});
}

View File

@ -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;
}

View File

@ -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);
};
}
}

8
src/lib/storage.ts Normal file
View File

@ -0,0 +1,8 @@
import localforage from "localforage";
localforage.config({
driver: localforage.INDEXEDDB,
name: 'audioDB'
});
export default localforage;

View File

@ -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);
}