feat: preview size is fixed to 512

This commit is contained in:
2025-12-20 23:14:14 +01:00
parent 95d09d7750
commit 030c2f0803
2 changed files with 49 additions and 51 deletions
+11 -11
View File
@@ -1,7 +1,7 @@
import { globalIgnores } from "eslint/config"; import { globalIgnores } from "eslint/config";
import { import {
defineConfigWithVueTs, defineConfigWithVueTs,
vueTsConfigs, vueTsConfigs,
} from "@vue/eslint-config-typescript"; } from "@vue/eslint-config-typescript";
import pluginVue from "eslint-plugin-vue"; import pluginVue from "eslint-plugin-vue";
import skipFormatting from "@vue/eslint-config-prettier/skip-formatting"; import skipFormatting from "@vue/eslint-config-prettier/skip-formatting";
@@ -10,15 +10,15 @@ import { configureVueProject } from "@vue/eslint-config-typescript";
configureVueProject({ scriptLangs: ["ts", "tsx"] }); configureVueProject({ scriptLangs: ["ts", "tsx"] });
export default defineConfigWithVueTs( export default defineConfigWithVueTs(
{ {
name: "app/files-to-lint", name: "app/files-to-lint",
files: ["**/*.{ts,mts,tsx,vue}"], files: ["**/*.{ts,mts,tsx,vue}"],
}, },
globalIgnores(["**/dist/**"]), globalIgnores(["**/dist/**"]),
pluginVue.configs["flat/recommended"], pluginVue.configs["flat/recommended"],
vueTsConfigs.strictTypeChecked, vueTsConfigs.strictTypeChecked,
vueTsConfigs.stylisticTypeChecked, vueTsConfigs.stylisticTypeChecked,
skipFormatting, skipFormatting,
); );
+38 -40
View File
@@ -19,6 +19,7 @@ enum PAPosition {
} }
const PA_RATIO = 404 / 646; const PA_RATIO = 404 / 646;
const PREVIEW_SIZE = 512;
const visible = ref<boolean>(false); const visible = ref<boolean>(false);
const srcData = ref<string | null>(null); const srcData = ref<string | null>(null);
@@ -60,9 +61,9 @@ function randomElement<T>(items: T[]): T {
} }
function randomize() { function randomize() {
centerX.value = Math.random(); centerX.value = 0.25 + Math.random() * 0.5;
centerY.value = Math.random(); centerY.value = 0.25 + Math.random() * 0.5;
zoom.value = 1 + Math.random() * 2; zoom.value = 1 + Math.random();
filter.value = randomElement(Object.values(Filter)); filter.value = randomElement(Object.values(Filter));
paPos.value = randomElement(Object.values(PAPosition)); paPos.value = randomElement(Object.values(PAPosition));
paScale.value = 0.1 + Math.random() * 0.2; paScale.value = 0.1 + Math.random() * 0.2;
@@ -89,6 +90,9 @@ function newImage() {
function download() { function download() {
const link = document.createElement("a"); const link = document.createElement("a");
link.download = `coverify-${new Date().getTime().toString()}.png`; link.download = `coverify-${new Date().getTime().toString()}.png`;
if (targetSize.value !== PREVIEW_SIZE) {
draw(targetSize.value);
}
link.href = canvas.value?.toDataURL() ?? "#"; link.href = canvas.value?.toDataURL() ?? "#";
link.click(); link.click();
} }
@@ -122,7 +126,7 @@ function asyncDraw() {
drawTimeout.value = setTimeout(draw); drawTimeout.value = setTimeout(draw);
} }
function draw() { function draw(size = PREVIEW_SIZE) {
if (!canvas.value) { if (!canvas.value) {
return; return;
} }
@@ -130,61 +134,55 @@ function draw() {
if (!ctx || !image.value) { if (!ctx || !image.value) {
return; return;
} }
canvas.value.width = targetSize.value; canvas.value.width = size;
canvas.value.height = targetSize.value; canvas.value.height = size;
ctx.clearRect(0, 0, targetSize.value, targetSize.value); ctx.clearRect(0, 0, size, size);
const imgRatio = image.value.height / image.value.width; const imgRatio = image.value.height / image.value.width;
const widthFirst = image.value.width < image.value.height; const widthFirst = image.value.width < image.value.height;
const imgWidth = targetSize.value * (widthFirst ? 1 : 1 / imgRatio) * zoom.value; const imgWidth = size * (widthFirst ? 1 : 1 / imgRatio) * zoom.value;
const imgHeight = targetSize.value * (widthFirst ? imgRatio : 1) * zoom.value; const imgHeight = size * (widthFirst ? imgRatio : 1) * zoom.value;
const dx = (targetSize.value - imgWidth) * centerX.value; const dx = (size - imgWidth) * centerX.value;
const dy = (targetSize.value - imgHeight) * centerY.value; const dy = (size - imgHeight) * centerY.value;
// TODO get only selected area
ctx.drawImage(image.value, dx, dy, imgWidth, imgHeight); ctx.drawImage(image.value, dx, dy, imgWidth, imgHeight);
const imageData = ctx.getImageData( if (filter.value !== Filter.None) {
0, const imageData = ctx.getImageData(0, 0, size, size);
0, const pixelData = imageData.data;
targetSize.value, for (let i = 0; i < pixelData.length; i += 4) {
targetSize.value, const r1 = pixelData[i] ?? 0;
); const g1 = pixelData[i + 1] ?? 0;
// @ts-expect-error: safer to cast const b1 = pixelData[i + 2] ?? 0;
const pixelData = imageData.data as number[];
for (let i = 0; i < pixelData.length; i += 4) {
const r1 = pixelData[i]!;
const g1 = pixelData[i + 1]!;
const b1 = pixelData[i + 2]!;
const [r2, g2, b2] = applyFilter(filter.value, r1, g1, b1); const [r2, g2, b2] = applyFilter(filter.value, r1, g1, b1);
pixelData[i] = r2; pixelData[i] = r2;
pixelData[i + 1] = g2; pixelData[i + 1] = g2;
pixelData[i + 2] = b2; pixelData[i + 2] = b2;
pixelData[i + 3] = 255; pixelData[i + 3] = 255;
}
ctx.putImageData(imageData, 0, 0);
} }
ctx.putImageData(imageData, 0, 0);
if (paPos.value !== PAPosition.None && parentalAdvisory.value) { if (paPos.value !== PAPosition.None && parentalAdvisory.value) {
const paWidth = targetSize.value * paScale.value; const paWidth = size * paScale.value;
const paHeight = paWidth * PA_RATIO; const paHeight = paWidth * PA_RATIO;
let padx = paMargin.value * targetSize.value; let padx = paMargin.value * size;
let pady = paMargin.value * targetSize.value; let pady = paMargin.value * size;
if ( if (
paPos.value === PAPosition.BC || paPos.value === PAPosition.BC ||
paPos.value === PAPosition.BL || paPos.value === PAPosition.BL ||
paPos.value === PAPosition.BR paPos.value === PAPosition.BR
) { ) {
pady = targetSize.value - paHeight - pady; pady = size - paHeight - pady;
} }
if (paPos.value === PAPosition.BR || paPos.value === PAPosition.TR) { if (paPos.value === PAPosition.BR || paPos.value === PAPosition.TR) {
padx = targetSize.value - paWidth - padx; padx = size - paWidth - padx;
} else if ( } else if (
paPos.value === PAPosition.BC || paPos.value === PAPosition.BC ||
paPos.value === PAPosition.TC paPos.value === PAPosition.TC
) { ) {
padx = (targetSize.value - paWidth) * 0.5; padx = (size - paWidth) * 0.5;
} }
ctx.drawImage(parentalAdvisory.value, padx, pady, paWidth, paHeight); ctx.drawImage(parentalAdvisory.value, padx, pady, paWidth, paHeight);
} }
@@ -290,7 +288,7 @@ onMounted(() => {
v-model="zoom" v-model="zoom"
type="range" type="range"
min="1" min="1"
max="3" max="4"
step="0.01" step="0.01"
@input="asyncDraw" @input="asyncDraw"
/> />
@@ -333,7 +331,7 @@ onMounted(() => {
</td> </td>
<td></td> <td></td>
</tr> </tr>
<tr v-if="paPos !== PAPosition.None"> <tr>
<td><label for="pa-scale">Sticker Scale:</label></td> <td><label for="pa-scale">Sticker Scale:</label></td>
<td> <td>
<input <input
@@ -348,7 +346,7 @@ onMounted(() => {
</td> </td>
<td>{{ (paScale * 100).toFixed(0) }}%</td> <td>{{ (paScale * 100).toFixed(0) }}%</td>
</tr> </tr>
<tr v-if="paPos !== PAPosition.None"> <tr>
<td><label for="pa-margin">Sticker Margin:</label></td> <td><label for="pa-margin">Sticker Margin:</label></td>
<td> <td>
<input <input