fix: background zoom mismatch between cached and real-time calculated result
This commit is contained in:
parent
5afdaec8a0
commit
6d9c826b1d
@ -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>
|
||||
|
17
src/lib/graphics/blob2imageData.ts
Normal file
17
src/lib/graphics/blob2imageData.ts
Normal 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);
|
||||
});
|
||||
}
|
11
src/lib/graphics/imageData2blob.ts
Normal file
11
src/lib/graphics/imageData2blob.ts
Normal 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;
|
||||
}
|
@ -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
8
src/lib/storage.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import localforage from "localforage";
|
||||
|
||||
localforage.config({
|
||||
driver: localforage.INDEXEDDB,
|
||||
name: 'audioDB'
|
||||
});
|
||||
|
||||
export default localforage;
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user