189 lines
4.9 KiB
JavaScript
189 lines
4.9 KiB
JavaScript
const sharp = require('sharp');
|
|
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
|
|
class ImageProcessor {
|
|
constructor() {
|
|
this.supportedFormats = ['png', 'jpg', 'jpeg'];
|
|
this.maxImageSize = 10 * 1024 * 1024; // 10MB
|
|
}
|
|
|
|
// ================================================================
|
|
// MÉTODOS EXISTENTES (se já existirem no servidor)
|
|
// ================================================================
|
|
|
|
async process(imageBuffer, options = {}) {
|
|
let pipeline = sharp(imageBuffer);
|
|
|
|
// Ajustar brilho
|
|
if (options.brightness !== undefined) {
|
|
pipeline = pipeline.modulate({
|
|
brightness: options.brightness
|
|
});
|
|
}
|
|
|
|
// Ajustar contraste
|
|
if (options.contrast !== undefined) {
|
|
pipeline = pipeline.modulate({
|
|
brightness: options.contrast
|
|
});
|
|
}
|
|
|
|
// Ajustar saturação
|
|
if (options.saturation !== undefined) {
|
|
pipeline = pipeline.modulate({
|
|
saturation: options.saturation
|
|
});
|
|
}
|
|
|
|
return await pipeline.png().toBuffer();
|
|
}
|
|
|
|
// ================================================================
|
|
// NOVOS MÉTODOS - ROTAÇÃO E FLIP
|
|
// ================================================================
|
|
|
|
async rotate(imageBuffer, degrees) {
|
|
try {
|
|
if (degrees === 0) return imageBuffer;
|
|
|
|
const sharp = require('sharp');
|
|
return await sharp(imageBuffer)
|
|
.rotate(degrees)
|
|
.png()
|
|
.toBuffer();
|
|
} catch (error) {
|
|
console.error('Erro na rotação:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async flip(imageBuffer, horizontal, vertical) {
|
|
try {
|
|
const sharp = require('sharp');
|
|
let pipeline = sharp(imageBuffer);
|
|
|
|
if (horizontal) {
|
|
pipeline = pipeline.flop();
|
|
}
|
|
if (vertical) {
|
|
pipeline = pipeline.flip();
|
|
}
|
|
|
|
return await pipeline.png().toBuffer();
|
|
} catch (error) {
|
|
console.error('Erro no flip:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async rotateAndFlip(imageBuffer, options = {}) {
|
|
try {
|
|
let pipeline = sharp(imageBuffer);
|
|
|
|
if (options.rotation && options.rotation !== 0) {
|
|
pipeline = pipeline.rotate(options.rotation);
|
|
}
|
|
|
|
if (options.flipH) {
|
|
pipeline = pipeline.flop();
|
|
}
|
|
|
|
if (options.flipV) {
|
|
pipeline = pipeline.flip();
|
|
}
|
|
|
|
return await pipeline.png().toBuffer();
|
|
} catch (error) {
|
|
console.error('Erro ao rotacionar e flipar:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ================================================================
|
|
// MÉTODOS DE UTILIDADE
|
|
// ================================================================
|
|
|
|
async getThumbnail(imageBuffer, width = 500, height = 500) {
|
|
try {
|
|
const sharp = require('sharp');
|
|
return await sharp(imageBuffer)
|
|
.resize(width, height, {
|
|
fit: 'inside',
|
|
withoutEnlargement: true
|
|
})
|
|
.jpeg({ quality: 80, force: true })
|
|
.toBuffer();
|
|
} catch (error) {
|
|
console.error('Erro ao gerar thumbnail:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async getBase64Preview(imageBuffer, maxSize = 300) {
|
|
try {
|
|
const thumbnail = await this.getThumbnail(imageBuffer, maxSize, maxSize);
|
|
return `data:image/png;base64,${thumbnail.toString('base64')}`;
|
|
} catch (error) {
|
|
console.error('Erro ao gerar preview base64:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async validateImage(imageBuffer) {
|
|
try {
|
|
const metadata = await sharp(imageBuffer).metadata();
|
|
|
|
if (!metadata.format || !this.supportedFormats.includes(metadata.format.toLowerCase())) {
|
|
throw new Error(`Formato não suportado: ${metadata.format}`);
|
|
}
|
|
|
|
if (imageBuffer.length > this.maxImageSize) {
|
|
throw new Error(`Imagem muito grande: ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);
|
|
}
|
|
|
|
return true;
|
|
} catch (error) {
|
|
console.error('Erro na validação:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async resize(imageBuffer, width, height, options = {}) {
|
|
try {
|
|
const sharp = require('sharp');
|
|
return await sharp(imageBuffer)
|
|
.resize(width, height, {
|
|
fit: options.fit || 'inside',
|
|
withoutEnlargement: true
|
|
})
|
|
.png()
|
|
.toBuffer();
|
|
} catch (error) {
|
|
console.error('Erro no resize:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async getImageMetadata(imageBuffer) {
|
|
try {
|
|
const sharp = require('sharp');
|
|
const metadata = await sharp(imageBuffer).metadata();
|
|
return {
|
|
format: metadata.format,
|
|
width: metadata.width,
|
|
height: metadata.height,
|
|
size: imageBuffer.length,
|
|
channels: metadata.channels,
|
|
hasAlpha: metadata.hasAlpha
|
|
};
|
|
} catch (error) {
|
|
console.error('Erro ao ler metadata:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Exportar instância singleton
|
|
module.exports = new ImageProcessor();
|