fix: watermark upload JSON parsing and image quality preservation
- Fix JSON parsing error when uploading watermark logo by handling both JSON-stringified and raw string paths - Ensure publicPath is JSON.stringify'd consistently when saving - Preserve original image format (PNG/WebP/JPEG) when applying watermarks - Use maximum quality (100) to prevent unnecessary recompression
This commit is contained in:
@@ -392,11 +392,21 @@ router.post('/branding/watermark-logo', adminAuth, requirePermission('settings.e
|
|||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (oldWatermarkLogoSetting && oldWatermarkLogoSetting.setting_value) {
|
if (oldWatermarkLogoSetting && oldWatermarkLogoSetting.setting_value) {
|
||||||
const oldPath = JSON.parse(oldWatermarkLogoSetting.setting_value);
|
let oldPath;
|
||||||
try {
|
try {
|
||||||
await fs.unlink(oldPath);
|
// Try to parse as JSON first (for JSON-stringified paths)
|
||||||
} catch (error) {
|
oldPath = JSON.parse(oldWatermarkLogoSetting.setting_value);
|
||||||
console.error('Failed to delete old watermark logo:', error);
|
} catch (e) {
|
||||||
|
// If it's not valid JSON, use the raw value
|
||||||
|
oldPath = oldWatermarkLogoSetting.setting_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldPath && typeof oldPath === 'string') {
|
||||||
|
try {
|
||||||
|
await fs.unlink(oldPath);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to delete old watermark logo:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,13 +431,13 @@ router.post('/branding/watermark-logo', adminAuth, requirePermission('settings.e
|
|||||||
await db('app_settings')
|
await db('app_settings')
|
||||||
.insert({
|
.insert({
|
||||||
setting_key: 'branding_watermark_logo_url',
|
setting_key: 'branding_watermark_logo_url',
|
||||||
setting_value: publicPath,
|
setting_value: JSON.stringify(publicPath),
|
||||||
setting_type: 'branding',
|
setting_type: 'branding',
|
||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
})
|
})
|
||||||
.onConflict('setting_key')
|
.onConflict('setting_key')
|
||||||
.merge({
|
.merge({
|
||||||
setting_value: publicPath,
|
setting_value: JSON.stringify(publicPath),
|
||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -177,14 +177,25 @@ class WatermarkService {
|
|||||||
settings.position
|
settings.position
|
||||||
);
|
);
|
||||||
|
|
||||||
// Apply watermark
|
// Apply watermark with high quality output to preserve original image quality
|
||||||
const watermarkedBuffer = await image
|
let watermarkedImage = image.composite([{
|
||||||
.composite([{
|
input: watermarkBuffer,
|
||||||
input: watermarkBuffer,
|
top: position.top,
|
||||||
top: position.top,
|
left: position.left
|
||||||
left: position.left
|
}]);
|
||||||
}])
|
|
||||||
.toBuffer();
|
// Preserve original format with high quality settings
|
||||||
|
const format = metadata.format || 'jpeg';
|
||||||
|
let watermarkedBuffer;
|
||||||
|
|
||||||
|
if (format === 'png') {
|
||||||
|
watermarkedBuffer = await watermarkedImage.png({ quality: 100, compressionLevel: 6 }).toBuffer();
|
||||||
|
} else if (format === 'webp') {
|
||||||
|
watermarkedBuffer = await watermarkedImage.webp({ quality: 95, lossless: false }).toBuffer();
|
||||||
|
} else {
|
||||||
|
// Default to JPEG with maximum quality (100) to prevent recompression
|
||||||
|
watermarkedBuffer = await watermarkedImage.jpeg({ quality: 100, mozjpeg: true }).toBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
// Cache the result
|
// Cache the result
|
||||||
this.cache.set(cacheKey, {
|
this.cache.set(cacheKey, {
|
||||||
|
|||||||
Reference in New Issue
Block a user