diff --git a/eslint.config.mjs b/eslint.config.mjs index f78a1d2..dab4d49 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,7 @@ import { globalIgnores } from "eslint/config"; import { - defineConfigWithVueTs, - vueTsConfigs, + defineConfigWithVueTs, + vueTsConfigs, } from "@vue/eslint-config-typescript"; import pluginVue from "eslint-plugin-vue"; import skipFormatting from "@vue/eslint-config-prettier/skip-formatting"; @@ -10,15 +10,15 @@ import { configureVueProject } from "@vue/eslint-config-typescript"; configureVueProject({ scriptLangs: ["ts", "tsx"] }); export default defineConfigWithVueTs( - { - name: "app/files-to-lint", - files: ["**/*.{ts,mts,tsx,vue}"], - }, + { + name: "app/files-to-lint", + files: ["**/*.{ts,mts,tsx,vue}"], + }, - globalIgnores(["**/dist/**"]), + globalIgnores(["**/dist/**"]), - pluginVue.configs["flat/recommended"], - vueTsConfigs.strictTypeChecked, - vueTsConfigs.stylisticTypeChecked, - skipFormatting, + pluginVue.configs["flat/recommended"], + vueTsConfigs.strictTypeChecked, + vueTsConfigs.stylisticTypeChecked, + skipFormatting, ); diff --git a/src/App.vue b/src/App.vue index 39dbfbd..7d45436 100644 --- a/src/App.vue +++ b/src/App.vue @@ -19,6 +19,7 @@ enum PAPosition { } const PA_RATIO = 404 / 646; +const PREVIEW_SIZE = 512; const visible = ref(false); const srcData = ref(null); @@ -60,9 +61,9 @@ function randomElement(items: T[]): T { } function randomize() { - centerX.value = Math.random(); - centerY.value = Math.random(); - zoom.value = 1 + Math.random() * 2; + centerX.value = 0.25 + Math.random() * 0.5; + centerY.value = 0.25 + Math.random() * 0.5; + zoom.value = 1 + Math.random(); filter.value = randomElement(Object.values(Filter)); paPos.value = randomElement(Object.values(PAPosition)); paScale.value = 0.1 + Math.random() * 0.2; @@ -89,6 +90,9 @@ function newImage() { function download() { const link = document.createElement("a"); link.download = `coverify-${new Date().getTime().toString()}.png`; + if (targetSize.value !== PREVIEW_SIZE) { + draw(targetSize.value); + } link.href = canvas.value?.toDataURL() ?? "#"; link.click(); } @@ -122,7 +126,7 @@ function asyncDraw() { drawTimeout.value = setTimeout(draw); } -function draw() { +function draw(size = PREVIEW_SIZE) { if (!canvas.value) { return; } @@ -130,61 +134,55 @@ function draw() { if (!ctx || !image.value) { return; } - canvas.value.width = targetSize.value; - canvas.value.height = targetSize.value; - ctx.clearRect(0, 0, targetSize.value, targetSize.value); + canvas.value.width = size; + canvas.value.height = size; + ctx.clearRect(0, 0, size, size); const imgRatio = image.value.height / image.value.width; const widthFirst = image.value.width < image.value.height; - const imgWidth = targetSize.value * (widthFirst ? 1 : 1 / imgRatio) * zoom.value; - const imgHeight = targetSize.value * (widthFirst ? imgRatio : 1) * zoom.value; - const dx = (targetSize.value - imgWidth) * centerX.value; - const dy = (targetSize.value - imgHeight) * centerY.value; - // TODO get only selected area + const imgWidth = size * (widthFirst ? 1 : 1 / imgRatio) * zoom.value; + const imgHeight = size * (widthFirst ? imgRatio : 1) * zoom.value; + const dx = (size - imgWidth) * centerX.value; + const dy = (size - imgHeight) * centerY.value; ctx.drawImage(image.value, dx, dy, imgWidth, imgHeight); - const imageData = ctx.getImageData( - 0, - 0, - targetSize.value, - targetSize.value, - ); - // @ts-expect-error: safer to cast - 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]!; + if (filter.value !== Filter.None) { + const imageData = ctx.getImageData(0, 0, size, size); + const pixelData = imageData.data; + for (let i = 0; i < pixelData.length; i += 4) { + const r1 = pixelData[i] ?? 0; + const g1 = pixelData[i + 1] ?? 0; + const b1 = pixelData[i + 2] ?? 0; - 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 + 1] = g2; - pixelData[i + 2] = b2; - pixelData[i + 3] = 255; + pixelData[i] = r2; + pixelData[i + 1] = g2; + pixelData[i + 2] = b2; + pixelData[i + 3] = 255; + } + ctx.putImageData(imageData, 0, 0); } - ctx.putImageData(imageData, 0, 0); - if (paPos.value !== PAPosition.None && parentalAdvisory.value) { - const paWidth = targetSize.value * paScale.value; + const paWidth = size * paScale.value; const paHeight = paWidth * PA_RATIO; - let padx = paMargin.value * targetSize.value; - let pady = paMargin.value * targetSize.value; + let padx = paMargin.value * size; + let pady = paMargin.value * size; if ( paPos.value === PAPosition.BC || paPos.value === PAPosition.BL || paPos.value === PAPosition.BR ) { - pady = targetSize.value - paHeight - pady; + pady = size - paHeight - pady; } if (paPos.value === PAPosition.BR || paPos.value === PAPosition.TR) { - padx = targetSize.value - paWidth - padx; + padx = size - paWidth - padx; } else if ( paPos.value === PAPosition.BC || paPos.value === PAPosition.TC ) { - padx = (targetSize.value - paWidth) * 0.5; + padx = (size - paWidth) * 0.5; } ctx.drawImage(parentalAdvisory.value, padx, pady, paWidth, paHeight); } @@ -290,7 +288,7 @@ onMounted(() => { v-model="zoom" type="range" min="1" - max="3" + max="4" step="0.01" @input="asyncDraw" /> @@ -333,7 +331,7 @@ onMounted(() => { - + { {{ (paScale * 100).toFixed(0) }}% - +