Fixed minor avatar cropping bug in avatars.js (#4192)

* Fixed avatar cropping bug in avatars.js

Persona icons/profile pictures were forced to a 2:3 ratio despite "Never resize avatars" being enabled.

Moved a misplaced line of code inside the crop condition to fix this behavior.

* Fix indentation for ESLint compliance

**Attempted** to correct indentation on line 49 of avatars.js to pass ESLint check.

* Update avatars.js

Gave my best to fix it :(

At the very least the issue is known now.

* Update avatars.js

Removed empty characters (formatting)

* Fixed avatars.js

Fixed the issue of avatar's not changing after my recent revision.

* Update avatars.js

Accidentally left a duplicate line; removed it now

* Extract reusable function for avatar resize

---------

Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
02loka
2025-06-23 22:09:54 +02:00
committed by GitHub
parent 2b7c0a3d37
commit e3923a7be3
2 changed files with 21 additions and 31 deletions
+3 -9
View File
@@ -3,12 +3,12 @@ import fs from 'node:fs';
import express from 'express';
import sanitize from 'sanitize-filename';
import { Jimp, JimpMime } from '../jimp.js';
import { Jimp } from '../jimp.js';
import { sync as writeFileAtomicSync } from 'write-file-atomic';
import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
import { getImages, tryParse } from '../util.js';
import { getFileNameValidationFunction } from '../middleware/validateFileName.js';
import { applyAvatarCropResize } from './characters.js';
export const router = express.Router();
@@ -42,13 +42,7 @@ router.post('/upload', getFileNameValidationFunction('overwrite_name'), async (r
const pathToUpload = path.join(request.file.destination, request.file.filename);
const crop = tryParse(request.query.crop);
const rawImg = await Jimp.read(pathToUpload);
if (typeof crop == 'object' && [crop.x, crop.y, crop.width, crop.height].every(x => typeof x === 'number')) {
rawImg.crop({ w: crop.width, h: crop.height, x: crop.x, y: crop.y });
}
rawImg.cover({ w: AVATAR_WIDTH, h: AVATAR_HEIGHT });
const image = await rawImg.getBuffer(JimpMime.png);
const image = await applyAvatarCropResize(rawImg, crop);
const filename = request.body.overwrite_name || `${Date.now()}.png`;
const pathToNewFile = path.join(request.user.directories.avatars, filename);
+18 -22
View File
@@ -270,13 +270,14 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
*/
/**
* Parses an image buffer and applies crop if defined.
* @param {Buffer} buffer Buffer of the image
* Applies avatar crop and resize operations to an image.
* I couldn't fix the type issue, so the first argument has {any} type.
* @param {object} jimp Jimp image instance
* @param {Crop|undefined} [crop] Crop parameters
* @returns {Promise<Buffer>} Image buffer
* @returns {Promise<Buffer>} Processed image buffer
*/
async function parseImageBuffer(buffer, crop) {
const image = await Jimp.fromBuffer(buffer);
export async function applyAvatarCropResize(jimp, crop) {
const image = /** @type {InstanceType<typeof import('../jimp.js').Jimp>} */ (jimp);
let finalWidth = image.bitmap.width, finalHeight = image.bitmap.height;
// Apply crop if defined
@@ -296,6 +297,17 @@ async function parseImageBuffer(buffer, crop) {
return await image.getBuffer(JimpMime.png);
}
/**
* Parses an image buffer and applies crop if defined.
* @param {Buffer} buffer Buffer of the image
* @param {Crop|undefined} [crop] Crop parameters
* @returns {Promise<Buffer>} Image buffer
*/
async function parseImageBuffer(buffer, crop) {
const image = await Jimp.fromBuffer(buffer);
return await applyAvatarCropResize(image, crop);
}
/**
* Reads an image file and applies crop if defined.
* @param {string} imgPath Path to the image file
@@ -305,23 +317,7 @@ async function parseImageBuffer(buffer, crop) {
async function tryReadImage(imgPath, crop) {
try {
const rawImg = await Jimp.read(imgPath);
let finalWidth = rawImg.bitmap.width, finalHeight = rawImg.bitmap.height;
// Apply crop if defined
if (typeof crop == 'object' && [crop.x, crop.y, crop.width, crop.height].every(x => typeof x === 'number')) {
rawImg.crop({ x: crop.x, y: crop.y, w: crop.width, h: crop.height });
// Apply standard resize if requested
if (crop.want_resize) {
finalWidth = AVATAR_WIDTH;
finalHeight = AVATAR_HEIGHT;
} else {
finalWidth = crop.width;
finalHeight = crop.height;
}
}
rawImg.cover({ w: finalWidth, h: finalHeight });
return await rawImg.getBuffer(JimpMime.png);
return await applyAvatarCropResize(rawImg, crop);
}
// If it's an unsupported type of image (APNG) - just read the file as buffer
catch (error) {