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 = 300, height = 300) { try { const sharp = require('sharp'); return await sharp(imageBuffer) .resize(width, height, { fit: 'inside', withoutEnlargement: true }) .png() .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();