Add CharX-Jpeg

This commit is contained in:
Kwaroran
2025-02-02 07:49:08 +09:00
parent 25aa83877b
commit 243984d788
3 changed files with 38 additions and 11 deletions

View File

@@ -489,7 +489,7 @@
{/if}
{:else}
<span class="text-textcolor2 text-sm">{language.ccv3Desc}</span>
{#if cardExportType2 !== 'charx' && isCharacterHasAssets(DBState.db.characters[$selectedCharID])}
{#if cardExportType2 !== 'charx' && cardExportType2 !== 'charxJpeg' && isCharacterHasAssets(DBState.db.characters[$selectedCharID])}
<span class="text-red-500 text-sm">{language.notCharxWarn}</span>
{/if}
{/if}
@@ -512,7 +512,7 @@
<button class="bg-bgcolor px-2 py-4 rounded-lg flex-1" class:ring-1={cardExportType === 'realm'} onclick={() => {cardExportType = 'realm'}}>RisuRealm</button>
<button class="bg-bgcolor px-2 py-4 rounded-lg ml-2 flex-1" class:ring-1={cardExportType === ''} onclick={() => {
cardExportType = ''
cardExportType2 = isCharacterHasAssets(DBState.db.characters[$selectedCharID]) ? 'charx' : ''
cardExportType2 = 'charxJpeg'
}}>Character Card V3</button>
<button class="bg-bgcolor px-2 py-4 rounded-lg ml-2 flex-1" class:ring-1={cardExportType === 'ccv2'} onclick={() => {cardExportType = 'ccv2'}}>Character Card V2</button>
{/if}
@@ -520,9 +520,10 @@
{#if $alertStore.submsg === '' && cardExportType === ''}
<span class="text-textcolor mt-4">{language.format}</span>
<SelectInput bind:value={cardExportType2} className="mt-2">
<OptionInput value="charx">CHARX</OptionInput>
<OptionInput value="charxJpeg">CHARX-JPEG</OptionInput>
<OptionInput value="">PNG</OptionInput>
<OptionInput value="json">JSON</OptionInput>
<OptionInput value="charx">CHARX</OptionInput>
</SelectInput>
{/if}
<Button className="mt-4" onclick={() => {

View File

@@ -72,7 +72,7 @@ export async function importCharacterProcess(f:{
let db = getDatabase()
db.statics.imports += 1
if(f.name.endsWith('charx')){
if(f.name.endsWith('charx') || f.name.endsWith('jpg') || f.name.endsWith('jpeg')){
console.log('reading charx')
alertStore.set({
type: 'wait',
@@ -474,7 +474,7 @@ export async function characterURLImport() {
}
async function importFile(name:string, data:Uint8Array) {
if(name.endsWith('.charx') || name.endsWith('.png')){
if(name.endsWith('.charx') || name.endsWith('.jpg') || name.endsWith('.jpeg') || name.endsWith('.png')){
await importCharacterProcess({
name: name,
data: data
@@ -609,7 +609,7 @@ export async function exportChar(charaID:number):Promise<string> {
const option = await alertCardExport()
if(option.type === ''){
exportCharacterCard(char, option.type2 === 'json' ? 'json' : (option.type2 === 'charx' ? 'charx' : 'png'), {spec: 'v3'})
exportCharacterCard(char, option.type2 === 'json' ? 'json' : (option.type2 === 'charx' ? 'charx' : option.type2 === 'charxJpeg' ? 'charxJpeg' : 'png'), {spec: 'v3'})
}
else if(option.type === 'ccv2'){
exportCharacterCard(char,'png', {spec: 'v2'})
@@ -1131,7 +1131,7 @@ async function createBaseV2(char:character) {
}
export async function exportCharacterCard(char:character, type:'png'|'json'|'charx' = 'png', arg:{
export async function exportCharacterCard(char:character, type:'png'|'json'|'charx'|'charxJpeg' = 'png', arg:{
password?:string
writer?:LocalWriter|VirtualWriter,
spec?:'v2'|'v3'
@@ -1146,14 +1146,18 @@ export async function exportCharacterCard(char:character, type:'png'|'json'|'cha
const nameExt = {
'png': ['Image File', 'png'],
'json': ['JSON File', 'json'],
'charx': ['CharX File', 'charx']
'charx': ['CharX File', 'charx'],
'charxJpeg': ['CharX Embeded Jpeg', 'jpeg']
}
const ext = nameExt[type]
console.log(ext)
await (localWriter as LocalWriter).init(ext[0], [ext[1]])
}
const writer = type === 'charx' ? (new CharXWriter(localWriter)) : type === 'json' ? (new BlankWriter()) : (new PngChunk.streamWriter(img, localWriter))
const writer = (type === 'charx' || type === 'charxJpeg') ? (new CharXWriter(localWriter)) : type === 'json' ? (new BlankWriter()) : (new PngChunk.streamWriter(img, localWriter))
await writer.init()
if(writer instanceof CharXWriter && type === 'charxJpeg'){
await writer.writeJpeg(img)
}
let assetIndex = 0
if(spec === 'v2'){
const card = await createBaseV2(char)
@@ -1347,7 +1351,7 @@ export async function exportCharacterCard(char:character, type:'png'|'json'|'cha
msg: 'Loading... (Writing)'
})
if(type === 'charx'){
if(type === 'charx' || type === 'charxJpeg'){
const md:RisuModule = {
name: `${char.name} Module`,
description: "Module for " + char.name,

View File

@@ -33,7 +33,6 @@ export class CharXWriter{
}
}
this.zip = new fflate.Zip()
this.zip.ondata = handlerAsync
}
@@ -41,6 +40,29 @@ export class CharXWriter{
//do nothing, just to make compatible with other writer
}
async writeJpeg(img:Uint8Array<ArrayBufferLike>){
console.log('writeJpeg')
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if(!ctx){
return
}
const imgBlob = new Blob([img], {type: 'image/jpeg'})
const imgURL = URL.createObjectURL(imgBlob)
const imgElement = document.createElement('img')
imgElement.src = imgURL
await imgElement.decode()
canvas.width = imgElement.width
canvas.height = imgElement.height
ctx.drawImage(imgElement, 0, 0)
const blob = await (new Promise((res:BlobCallback, rej) => {
canvas.toBlob(res, 'image/jpeg')
}))
const buf = await blob.arrayBuffer()
this.apb.append(new Uint8Array(buf))
console.log('writeJpeg done')
}
async write(key:string,data:Uint8Array|string, level?:0|1|2|3|4|5|6|7|8|9){
console.log('write',key)
let dat:Uint8Array