Skip to content

Ejemplos Avanzados

Aquí se proporcionan algunos ejemplos de uso avanzado de Sharp, incluyendo operaciones complejas de procesamiento de imágenes.

Composición de Imágenes

Agregar Marca de Agua

javascript
import sharp from 'sharp';

// Agregar marca de agua de texto
await sharp('input.jpg')
  .composite([
    {
      input: Buffer.from(`
        <svg width="200" height="100">
          <text x="10" y="50" font-family="Arial" font-size="24" fill="white">
            Watermark
          </text>
        </svg>
      `),
      top: 10,
      left: 10
    }
  ])
  .jpeg()
  .toFile('output.jpg');

Superposición de Imágenes

javascript
// Superponer múltiples imágenes
await sharp('background.jpg')
  .composite([
    {
      input: 'overlay1.png',
      top: 100,
      left: 100
    },
    {
      input: 'overlay2.png',
      top: 200,
      left: 200
    }
  ])
  .jpeg()
  .toFile('output.jpg');

Operaciones de Canales

Separar Canales

javascript
// Separar canales RGB
const channels = await sharp('input.jpg').separate();

// Guardar cada canal
await sharp(channels[0]).toFile('red-channel.jpg');
await sharp(channels[1]).toFile('green-channel.jpg');
await sharp(channels[2]).toFile('blue-channel.jpg');

Combinar Canales

javascript
// Combinar desde archivos de canales separados
await sharp('red-channel.jpg')
  .joinChannel(['green-channel.jpg', 'blue-channel.jpg'])
  .toFile('merged.jpg');

Conversión de Espacios de Color

RGB a CMYK

javascript
await sharp('input.jpg')
  .toColourspace(sharp.colourspace.cmyk)
  .tiff()
  .toFile('output.tiff');

Convertir a Espacio de Color Lab

javascript
await sharp('input.jpg')
  .toColourspace(sharp.colourspace.lab)
  .tiff()
  .toFile('output.tiff');

Filtros Avanzados

Nitidez Personalizada

javascript
await sharp('input.jpg')
  .sharpen({
    sigma: 1,
    flat: 1,
    jagged: 2
  })
  .toFile('output.jpg');

Corrección Gamma

javascript
await sharp('input.jpg')
  .gamma(2.2)
  .toFile('output.jpg');

Tinte

javascript
await sharp('input.jpg')
  .tint({ r: 255, g: 0, b: 0 })
  .toFile('output.jpg');

Procesamiento de Imágenes Multipágina

Procesar TIFF Multipágina

javascript
// Procesar todas las páginas
await sharp('multi-page.tiff', { pages: -1 })
  .resize(800, 600)
  .tiff()
  .toFile('output.tiff');

// Procesar página específica
await sharp('multi-page.tiff', { pages: 0 })
  .resize(800, 600)
  .jpeg()
  .toFile('page0.jpg');

Procesar PDF

javascript
// Procesar primera página de PDF
await sharp('document.pdf', { pages: 0 })
  .resize(800, 600)
  .jpeg()
  .toFile('page0.jpg');

Generación de Imágenes Adaptativas

Generar Múltiples Tamaños

javascript
async function generateResponsiveImages(inputPath) {
  const sizes = [
    { width: 320, height: 240, suffix: 'small' },
    { width: 640, height: 480, suffix: 'medium' },
    { width: 1280, height: 960, suffix: 'large' },
    { width: 1920, height: 1440, suffix: 'xlarge' }
  ];
  
  const promises = sizes.map(async ({ width, height, suffix }) => {
    await sharp(inputPath)
      .resize(width, height, { fit: 'cover' })
      .jpeg({ quality: 80 })
      .toFile(`output-${suffix}.jpg`);
  });
  
  await Promise.all(promises);
}

Generar Múltiples Formatos

javascript
async function generateMultipleFormats(inputPath) {
  const formats = [
    { format: 'jpeg', quality: 80, ext: 'jpg' },
    { format: 'webp', quality: 80, ext: 'webp' },
    { format: 'avif', quality: 80, ext: 'avif' }
  ];
  
  const promises = formats.map(async ({ format, quality, ext }) => {
    const image = sharp(inputPath).resize(800, 600);
    
    switch (format) {
      case 'jpeg':
        await image.jpeg({ quality }).toFile(`output.${ext}`);
        break;
      case 'webp':
        await image.webp({ quality }).toFile(`output.${ext}`);
        break;
      case 'avif':
        await image.avif({ quality }).toFile(`output.${ext}`);
        break;
    }
  });
  
  await Promise.all(promises);
}

Análisis de Imágenes

Obtener Información Estadística de Imagen

javascript
async function analyzeImage(filePath) {
  const metadata = await sharp(filePath).metadata();
  const stats = await sharp(filePath).stats();
  
  return {
    metadata,
    stats: {
      isOpaque: stats.isOpaque,
      dominant: stats.dominant,
      channels: stats.channels
    }
  };
}

Detectar Tipo de Imagen

javascript
async function detectImageType(filePath) {
  const metadata = await sharp(filePath).metadata();
  
  return {
    format: metadata.format,
    hasAlpha: metadata.hasAlpha,
    isOpaque: metadata.isOpaque,
    channels: metadata.channels,
    colorSpace: metadata.space
  };
}

Recorte Avanzado

Recorte Inteligente

javascript
async function smartCrop(inputPath, outputPath, width, height) {
  // Obtener información de imagen
  const metadata = await sharp(inputPath).metadata();
  
  // Calcular región de recorte
  const aspectRatio = width / height;
  const imageAspectRatio = metadata.width / metadata.height;
  
  let cropWidth, cropHeight, left, top;
  
  if (aspectRatio > imageAspectRatio) {
    // Objetivo más ancho, usar altura como referencia
    cropHeight = metadata.height;
    cropWidth = cropHeight * aspectRatio;
    top = 0;
    left = (metadata.width - cropWidth) / 2;
  } else {
    // Objetivo más alto, usar ancho como referencia
    cropWidth = metadata.width;
    cropHeight = cropWidth / aspectRatio;
    left = 0;
    top = (metadata.height - cropHeight) / 2;
  }
  
  await sharp(inputPath)
    .extract({ left: Math.round(left), top: Math.round(top), width: Math.round(cropWidth), height: Math.round(cropHeight) })
    .resize(width, height)
    .toFile(outputPath);
}

Optimización de Imágenes

Optimización Automática

javascript
async function autoOptimize(inputPath, outputPath) {
  const metadata = await sharp(inputPath).metadata();
  
  let image = sharp(inputPath);
  
  // Seleccionar mejor formato según tipo de imagen
  if (metadata.hasAlpha) {
    // Tiene transparencia, usar PNG
    image = image.png();
  } else {
    // Sin transparencia, usar JPEG
    image = image.jpeg({ quality: 80, progressive: true });
  }
  
  await image.toFile(outputPath);
}

JPEG Progresivo

javascript
await sharp('input.jpg')
  .jpeg({ 
    quality: 80, 
    progressive: true,
    mozjpeg: true 
  })
  .toFile('output.jpg');

Procesamiento Avanzado por Lotes

Marca de Agua por Lotes

javascript
const fs = require('fs').promises;

async function batchWatermark(inputDir, outputDir, watermarkPath) {
  const files = await fs.readdir(inputDir);
  
  for (const file of files) {
    if (file.match(/\.(jpg|jpeg|png|webp)$/i)) {
      try {
        await sharp(path.join(inputDir, file))
          .composite([
            {
              input: watermarkPath,
              top: 10,
              left: 10
            }
          ])
          .jpeg({ quality: 80 })
          .toFile(path.join(outputDir, `watermarked_${file}`));
        
        console.log(`Marca de agua agregada: ${file}`);
      } catch (error) {
        console.error(`Error al procesar ${file}:`, error.message);
      }
    }
  }
}

Conversión y Optimización por Lotes

javascript
async function batchOptimize(inputDir, outputDir) {
  const files = await fs.readdir(inputDir);
  
  for (const file of files) {
    if (file.match(/\.(jpg|jpeg|png|webp)$/i)) {
      try {
        const metadata = await sharp(path.join(inputDir, file)).metadata();
        const image = sharp(path.join(inputDir, file));
        
        // Seleccionar mejor formato según características de imagen
        if (metadata.hasAlpha) {
          await image.png({ compressionLevel: 9 }).toFile(path.join(outputDir, file.replace(/\.[^.]+$/, '.png')));
        } else {
          await image.jpeg({ quality: 80, progressive: true }).toFile(path.join(outputDir, file.replace(/\.[^.]+$/, '.jpg')));
        }
        
        console.log(`Optimización completada: ${file}`);
      } catch (error) {
        console.error(`Error al procesar ${file}:`, error.message);
      }
    }
  }
}

Enlaces Relacionados

Liberado bajo la Licencia Apache 2.0.