Allow AVIF and friends for avatar images

This commit is contained in:
Cohee 2024-03-21 14:47:22 +02:00
parent 176befcf8c
commit 3b293de3ec
3 changed files with 65 additions and 5 deletions

View File

@ -4008,7 +4008,7 @@
<div id="avatar_div" class="avatar_div alignitemsflexstart justifySpaceBetween flexnowrap flexGap5">
<label id="avatar_div_div" class="add_avatar avatar" for="add_avatar_button" title="Click to select a new avatar for this character" data-i18n="[title]Click to select a new avatar for this character">
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
<input hidden type="file" id="add_avatar_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif, image/bmp">
<input hidden type="file" id="add_avatar_button" name="avatar" accept="image/*">
</label>
<div class="flex-container flexFlowColumn">
<div class="flex-container flexFlowColumn">

View File

@ -150,6 +150,7 @@ import {
humanFileSize,
Stopwatch,
isValidUrl,
ensureImageFormatSupported,
} from './scripts/utils.js';
import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, loadExtensionSettings, renderExtensionTemplate, runGenerationInterceptors, saveMetadataDebounced, writeExtensionField } from './scripts/extensions.js';
@ -5713,6 +5714,12 @@ async function uploadUserAvatar(e) {
}
}
const rawFile = formData.get('avatar');
if (rawFile instanceof File){
const convertedFile = await ensureImageFormatSupported(rawFile);
formData.set('avatar', convertedFile);
}
jQuery.ajax({
type: 'POST',
url: url,
@ -7212,8 +7219,15 @@ function addAlternateGreeting(template, greeting, index, getArray) {
async function createOrEditCharacter(e) {
$('#rm_info_avatar').html('');
var formData = new FormData($('#form_create').get(0));
const formData = new FormData($('#form_create').get(0));
formData.set('fav', fav_ch_checked);
const rawFile = formData.get('avatar');
if (rawFile instanceof File){
const convertedFile = await ensureImageFormatSupported(rawFile);
formData.set('avatar', convertedFile);
}
if ($('#form_create').attr('actiontype') == 'createcharacter') {
if ($('#character_name_pole').val().length > 0) {
if (is_group_generating || is_send_press) {

View File

@ -1047,15 +1047,51 @@ export function loadFileToDocument(url, type) {
});
}
/**
* Ensure that we can import war crime image formats like WEBP and AVIF.
* @param {File} file Input file
* @returns {Promise<File>} A promise that resolves to the supported file.
*/
export async function ensureImageFormatSupported(file) {
const supportedTypes = [
'image/jpeg',
'image/png',
'image/bmp',
'image/tiff',
'image/gif',
'image/apng',
];
if (supportedTypes.includes(file.type) || !file.type.startsWith('image/')) {
return file;
}
return await convertImageFile(file, 'image/png');
}
/**
* Converts an image file to a given format.
* @param {File} inputFile File to convert
* @param {string} type Target file type
* @returns {Promise<File>} A promise that resolves to the converted file.
*/
export async function convertImageFile(inputFile, type = 'image/png') {
const base64 = await getBase64Async(inputFile);
const thumbnail = await createThumbnail(base64, null, null, type);
const blob = await fetch(thumbnail).then(res => res.blob());
const outputFile = new File([blob], inputFile.name, { type });
return outputFile;
}
/**
* Creates a thumbnail from a data URL.
* @param {string} dataUrl The data URL encoded data of the image.
* @param {number} maxWidth The maximum width of the thumbnail.
* @param {number} maxHeight The maximum height of the thumbnail.
* @param {number|null} maxWidth The maximum width of the thumbnail.
* @param {number|null} maxHeight The maximum height of the thumbnail.
* @param {string} [type='image/jpeg'] The type of the thumbnail.
* @returns {Promise<string>} A promise that resolves to the thumbnail data URL.
*/
export function createThumbnail(dataUrl, maxWidth, maxHeight, type = 'image/jpeg') {
export function createThumbnail(dataUrl, maxWidth = null, maxHeight = null, type = 'image/jpeg') {
// Someone might pass in a base64 encoded string without the data URL prefix
if (!dataUrl.includes('data:')) {
dataUrl = `data:image/jpeg;base64,${dataUrl}`;
@ -1073,6 +1109,16 @@ export function createThumbnail(dataUrl, maxWidth, maxHeight, type = 'image/jpeg
let thumbnailWidth = maxWidth;
let thumbnailHeight = maxHeight;
if (maxWidth === null) {
thumbnailWidth = img.width;
maxWidth = img.width;
}
if (maxHeight === null) {
thumbnailHeight = img.height;
maxHeight = img.height;
}
if (img.width > img.height) {
thumbnailHeight = maxWidth / aspectRatio;
} else {