Convertir imágenes normalmente implica un servidor, pero con Canvas API puedes hacerlo íntegramente en el navegador. El usuario carga la imagen, se procesa en su dispositivo y descarga el resultado. Cero privacidad comprometida, cero coste de servidor.
El flujo completo
- Usuario selecciona un archivo con
<input type="file"> - Lo leemos con
FileReaderoURL.createObjectURL() - Lo dibujamos en un
<canvas> - Exportamos el canvas al formato deseado con
toBlob()otoDataURL() - Disparamos la descarga
Implementación
async function convertImage(file, targetFormat, quality = 0.92) {
// 1. Cargar la imagen
const img = await loadImage(file);
// 2. Crear canvas con las dimensiones originales
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
// 3. Dibujar
const ctx = canvas.getContext('2d');
// Fondo blanco para conversiones a JPG (JPG no soporta transparencia)
if (targetFormat === 'image/jpeg') {
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
ctx.drawImage(img, 0, 0);
// 4. Exportar
return new Promise((resolve) => {
canvas.toBlob(resolve, targetFormat, quality);
});
}
function loadImage(file) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = URL.createObjectURL(file);
});
}
Disparar la descarga
function downloadBlob(blob, filename) {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url); // liberar memoria
}
// Uso completo
async function handleConvert(file, format) {
const mimeTypes = {
jpg: 'image/jpeg',
png: 'image/png',
webp: 'image/webp',
};
const blob = await convertImage(file, mimeTypes[format]);
const ext = format;
const name = file.name.replace(/\.[^.]+$/, '') + '.' + ext;
downloadBlob(blob, name);
}
Soporte de formatos
// Detectar si el navegador soporta WebP
async function supportsWebP() {
const canvas = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
return canvas.toDataURL('image/webp').startsWith('data:image/webp');
}
// Detectar soporte de AVIF
async function supportsAVIF() {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQ==';
});
}
Redimensionar antes de convertir
function resizeAndConvert(file, maxWidth, maxHeight, format, quality = 0.9) {
return new Promise(async (resolve) => {
const img = await loadImage(file);
let { naturalWidth: w, naturalHeight: h } = img;
// Mantener proporción
if (w > maxWidth) { h = Math.round(h * maxWidth / w); w = maxWidth; }
if (h > maxHeight) { w = Math.round(w * maxHeight / h); h = maxHeight; }
const canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
canvas.getContext('2d').drawImage(img, 0, 0, w, h);
canvas.toBlob(resolve, format, quality);
});
}
Limitaciones
- SVG: Canvas puede rasterizar SVG, pero pierde la escalabilidad vectorial
- Archivos grandes: el canvas tiene límites de tamaño (varía por navegador, ~4096×4096 en móvil)
-
AVIF: soporte limitado en
toBlob(), mejor comprobarlo antes - GIF animado: Canvas solo exporta el primer frame; para GIFs animados necesitas una librería
Herramienta lista para usar
Si necesitas convertir imágenes sin implementarlo, puedes usar este conversor de imágenes gratuito que soporta PNG, JPG, WebP, GIF y SVG con conversión completamente en el navegador.
Conclusión
Canvas API es todo lo que necesitas para convertir imágenes en el navegador. El resultado es:
- Sin coste de servidor
- Sin límites de uso
- Sin comprometer la privacidad del usuario
- Compatible con todos los navegadores modernos
Top comments (0)