Allow AVIF and friends for avatar images
This commit is contained in:
parent
176befcf8c
commit
3b293de3ec
|
@ -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">
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue