From 37455894dc6369dd71e28fb82c6a4f168e001141 Mon Sep 17 00:00:00 2001 From: kwaroran Date: Sat, 18 Nov 2023 04:05:49 +0900 Subject: [PATCH] [fix] encoding images --- src/ts/characterCards.ts | 33 ++++++++++----------------------- src/ts/characters.ts | 7 ++++--- src/ts/image.ts | 16 ++++++++++++++++ src/ts/persona.ts | 5 +++-- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/ts/characterCards.ts b/src/ts/characterCards.ts index a35d965c..359b967c 100644 --- a/src/ts/characterCards.ts +++ b/src/ts/characterCards.ts @@ -1,5 +1,5 @@ import { get, writable, type Writable } from "svelte/store" -import { alertConfirm, alertError, alertMd, alertNormal, alertSelect, alertStore, alertTOS } from "./alert" +import { alertConfirm, alertError, alertMd, alertNormal, alertSelect, alertStore, alertTOS, alertWait } from "./alert" import { DataBase, defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook, type triggerscript } from "./storage/database" import { checkNullish, selectMultipleFile, sleep } from "./util" import { language } from "src/lang" @@ -10,6 +10,7 @@ import { cloneDeep } from "lodash" import { selectedCharID } from "./stores" import { convertImage } from "./parser" import * as yuso from 'yuso' +import { reencodeImage } from "./image" export const hubURL = "https://sv.risuai.xyz" @@ -68,7 +69,7 @@ async function importCharacterProcess(f:{ } } const charaData:OldTavernChar = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8')) - const imgp = await saveAsset(yuso.trim(img)) + const imgp = await saveAsset(await reencodeImage(img)) let db = get(DataBase) db.characters.push(convertOldTavernAndJSON(charaData, imgp)) DataBase.set(db) @@ -105,6 +106,7 @@ export async function characterURLImport() { const charPath = (new URLSearchParams(location.search)).get('charahub') try { if(charPath){ + alertWait('Loading from Chub...') const url = new URL(location.href); url.searchParams.delete('charahub'); window.history.pushState(null, '', url.toString()); @@ -120,26 +122,10 @@ export async function characterURLImport() { } }) const img = new Uint8Array(await chara.arrayBuffer()) - - const readed = (yuso.decode(img, "chara")) - { - const charaData:CharacterCardV2 = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8')) - if(await importSpecv2(charaData, img)){ - checkCharOrder() - return - } - } - { - const imgp = await saveAsset(yuso.trim(img)) - let db = get(DataBase) - const charaData:OldTavernChar = JSON.parse(Buffer.from(readed, 'base64').toString('utf-8')) - db.characters.push(convertOldTavernAndJSON(charaData, imgp)) - - DataBase.set(db) - checkCharOrder() - alertNormal(language.importedCharacter) - return - } + await importCharacterProcess({ + name: 'charahub.png', + data: img + }) } } catch (error) { alertError(language.errors.noData) @@ -221,7 +207,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|' } const data = card.data - const im = img ? await saveAsset(yuso.trim(img)) : undefined + const im = img ? await saveAsset(await reencodeImage(img)) : undefined let db = get(DataBase) const risuext = cloneDeep(data.extensions.risuai) @@ -513,6 +499,7 @@ export async function exportSpecV2(char:character, type:'png'|'json' = 'png') { await sleep(10) + img = await reencodeImage(img) img = yuso.encode(img, "chara",Buffer.from(JSON.stringify(card)).toString('base64')) alertStore.set({ diff --git a/src/ts/characters.ts b/src/ts/characters.ts index 47ccedee..1ad4c8cc 100644 --- a/src/ts/characters.ts +++ b/src/ts/characters.ts @@ -8,6 +8,7 @@ import { v4 as uuidv4 } from 'uuid'; import { selectedCharID } from "./stores"; import { checkCharOrder, downloadFile, getFileSrc, readImage } from "./storage/globalApi"; import * as yuso from 'yuso' +import { reencodeImage } from "./image"; export function createNewCharacter() { let db = get(DataBase) @@ -71,13 +72,13 @@ export async function getCharImage(loc:string, type:'plain'|'css'|'contain'|'lgc } export async function selectCharImg(charId:number) { - const selected = await selectSingleFile(['png']) + const selected = await selectSingleFile(['png', 'webp', 'gif', 'jpg', 'jpeg']) if(!selected){ return } const img = selected.data let db = get(DataBase) - const imgp = await saveImage(img) + const imgp = await saveImage(await reencodeImage(img)) db.characters[charId].image = imgp setDatabase(db) } @@ -492,7 +493,7 @@ export async function addDefaultCharacters() { } char.chatPage = 0 - char.image = await saveImage(yuso.trim(Buffer.from(imgBuffer))) + char.image = await saveImage(await reencodeImage(Buffer.from(imgBuffer))) char.chaId = uuidv4() db.characters.push(characterFormatUpdate(char)) setDatabase(db) diff --git a/src/ts/image.ts b/src/ts/image.ts index f0464733..25e37033 100644 --- a/src/ts/image.ts +++ b/src/ts/image.ts @@ -86,4 +86,20 @@ export async function getInlayImage(id: string){ export function supportsInlayImage(){ const db = get(DataBase) return db.aiModel.startsWith('gptv') || (db.aiModel === 'reverse_proxy' && db.proxyRequestModel?.startsWith('gptv')) +} + +export async function reencodeImage(img:Uint8Array){ + const canvas = document.createElement('canvas') + const imgObj = new Image() + imgObj.src = URL.createObjectURL(new Blob([img], {type: `image/png`})) + await imgObj.decode() + let drawHeight = imgObj.height + let drawWidth = imgObj.width + canvas.width = drawWidth + canvas.height = drawHeight + const ctx = canvas.getContext('2d') + ctx.drawImage(imgObj, 0, 0, drawWidth, drawHeight) + const b64 = canvas.toDataURL('image/png').split(',')[1] + const b = Buffer.from(b64, 'base64') + return b } \ No newline at end of file diff --git a/src/ts/persona.ts b/src/ts/persona.ts index 2d49bfa1..147906ee 100644 --- a/src/ts/persona.ts +++ b/src/ts/persona.ts @@ -6,6 +6,7 @@ import * as yuso from 'yuso' import { downloadFile, readImage } from "./storage/globalApi" import { language } from "src/lang" import { cloneDeep } from "lodash" +import { reencodeImage } from "./image" export async function selectUserImg() { const selected = await selectSingleFile(['png']) @@ -80,7 +81,7 @@ export async function exportUserPersona(){ await sleep(10) - img = yuso.encode(yuso.trim(img), "persona",Buffer.from(JSON.stringify(card)).toString('base64')) + img = yuso.encode(await reencodeImage(img), "persona",Buffer.from(JSON.stringify(card)).toString('base64')) alertStore.set({ type: 'wait', @@ -102,7 +103,7 @@ export async function importUserPersona(){ let db = get(DataBase) db.personas.push({ name: data.name, - icon: await saveImage(yuso.trim(v.data)), + icon: await saveImage(await reencodeImage(v.data)), personaPrompt: data.personaPrompt }) setDatabase(db)