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"> <script lang="ts">
import { processImage } from '$lib/graphics'; import { processImage } from '$lib/graphics';
import localforage from 'localforage'; import blobToImageData from '$lib/graphics/blob2imageData';
// Initialize IndexedDB import imageDataToBlob from '$lib/graphics/imageData2blob';
localforage.config({ import localforage from '$lib/storage';
driver: localforage.INDEXEDDB,
name: 'audioDB'
});
export let coverId: string; export let coverId: string;
let canvas: HTMLCanvasElement; let canvas: HTMLCanvasElement;
let flag = false;
localforage.getItem(`${coverId}-cover-cache`, function (err, file) {
if (file) {
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) { localforage.getItem(`${coverId}-cover`, function (err, file) {
console.log(file);
console.log(err);
if (file) { if (file) {
const path = URL.createObjectURL(file as File); const path = URL.createObjectURL(file as File);
processImage(16, 4, 96, path, canvas); processImage(16, 3, 96, path, canvas, (resultImageData: ImageData) => {
localforage.setItem(`${coverId}-cover-cache`, imageDataToBlob(resultImageData));
});
}
});
} }
}); });
</script> </script>
@ -37,8 +46,8 @@
} }
canvas { canvas {
position: relative; position: relative;
width: 110%;
height: 110%;
object-fit: cover; object-fit: cover;
width: 100%;
height: 100%;
} }
</style> </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) { export function processImage(
const ctx = canvas.getContext("2d")!; blockSize: number,
resolutionFactor: number,
radius: number,
path: string,
canvas: HTMLCanvasElement,
callback: (resultImageData: ImageData) => void
) {
const ctx = canvas.getContext('2d')!;
const image = new Image(); const image = new Image();
image.src = path; // Replace with your image path image.src = path; // Replace with your image path
image.onload = function () { image.onload = function () {
// Resize image to 1/9 of the original resolution // Resize image to 1/9 of the original resolution
const width = image.width;
const height = image.height;
const resizedWidth = image.width / resolutionFactor; const resizedWidth = image.width / resolutionFactor;
const resizedHeight = image.height / 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.width = resizedWidth;
canvas.height = resizedHeight; canvas.height = resizedHeight;
const block = document.createElement('canvas');
for (let i = 0; i < num_blocks_y; i++) { const blockCtx = block.getContext('2d')!;
for (let j = 0; j < num_blocks_x; j++) { block.width = image.width;
const block = document.createElement("canvas"); block.height = image.height;
block.width = blockSize; blockCtx.drawImage(image, 0, 0, width, height, 0, 0, resizedWidth, resizedHeight);
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); applyFilter(block);
ctx.drawImage(block, 0, 0);
ctx.drawImage(block, j * blockSize, i * blockSize);
}
}
// Horizontal Gaussian blur // Horizontal Gaussian blur
const imageDataHorizontal = ctx.getImageData(0, 0, canvas.width, canvas.height); 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 imageDataVertical = blurredImageDataHorizontal;
const blurredImageData = gaussianBlurVertical(imageDataVertical, radius); 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 // Handle audio input change
audioInput.addEventListener('change', function (e: any) { audioInput.addEventListener('change', function (e: any) {
const file: File = e.target.files[0]; const file: File = e.target.files[0];
console.log(file.size);
if (file) { if (file) {
localforage.setItem(audioId + '-file', file); localforage.setItem(audioId + '-file', file);
} }