From 300254c2f524a2332bfa1bad2f116c89aa55b4bf Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Wed, 22 Nov 2023 09:59:51 -0600 Subject: [PATCH 1/6] Animation for comparison --- src/helpers/functions/textureComparison.ts | 79 +++++++++++++++++++--- src/interfaces/firestorm.ts | 10 +++ 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 82167ad5..3834e34e 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -1,12 +1,13 @@ import stitch from "@images/stitch"; -import { magnifyToAttachment } from "@images/magnify"; -import { Image, loadImage } from "@napi-rs/canvas"; +import { magnify, magnifyToAttachment } from "@images/magnify"; +import { Image, loadImage, createCanvas, Canvas } from "@napi-rs/canvas"; import { Client, EmbedBuilder } from "@client"; import { addPathsToEmbed } from "@functions/getTexture"; -import { AnyPack, GalleryTexture } from "@interfaces/firestorm"; +import { AnyPack, GalleryTexture, MCMeta } from "@interfaces/firestorm"; import axios from "axios"; -import { ActionRowBuilder, ButtonBuilder } from "discord.js"; +import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder } from "discord.js"; import { template } from "@utility/buttons"; +import { animateToAttachment } from "@helpers/images/animate"; /** * Get the corresponding pack IDs for a given display choice @@ -50,6 +51,13 @@ export default async function textureComparison( await axios.get(`${client.tokens.apiUrl}gallery/modal/${id}/latest`) ).data; + const isAnimated = result.paths.filter((p) => p.mcmeta === true).length !== 0; + + let mcmeta: MCMeta; + if (isAnimated) { + mcmeta = (await axios.get(`${client.tokens.apiUrl}gallery/modal/${id}/latest`)).data.mcmeta; + } + const displayed = parseDisplay(display); const defaultURL = result.urls.default; @@ -72,11 +80,66 @@ export default async function textureComparison( } } - const stitched = await stitch(loadedImages); - const magnified = await magnifyToAttachment(stitched); + let canvasArray: Canvas[][][] = []; + let animatedGif: AttachmentBuilder; + + if (isAnimated) { + + let frameCount: number; + if (!mcmeta.animation?.height) frameCount = dimension.height / dimension.width; + else frameCount = dimension.height / mcmeta.animation.height; + + for (const images of loadedImages) { + canvasArray.push([]); + for (const image of images) { + canvasArray.at(-1).push([]); + let individualHeight = image.height / frameCount; + for (let i = 0; i < frameCount; ++i) { + const canvas = createCanvas(image.width, individualHeight); + const ctx = canvas.getContext("2d"); + ctx.imageSmoothingEnabled = false; + ctx.clearRect(0, 0, image.width, individualHeight); + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = "copy"; + + ctx.drawImage( + image, // image + 0, + individualHeight * i, // sx, sy + image.width, + individualHeight, // sWidth, sHeight + 0, + 0, // dx, dy + image.width, + individualHeight, // dWidth, dHeight + ); + canvasArray.at(-1).at(-1).push(canvas); + } + } + } + let stitchedFrames: Image [][] = []; + for (let i = 0; i < frameCount; ++i) { + stitchedFrames.push([]); + stitchedFrames.at(-1).push(await loadImage(await stitch(canvasArray.map((c) => c.map((c2) => c2[i]))))); + } + const firstTileSheet = await loadImage(await stitch(stitchedFrames, 0)); + const { magnified } = await magnify(firstTileSheet, { isAnimation: true, factor: 4 }); // 4 was chosen as a middle ground to prevent too much lag + const imageMagnified = await loadImage(magnified); + if (!mcmeta.animation?.height) mcmeta.animation.height = imageMagnified.height / frameCount; + else mcmeta.animation.height *= 4; + if (!mcmeta.animation?.width) mcmeta.animation.width = imageMagnified.width; + else mcmeta.animation.width *= 4; + animatedGif = await animateToAttachment(magnified, mcmeta); + } + + let magnified; + if (!isAnimated) { + const stitched = await stitch(loadedImages); + magnified = await magnifyToAttachment(stitched); + } const embed = new EmbedBuilder() - .setImage("attachment://magnified.png") + .setImage(`attachment://${isAnimated ? "animated.gif" : "magnified.png"}`) .setTitle(`[#${result.texture.id}] ${result.texture.name}`) .setURL(`https://webapp.faithfulpack.net/#/gallery/java/32x/latest/all/?show=${id}`) .addFields(addPathsToEmbed(result)) @@ -84,7 +147,7 @@ export default async function textureComparison( return { embeds: [embed], - files: [magnified], + files: [isAnimated ? animatedGif : magnified], components: [new ActionRowBuilder().addComponents(template)], }; } diff --git a/src/interfaces/firestorm.ts b/src/interfaces/firestorm.ts index 27bc7cd9..dcca856a 100644 --- a/src/interfaces/firestorm.ts +++ b/src/interfaces/firestorm.ts @@ -35,6 +35,16 @@ export interface Path { versions: string[]; // texture versions } +export interface MCMeta { + animation: { + frametime?: number; + interpolate?: boolean; + frames?: (number | { index?: number; time?: number })[]; + height?: number; + width?: number; + }; +} + export interface Use { id: string; name: string; From ff56008ff23edc1aca085d181e981ab06c692e09 Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Wed, 22 Nov 2023 10:16:23 -0600 Subject: [PATCH 2/6] Fixes a crash --- src/helpers/functions/textureComparison.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 3834e34e..8fa9a83d 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -125,6 +125,7 @@ export default async function textureComparison( const firstTileSheet = await loadImage(await stitch(stitchedFrames, 0)); const { magnified } = await magnify(firstTileSheet, { isAnimation: true, factor: 4 }); // 4 was chosen as a middle ground to prevent too much lag const imageMagnified = await loadImage(magnified); + if (!mcmeta.animation) mcmeta.animation = {}; if (!mcmeta.animation?.height) mcmeta.animation.height = imageMagnified.height / frameCount; else mcmeta.animation.height *= 4; if (!mcmeta.animation?.width) mcmeta.animation.width = imageMagnified.width; From 283919cbca3017ba66590db65068f07aedb4cc95 Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Wed, 22 Nov 2023 14:51:21 -0600 Subject: [PATCH 3/6] Code Cleanup --- src/helpers/functions/textureComparison.ts | 97 +++++++++++----------- src/helpers/images/magnify.ts | 2 +- src/interfaces/firestorm.ts | 13 +-- 3 files changed, 51 insertions(+), 61 deletions(-) diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 8fa9a83d..6f0e4468 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -3,11 +3,11 @@ import { magnify, magnifyToAttachment } from "@images/magnify"; import { Image, loadImage, createCanvas, Canvas } from "@napi-rs/canvas"; import { Client, EmbedBuilder } from "@client"; import { addPathsToEmbed } from "@functions/getTexture"; -import { AnyPack, GalleryTexture, MCMeta } from "@interfaces/firestorm"; +import { AnyPack, GalleryTexture } from "@interfaces/firestorm"; import axios from "axios"; import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder } from "discord.js"; import { template } from "@utility/buttons"; -import { animateToAttachment } from "@helpers/images/animate"; +import { animateToAttachment, MCMETA } from "@helpers/images/animate"; /** * Get the corresponding pack IDs for a given display choice @@ -35,6 +35,44 @@ export function parseDisplay(display: string) { } } +export async function tileSheetArraySlicer( + loadedImages: Image[][], + dimension: Image, + mcmeta: MCMETA, +) { + const frameCount: number = !mcmeta.animation?.height ? dimension.height / dimension.width : dimension.height / mcmeta.animation.height; // if height is not specified, assume square image + let canvasArray: Canvas[][][] = []; + for (const images of loadedImages) { + canvasArray.push([]); + for (const image of images) { + canvasArray.at(-1).push([]); + let individualHeight = image.height / frameCount; // height of each frame adjusted for resolution + for (let i = 0; i < frameCount; ++i) { + const canvas = createCanvas(image.width, individualHeight); // canvas for each frame adjusted for resolution + const ctx = canvas.getContext("2d"); + ctx.imageSmoothingEnabled = false; + ctx.clearRect(0, 0, image.width, individualHeight); + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = "copy"; // just canvas stuff + + ctx.drawImage( + image, // image + 0, + individualHeight * i, // sx, sy + image.width, + individualHeight, // sWidth, sHeight + 0, + 0, // dx, dy + image.width, + individualHeight, // dWidth, dHeight + ); + canvasArray.at(-1).at(-1).push(canvas); // putting the new frame into the array + } + } + } + return {canvasArray, frameCount}; // returns the 3D array with all of the frames and the number of frames +} + /** * Generate a texture comparison by ID * @author Evorp @@ -52,11 +90,7 @@ export default async function textureComparison( ).data; const isAnimated = result.paths.filter((p) => p.mcmeta === true).length !== 0; - - let mcmeta: MCMeta; - if (isAnimated) { - mcmeta = (await axios.get(`${client.tokens.apiUrl}gallery/modal/${id}/latest`)).data.mcmeta; - } + const mcmeta: MCMETA = result.mcmeta ?? {} as MCMETA; const displayed = parseDisplay(display); const defaultURL = result.urls.default; @@ -80,56 +114,19 @@ export default async function textureComparison( } } - let canvasArray: Canvas[][][] = []; let animatedGif: AttachmentBuilder; - if (isAnimated) { - - let frameCount: number; - if (!mcmeta.animation?.height) frameCount = dimension.height / dimension.width; - else frameCount = dimension.height / mcmeta.animation.height; - - for (const images of loadedImages) { - canvasArray.push([]); - for (const image of images) { - canvasArray.at(-1).push([]); - let individualHeight = image.height / frameCount; - for (let i = 0; i < frameCount; ++i) { - const canvas = createCanvas(image.width, individualHeight); - const ctx = canvas.getContext("2d"); - ctx.imageSmoothingEnabled = false; - ctx.clearRect(0, 0, image.width, individualHeight); - ctx.globalAlpha = 1; - ctx.globalCompositeOperation = "copy"; - - ctx.drawImage( - image, // image - 0, - individualHeight * i, // sx, sy - image.width, - individualHeight, // sWidth, sHeight - 0, - 0, // dx, dy - image.width, - individualHeight, // dWidth, dHeight - ); - canvasArray.at(-1).at(-1).push(canvas); - } - } - } + const { canvasArray, frameCount } = await tileSheetArraySlicer(loadedImages, dimension, mcmeta); let stitchedFrames: Image [][] = []; - for (let i = 0; i < frameCount; ++i) { + for (let i = 0; i < frameCount; ++i) { // This is to orient the frames vertically so they stitch properly stitchedFrames.push([]); stitchedFrames.at(-1).push(await loadImage(await stitch(canvasArray.map((c) => c.map((c2) => c2[i]))))); } - const firstTileSheet = await loadImage(await stitch(stitchedFrames, 0)); - const { magnified } = await magnify(firstTileSheet, { isAnimation: true, factor: 4 }); // 4 was chosen as a middle ground to prevent too much lag - const imageMagnified = await loadImage(magnified); + const firstTileSheet = await stitch(stitchedFrames, 0); + const { magnified, factor, height, width } = await magnify(firstTileSheet, { isAnimation: true }); if (!mcmeta.animation) mcmeta.animation = {}; - if (!mcmeta.animation?.height) mcmeta.animation.height = imageMagnified.height / frameCount; - else mcmeta.animation.height *= 4; - if (!mcmeta.animation?.width) mcmeta.animation.width = imageMagnified.width; - else mcmeta.animation.width *= 4; + mcmeta.animation.height = !mcmeta.animation?.height ? height / frameCount : mcmeta.animation.height * factor; // These scale the mcmeta info for the new resolution + mcmeta.animation.width = !mcmeta.animation?.width ? width : mcmeta.animation.width * factor; animatedGif = await animateToAttachment(magnified, mcmeta); } diff --git a/src/helpers/images/magnify.ts b/src/helpers/images/magnify.ts index f823cfff..868f5b12 100644 --- a/src/helpers/images/magnify.ts +++ b/src/helpers/images/magnify.ts @@ -18,7 +18,7 @@ export async function magnify(origin: ImageSource, options: MagnifyOptions = {}) const input = await loadImage(origin); // ignore height if tilesheet, otherwise it's not scaled as much - const surface = options.isAnimation ? input.width * 16 : input.width * input.height; + const surface = options.isAnimation ? input.width * 32 : input.width * input.height; // no custom factor provided let factor = 64; diff --git a/src/interfaces/firestorm.ts b/src/interfaces/firestorm.ts index dcca856a..1ea1cd92 100644 --- a/src/interfaces/firestorm.ts +++ b/src/interfaces/firestorm.ts @@ -1,3 +1,5 @@ +import { MCMETA } from "@helpers/images/animate"; + export type MinecraftEdition = "java" | "bedrock"; export type FaithfulPack = @@ -35,16 +37,6 @@ export interface Path { versions: string[]; // texture versions } -export interface MCMeta { - animation: { - frametime?: number; - interpolate?: boolean; - frames?: (number | { index?: number; time?: number })[]; - height?: number; - width?: number; - }; -} - export interface Use { id: string; name: string; @@ -62,6 +54,7 @@ export interface Texture extends BaseTexture { uses: Use[]; paths: Path[]; contributions?: Contribution[]; + mcmeta?: MCMETA; } // used for comparison loader From fc42a4d49ed0cfba67a992d761c50ae319497e84 Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Wed, 22 Nov 2023 17:46:45 -0600 Subject: [PATCH 4/6] Improvements and Prettier --- src/helpers/functions/getTexture.ts | 23 ++++++++----- src/helpers/functions/textureComparison.ts | 40 ++++++++++++++-------- src/helpers/images/magnify.ts | 3 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/helpers/functions/getTexture.ts b/src/helpers/functions/getTexture.ts index 0ac7f6c4..7365e1eb 100644 --- a/src/helpers/functions/getTexture.ts +++ b/src/helpers/functions/getTexture.ts @@ -12,7 +12,7 @@ import { Contributor, GalleryTexture, } from "@interfaces/firestorm"; -import { animateToAttachment } from "@images/animate"; +import { MCMETA, animateToAttachment } from "@images/animate"; import minecraftSorter from "@utility/minecraftSorter"; import formatName from "@utility/formatName"; import { textureButtons } from "@utility/buttons"; @@ -30,7 +30,7 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac const contributionJSON: Contributor[] = (await axios.get(`${tokens.apiUrl}contributions/authors`)) .data; - let mcmeta: any = {}; + let mcmeta: MCMETA; if (isAnimated) { const animatedPath = paths.filter((p) => p.mcmeta === true)[0]; const raw = (await axios.get(`${tokens.apiUrl}settings/repositories.raw`)).data; @@ -51,7 +51,7 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac const [strPack, strIconURL] = formatName(pack); const files: AttachmentBuilder[] = []; - const embed = new EmbedBuilder().setTitle(`[#${texture.id}] ${texture.name}`).setFooter({ + let embed = new EmbedBuilder().setTitle(`[#${texture.id}] ${texture.name}`).setFooter({ text: strPack, iconURL: strIconURL, }); @@ -119,12 +119,7 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac // magnifying the texture in thumbnail if (isAnimated) { - if (Object.keys(mcmeta?.animation ?? {}).length) - embed.addFields({ - name: "MCMETA", - value: `\`\`\`json\n${JSON.stringify(mcmeta.animation)}\`\`\``, - }); - + if (Object.keys(mcmeta?.animation ?? {}).length) addMCMetaToEmbed(embed, mcmeta); const { magnified } = await magnify(textureURL, { isAnimation: true }); files.push(await animateToAttachment(magnified, mcmeta)); } else files.push(await magnifyToAttachment(textureURL)); @@ -132,6 +127,16 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac return { embeds: [embed], files: files, components: [textureButtons], ephemeral: false }; } +export const addMCMetaToEmbed = (embed: EmbedBuilder, mcmeta: MCMETA) => { + embed.addFields({ + name: "MCMETA", + value: `\`\`\`json\n${JSON.stringify(mcmeta.animation)}\`\`\``, + }); + return { + embed, + }; +}; + /** * Generate embed fields for a given texture's paths * @author Juknum diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 6f0e4468..70e3bec8 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -2,7 +2,7 @@ import stitch from "@images/stitch"; import { magnify, magnifyToAttachment } from "@images/magnify"; import { Image, loadImage, createCanvas, Canvas } from "@napi-rs/canvas"; import { Client, EmbedBuilder } from "@client"; -import { addPathsToEmbed } from "@functions/getTexture"; +import { addMCMetaToEmbed, addPathsToEmbed } from "@functions/getTexture"; import { AnyPack, GalleryTexture } from "@interfaces/firestorm"; import axios from "axios"; import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder } from "discord.js"; @@ -40,21 +40,23 @@ export async function tileSheetArraySlicer( dimension: Image, mcmeta: MCMETA, ) { - const frameCount: number = !mcmeta.animation?.height ? dimension.height / dimension.width : dimension.height / mcmeta.animation.height; // if height is not specified, assume square image + const frameCount: number = !mcmeta.animation?.height + ? dimension.height / dimension.width + : dimension.height / mcmeta.animation.height; // if height is not specified, assume square image let canvasArray: Canvas[][][] = []; for (const images of loadedImages) { canvasArray.push([]); for (const image of images) { canvasArray.at(-1).push([]); - let individualHeight = image.height / frameCount; // height of each frame adjusted for resolution + let individualHeight = image.height / frameCount; // height of each frame adjusted for resolution for (let i = 0; i < frameCount; ++i) { - const canvas = createCanvas(image.width, individualHeight); // canvas for each frame adjusted for resolution + const canvas = createCanvas(image.width, individualHeight); // canvas for each frame adjusted for resolution const ctx = canvas.getContext("2d"); ctx.imageSmoothingEnabled = false; ctx.clearRect(0, 0, image.width, individualHeight); ctx.globalAlpha = 1; ctx.globalCompositeOperation = "copy"; // just canvas stuff - + ctx.drawImage( image, // image 0, @@ -70,7 +72,7 @@ export async function tileSheetArraySlicer( } } } - return {canvasArray, frameCount}; // returns the 3D array with all of the frames and the number of frames + return { canvasArray, frameCount }; // returns the 3D array with all of the frames and the number of frames } /** @@ -90,8 +92,9 @@ export default async function textureComparison( ).data; const isAnimated = result.paths.filter((p) => p.mcmeta === true).length !== 0; - const mcmeta: MCMETA = result.mcmeta ?? {} as MCMETA; - + const mcmeta: MCMETA = result.mcmeta ?? ({} as MCMETA); + const displayMCMETA: MCMETA = structuredClone(mcmeta); + const displayed = parseDisplay(display); const defaultURL = result.urls.default; @@ -117,15 +120,22 @@ export default async function textureComparison( let animatedGif: AttachmentBuilder; if (isAnimated) { const { canvasArray, frameCount } = await tileSheetArraySlicer(loadedImages, dimension, mcmeta); - let stitchedFrames: Image [][] = []; - for (let i = 0; i < frameCount; ++i) { // This is to orient the frames vertically so they stitch properly + let stitchedFrames: Image[][] = []; + for (let i = 0; i < frameCount; ++i) { + // This is to orient the frames vertically so they stitch properly stitchedFrames.push([]); - stitchedFrames.at(-1).push(await loadImage(await stitch(canvasArray.map((c) => c.map((c2) => c2[i]))))); + stitchedFrames + .at(-1) + .push(await loadImage(await stitch(canvasArray.map((c) => c.map((c2) => c2[i]))))); } const firstTileSheet = await stitch(stitchedFrames, 0); - const { magnified, factor, height, width } = await magnify(firstTileSheet, { isAnimation: true }); + const { magnified, factor, height, width } = await magnify(firstTileSheet, { + isAnimation: true, + }); if (!mcmeta.animation) mcmeta.animation = {}; - mcmeta.animation.height = !mcmeta.animation?.height ? height / frameCount : mcmeta.animation.height * factor; // These scale the mcmeta info for the new resolution + mcmeta.animation.height = !mcmeta.animation?.height + ? height / frameCount + : mcmeta.animation.height * factor; // These scale the mcmeta info for the new resolution mcmeta.animation.width = !mcmeta.animation?.width ? width : mcmeta.animation.width * factor; animatedGif = await animateToAttachment(magnified, mcmeta); } @@ -136,13 +146,15 @@ export default async function textureComparison( magnified = await magnifyToAttachment(stitched); } - const embed = new EmbedBuilder() + let embed = new EmbedBuilder() .setImage(`attachment://${isAnimated ? "animated.gif" : "magnified.png"}`) .setTitle(`[#${result.texture.id}] ${result.texture.name}`) .setURL(`https://webapp.faithfulpack.net/#/gallery/java/32x/latest/all/?show=${id}`) .addFields(addPathsToEmbed(result)) .setFooter({ text: `Displaying: ${display ?? "All"}` }); + if (Object.keys(displayMCMETA?.animation ?? {}).length) addMCMetaToEmbed(embed, displayMCMETA); + return { embeds: [embed], files: [isAnimated ? animatedGif : magnified], diff --git a/src/helpers/images/magnify.ts b/src/helpers/images/magnify.ts index 868f5b12..caf8f27d 100644 --- a/src/helpers/images/magnify.ts +++ b/src/helpers/images/magnify.ts @@ -18,8 +18,7 @@ export async function magnify(origin: ImageSource, options: MagnifyOptions = {}) const input = await loadImage(origin); // ignore height if tilesheet, otherwise it's not scaled as much - const surface = options.isAnimation ? input.width * 32 : input.width * input.height; - + const surface = options.isAnimation ? input.width ** 2 : input.width * input.height; // no custom factor provided let factor = 64; if (surface <= 256) factor = 32; From 910da729440e22f5d3815a007a76d7ac4ab9752b Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Wed, 22 Nov 2023 18:19:47 -0600 Subject: [PATCH 5/6] Minor Fixes --- src/helpers/functions/getTexture.ts | 19 ++++++--------- src/helpers/functions/textureComparison.ts | 28 ++++++++++++++-------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/helpers/functions/getTexture.ts b/src/helpers/functions/getTexture.ts index 7365e1eb..5e5207c4 100644 --- a/src/helpers/functions/getTexture.ts +++ b/src/helpers/functions/getTexture.ts @@ -51,7 +51,7 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac const [strPack, strIconURL] = formatName(pack); const files: AttachmentBuilder[] = []; - let embed = new EmbedBuilder().setTitle(`[#${texture.id}] ${texture.name}`).setFooter({ + const embed = new EmbedBuilder().setTitle(`[#${texture.id}] ${texture.name}`).setFooter({ text: strPack, iconURL: strIconURL, }); @@ -119,7 +119,12 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac // magnifying the texture in thumbnail if (isAnimated) { - if (Object.keys(mcmeta?.animation ?? {}).length) addMCMetaToEmbed(embed, mcmeta); + if (Object.keys(mcmeta?.animation ?? {}).length) + embed.addFields({ + name: "MCMETA", + value: `\`\`\`json\n${JSON.stringify(mcmeta.animation)}\`\`\``, + }); + const { magnified } = await magnify(textureURL, { isAnimation: true }); files.push(await animateToAttachment(magnified, mcmeta)); } else files.push(await magnifyToAttachment(textureURL)); @@ -127,16 +132,6 @@ export async function getTexture(interaction: Interaction, texture: Texture, pac return { embeds: [embed], files: files, components: [textureButtons], ephemeral: false }; } -export const addMCMetaToEmbed = (embed: EmbedBuilder, mcmeta: MCMETA) => { - embed.addFields({ - name: "MCMETA", - value: `\`\`\`json\n${JSON.stringify(mcmeta.animation)}\`\`\``, - }); - return { - embed, - }; -}; - /** * Generate embed fields for a given texture's paths * @author Juknum diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 70e3bec8..27c87486 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -2,7 +2,7 @@ import stitch from "@images/stitch"; import { magnify, magnifyToAttachment } from "@images/magnify"; import { Image, loadImage, createCanvas, Canvas } from "@napi-rs/canvas"; import { Client, EmbedBuilder } from "@client"; -import { addMCMetaToEmbed, addPathsToEmbed } from "@functions/getTexture"; +import { addPathsToEmbed } from "@functions/getTexture"; import { AnyPack, GalleryTexture } from "@interfaces/firestorm"; import axios from "axios"; import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder } from "discord.js"; @@ -35,11 +35,15 @@ export function parseDisplay(display: string) { } } -export async function tileSheetArraySlicer( - loadedImages: Image[][], - dimension: Image, - mcmeta: MCMETA, -) { +/** + * Takes in a 2D array of tilesheets and slices them into individual frames, then returns a 3D array with all of the frames and the number of frames + * @author Superboxer47 + * @param loadedImages Array of loaded images + * @param dimension Base image for dimensions + * @param mcmeta mcmeta for the texture, used for the dimensions of a single frame + * @returns 3D array with all of the frames and the number of frames + */ +export function tileSheetSlicer(loadedImages: Image[][], dimension: Image, mcmeta: MCMETA) { const frameCount: number = !mcmeta.animation?.height ? dimension.height / dimension.width : dimension.height / mcmeta.animation.height; // if height is not specified, assume square image @@ -119,8 +123,8 @@ export default async function textureComparison( let animatedGif: AttachmentBuilder; if (isAnimated) { - const { canvasArray, frameCount } = await tileSheetArraySlicer(loadedImages, dimension, mcmeta); - let stitchedFrames: Image[][] = []; + const { canvasArray, frameCount } = tileSheetSlicer(loadedImages, dimension, mcmeta); + const stitchedFrames: Image[][] = []; for (let i = 0; i < frameCount; ++i) { // This is to orient the frames vertically so they stitch properly stitchedFrames.push([]); @@ -146,14 +150,18 @@ export default async function textureComparison( magnified = await magnifyToAttachment(stitched); } - let embed = new EmbedBuilder() + const embed = new EmbedBuilder() .setImage(`attachment://${isAnimated ? "animated.gif" : "magnified.png"}`) .setTitle(`[#${result.texture.id}] ${result.texture.name}`) .setURL(`https://webapp.faithfulpack.net/#/gallery/java/32x/latest/all/?show=${id}`) .addFields(addPathsToEmbed(result)) .setFooter({ text: `Displaying: ${display ?? "All"}` }); - if (Object.keys(displayMCMETA?.animation ?? {}).length) addMCMetaToEmbed(embed, displayMCMETA); + if (Object.keys(displayMCMETA?.animation ?? {}).length) + embed.addFields({ + name: "MCMETA", + value: `\`\`\`json\n${JSON.stringify(displayMCMETA.animation)}\`\`\``, + }); return { embeds: [embed], From 4dc9810307fab0ab77fc4980ad45c756101e61a6 Mon Sep 17 00:00:00 2001 From: superbrotherx4 Date: Thu, 23 Nov 2023 00:02:15 -0600 Subject: [PATCH 6/6] simpli/clarifi-cation --- src/helpers/functions/textureComparison.ts | 23 +++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/helpers/functions/textureComparison.ts b/src/helpers/functions/textureComparison.ts index 27c87486..2ce56009 100644 --- a/src/helpers/functions/textureComparison.ts +++ b/src/helpers/functions/textureComparison.ts @@ -36,14 +36,14 @@ export function parseDisplay(display: string) { } /** - * Takes in a 2D array of tilesheets and slices them into individual frames, then returns a 3D array with all of the frames and the number of frames + * Slices tilesheets into individual frames and calculates the number of frames * @author Superboxer47 * @param loadedImages Array of loaded images * @param dimension Base image for dimensions * @param mcmeta mcmeta for the texture, used for the dimensions of a single frame * @returns 3D array with all of the frames and the number of frames */ -export function tileSheetSlicer(loadedImages: Image[][], dimension: Image, mcmeta: MCMETA) { +export function sliceTileSheet(loadedImages: Image[][], dimension: Image, mcmeta: MCMETA) { const frameCount: number = !mcmeta.animation?.height ? dimension.height / dimension.width : dimension.height / mcmeta.animation.height; // if height is not specified, assume square image @@ -57,9 +57,6 @@ export function tileSheetSlicer(loadedImages: Image[][], dimension: Image, mcmet const canvas = createCanvas(image.width, individualHeight); // canvas for each frame adjusted for resolution const ctx = canvas.getContext("2d"); ctx.imageSmoothingEnabled = false; - ctx.clearRect(0, 0, image.width, individualHeight); - ctx.globalAlpha = 1; - ctx.globalCompositeOperation = "copy"; // just canvas stuff ctx.drawImage( image, // image @@ -121,16 +118,16 @@ export default async function textureComparison( } } - let animatedGif: AttachmentBuilder; + let attachment; if (isAnimated) { - const { canvasArray, frameCount } = tileSheetSlicer(loadedImages, dimension, mcmeta); + const { canvasArray, frameCount } = sliceTileSheet(loadedImages, dimension, mcmeta); const stitchedFrames: Image[][] = []; for (let i = 0; i < frameCount; ++i) { // This is to orient the frames vertically so they stitch properly stitchedFrames.push([]); stitchedFrames .at(-1) - .push(await loadImage(await stitch(canvasArray.map((c) => c.map((c2) => c2[i]))))); + .push(await loadImage(await stitch(canvasArray.map((imageSet) => imageSet.map((image) => image[i]))))); // image[i] is the frame of the image } const firstTileSheet = await stitch(stitchedFrames, 0); const { magnified, factor, height, width } = await magnify(firstTileSheet, { @@ -141,13 +138,11 @@ export default async function textureComparison( ? height / frameCount : mcmeta.animation.height * factor; // These scale the mcmeta info for the new resolution mcmeta.animation.width = !mcmeta.animation?.width ? width : mcmeta.animation.width * factor; - animatedGif = await animateToAttachment(magnified, mcmeta); + attachment = await animateToAttachment(magnified, mcmeta); } - - let magnified; - if (!isAnimated) { + else { const stitched = await stitch(loadedImages); - magnified = await magnifyToAttachment(stitched); + attachment = await magnifyToAttachment(stitched); } const embed = new EmbedBuilder() @@ -165,7 +160,7 @@ export default async function textureComparison( return { embeds: [embed], - files: [isAnimated ? animatedGif : magnified], + files: [attachment], components: [new ActionRowBuilder().addComponents(template)], }; }