1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-19 05:09:43 +02:00

fix: Improve quality of resized images

This commit is contained in:
Maksim Eltyshev 2022-12-26 22:43:21 +01:00
parent 5cd025ffb7
commit 0ad9cffb08
4 changed files with 159 additions and 9 deletions

View file

@ -47,13 +47,20 @@ module.exports = {
fs.mkdirSync(thumbnailsPath); fs.mkdirSync(thumbnailsPath);
const { width, pageHeight: height = metadata.height } = metadata; const { width, pageHeight: height = metadata.height } = metadata;
const isPortrait = height > width;
const thumbnailsExtension = metadata.format === 'jpeg' ? 'jpg' : metadata.format; const thumbnailsExtension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
try { try {
await image await image
.resize(256, height > width ? 320 : undefined, { .resize(
256,
isPortrait ? 320 : undefined,
width < 256 || (isPortrait && height < 320)
? {
kernel: sharp.kernel.nearest, kernel: sharp.kernel.nearest,
}) }
: undefined,
)
.toFile(path.join(thumbnailsPath, `cover-256.${thumbnailsExtension}`)); .toFile(path.join(thumbnailsPath, `cover-256.${thumbnailsExtension}`));
fileData.image = { fileData.image = {

View file

@ -37,15 +37,22 @@ module.exports = {
fs.mkdirSync(rootPath); fs.mkdirSync(rootPath);
const { width, pageHeight: height = metadata.height } = metadata;
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format; const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
try { try {
await image.toFile(path.join(rootPath, `original.${extension}`)); await image.toFile(path.join(rootPath, `original.${extension}`));
await image await image
.resize(336, 200, { .resize(
336,
200,
width < 336 || height < 200
? {
kernel: sharp.kernel.nearest, kernel: sharp.kernel.nearest,
}) }
: undefined,
)
.toFile(path.join(rootPath, `cover-336.${extension}`)); .toFile(path.join(rootPath, `cover-336.${extension}`));
} catch (error1) { } catch (error1) {
try { try {

View file

@ -37,15 +37,22 @@ module.exports = {
fs.mkdirSync(rootPath); fs.mkdirSync(rootPath);
const { width, pageHeight: height = metadata.height } = metadata;
const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format; const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format;
try { try {
await image.toFile(path.join(rootPath, `original.${extension}`)); await image.toFile(path.join(rootPath, `original.${extension}`));
await image await image
.resize(100, 100, { .resize(
100,
100,
width < 100 || height < 100
? {
kernel: sharp.kernel.nearest, kernel: sharp.kernel.nearest,
}) }
: undefined,
)
.toFile(path.join(rootPath, `square-100.${extension}`)); .toFile(path.join(rootPath, `square-100.${extension}`));
} catch (error1) { } catch (error1) {
try { try {

View file

@ -0,0 +1,129 @@
const path = require('path');
const sharp = require('sharp');
const getConfig = require('../../get-config');
const processUserAvatar = async (user, userAvatarsPath) => {
const rootPath = path.join(userAvatarsPath, user.avatar.dirname);
const image = sharp(path.join(rootPath, `original.${user.avatar.extension}`), {
animated: true,
});
let metadata;
try {
metadata = await image.metadata();
} catch (error) {
return;
}
const { width, pageHeight: height = metadata.height } = metadata;
try {
await image
.resize(
100,
100,
width < 100 || height < 100
? {
kernel: sharp.kernel.nearest,
}
: undefined,
)
.toFile(path.join(rootPath, `square-100.${user.avatar.extension}`));
} catch (error) {} // eslint-disable-line no-empty
};
const processProjectBackgroundImage = async (project, projectBackgroundImagesPath) => {
const rootPath = path.join(projectBackgroundImagesPath, project.background_image.dirname);
const image = sharp(path.join(rootPath, `original.${project.background_image.extension}`), {
animated: true,
});
let metadata;
try {
metadata = await image.metadata();
} catch (error) {
return;
}
const { width, pageHeight: height = metadata.height } = metadata;
try {
await image
.resize(
336,
200,
width < 336 || height < 200
? {
kernel: sharp.kernel.nearest,
}
: undefined,
)
.toFile(path.join(rootPath, `cover-336.${project.background_image.extension}`));
} catch (error) {} // eslint-disable-line no-empty
};
const processAttachmentImage = async (attachment, attachmentsPath) => {
const rootPath = path.join(attachmentsPath, attachment.dirname);
const thumbnailsPath = path.join(rootPath, 'thumbnails');
const image = sharp(path.join(rootPath, attachment.filename), {
animated: true,
});
let metadata;
try {
metadata = await image.metadata();
} catch (error) {
return;
}
const { width, pageHeight: height = metadata.height } = metadata;
const isPortrait = height > width;
try {
await image
.resize(
256,
isPortrait ? 320 : undefined,
width < 256 || (isPortrait && height < 320)
? {
kernel: sharp.kernel.nearest,
}
: undefined,
)
.toFile(path.join(thumbnailsPath, `cover-256.${attachment.image.thumbnailsExtension}`));
} catch (error) {} // eslint-disable-line no-empty
};
module.exports.up = async (knex) => {
const config = await getConfig();
const users = await knex('user_account').whereNotNull('avatar');
// eslint-disable-next-line no-restricted-syntax
for (user of users) {
// eslint-disable-next-line no-await-in-loop
await processUserAvatar(user, config.custom.userAvatarsPath);
}
const projects = await knex('project').whereNotNull('background_image');
// eslint-disable-next-line no-restricted-syntax
for (project of projects) {
// eslint-disable-next-line no-await-in-loop
await processProjectBackgroundImage(project, config.custom.projectBackgroundImagesPath);
}
const attachments = await knex('attachment').whereNotNull('image');
// eslint-disable-next-line no-restricted-syntax
for (attachment of attachments) {
// eslint-disable-next-line no-await-in-loop
await processAttachmentImage(attachment, config.custom.attachmentsPath);
}
};
module.exports.down = () => Promise.resolve();