Methodology
Metodologia del formato immagine
Canvas API + encoder nativi del browser. L’immagine non lascia mai il tuo dispositivo.
By Buğra SözeriPublished
Il cluster Immaginiconverte tra PNG, JPG e WebP usando la Canvas API nativa del browser. Non c’è una fase di caricamento, nessuna elaborazione lato server e nessun servizio di imaging di terze parti nel percorso — il che ha implicazioni sia per la privacy che per la qualità.
La pipeline di conversione
- L’utente sceglie un file tramite drag-and-drop o selettore file.
- Il file viene letto come ImageBitmap tramite
createImageBitmap(file). - Viene creato un canvas fuori schermo alle dimensioni native della bitmap.
- La bitmap viene disegnata sul canvas.
- Il canvas viene esportato tramite
canvas.toBlob(callback, mimeType, quality)— la qualità si applica solo ai target lossy. - Il Blob risultante viene offerto come download.
Ogni passaggio viene eseguito nel browser. Il file non viene inviato da nessuna parte — non c’è nessun fetch, nessun FormData, nessun upload XHR. Lo stesso vale per lo strumento Immagine in Base64, che usa la FileReader API invece del canvas ma segue lo stesso principio solo-browser.
Gestione della qualità
Lossless → lossy (PNG/WebP → JPG)
Passando da un formato lossless a JPG, esponiamo un cursore di qualità (impostazione predefinita 0,85) che controlla l’aggressività di quantizzazione dell’encoder JPG. A 0,85 il file è tipicamente 80-95% più piccolo del PNG sorgente senza alcuna differenza visiva percettibile per le fotografie. Al di sotto di 0,7 gli artefatti diventano visibili; impostiamo il limite inferiore a 0,5 per evitare di produrre accidentalmente output visibilmente degradato.
Lossy → lossless (JPG → PNG)
Passare da JPG a PNG non ripristina la qualità già scartata dal JPG. L’output è pixel-perfect di ciò che il JPG decodificava, ma le perdite di arrotondamento del JPG sono incorporate. Questo è raramente utile in pratica; il percorso migliore è trovare una sorgente di qualità superiore.
Lossy → lossy (JPG → WebP, ecc.)
Ogni salvataggio lossy introduce nuovi errori di quantizzazione sopra a quelli esistenti della sorgente. Per i file che hanno già attraversato diversi salvataggi, questo può causare un degrado di compounding visibile. Ricodifica sempre dalla sorgente di qualità più alta che hai.
Cosa non gestiamo
- HEIC / HEIF. Il formato predefinito di Apple da iOS 11. Il supporto del browser è praticamente zero al di fuori dell’ecosistema Apple, quindi dovremmo includere un decoder da 1+ MB.
- Formati RAW (DNG, CR2, NEF, ARW). Stesso problema — decoder pesanti per un pubblico ridotto. Usa Lightroom / darktable / RawTherapee.
- SVG ↔ raster. Possibile tramite canvas, ma vettoriale → raster perde la scalabilità e il contrario perde la fedeltà.
- Conversione in blocco. La nostra interfaccia gestisce un file alla volta.
La pipeline dell’encoder, in codice
La conversione è abbastanza breve da scrivere per esteso. Dato un Fileda un input file, l’intera pipeline richiede circa sei righe:
const bitmap = await createImageBitmap(file);
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
const ctx = canvas.getContext("2d");
ctx.drawImage(bitmap, 0, 0);
const blob = await canvas.convertToBlob({ type: "image/webp", quality: 0.85 });
// blob è l'output convertito, pronto per il downloadOgni passaggio è nativo del browser: createImageBitmap decodifica il formato sorgente (definito nello HTML Living Standard), OffscreenCanvas fornisce una superficie di disegno non renderizzante e convertToBlob invoca l’encoder WebP / JPEG / PNG integrato del browser con il parametro di qualità definito dalla specifica (0-1 per i formati lossy, ignorato per PNG). L’intera pipeline gira in circa 40-200 ms per un input 4K su un laptop del 2023.
Fonti e riferimenti
Il comportamento di codifica è definito nello HTML Living Standard per la serializzazione del canvas. Il baseline DCT JPEG proviene da ITU-T T.81; PNG da IETF RFC 2083; WebP da RFC 9649. La semantica della qualità — il parametro qualitytra 0 e 1 per gli encoder lossy — è normativa nella specifica HTML.
Ipotesi e limitazioni
- Un file alla volta.L’interfaccia accetta un solo file per sessione. La ricodifica in blocco richiede uno script contro l’API REST o uno strumento desktop.
- Encoder nativi del browser.La qualità dell’output dipende dal browser dell’utente. L’encoder WebP di Chromium è libwebp; Firefox usa il proprio. Esistono sottili differenze negli artefatti tra motori a quality < 0,7.
- Nessuna decodifica HEIC/HEIF/RAW. Gli input in quei formati non possono essere aperti tramite
createImageBitmapnella maggior parte dei browser senza uno shim WASM che non includiamo. - Nessuna codifica AVIF. La lettura è supportata nei browser moderni; la scrittura richiede WASM (libaom), che spingerebbe il bundle oltre le dimensioni accettabili.
- Lossless ↔ lossy è unidirezionale. Ricodificare un JPG in PNG non ripristina informazioni; il PNG ricodificato è pixel-perfect del JPG decodificato, con le sue perdite di quantizzazione incorporate.
- Il profilo ICC è preservato solo per riscriture dello stesso formato.La conversione tra formati (PNG → JPG) può eliminare il profilo ICC incorporato a seconda dell’implementazione del browser.
- Limite di memoria. Input molto grandi (40+ megapixel) possono causare esaurimento della memoria su Safari mobile.
Supporto browser minimo
La codifica WebP tramite canvas.toBlobrichiede Chromium 23+, Firefox 65+, Safari 14+, Edge 79+. Nel 2026 questo rappresenta >97% del traffico globale. La codifica AVIF non è supportata nella Canvas API del browser; avremmo bisogno di un encoder WASM per fornire quel target.
Frequently asked questions
- Come converte Convertitive tra formati immagine?
- La pipeline: (1) carica il file sorgente in un elemento browser Image; (2) lo disegna su un HTML Canvas alle dimensioni target; (3) chiama canvas.toBlob(callback, mimeType, quality) con il formato e il parametro di qualità desiderati. Il codec integrato del browser gestisce la codifica effettiva. Questo significa che il supporto del formato dipende dal dispositivo: la decodifica WebP richiede Chrome/Firefox/Edge (Safari 14+); AVIF richiede Chrome 85+/Firefox 93+.
- Quale algoritmo di compressione usa il codificatore JPEG?
- JPEG usa la compressione lossy a Trasformata del Coseno Discreto (DCT) come specificato in ISO/IEC 10918-1:1994 (baseline JPEG). Il parametro di qualità dell’encoder del browser si mappa sulla scalatura della tabella di quantizzazione DCT — quality=1,0 usa quantizzazione minima (quasi lossless), quality=0 usa quantizzazione massima (fortemente lossy). Le tabelle di quantizzazione esatte sono specifiche dell’implementazione per la specifica WHATWG HTML canvas.toBlob().
- La conversione da PNG a PNG è lossless?
- PNG usa la compressione lossless DEFLATE (RFC 2083, §2.1). Ricodificare un PNG attraverso la Canvas API riesegue DEFLATE, che può produrre un file più grande o più piccolo dell’originale a seconda dell’implementazione DEFLATE del browser. I valori dei pixel sono identici; cambia solo la dimensione del file compresso. I dati del canale alfa sono preservati esattamente.
- L’immagine lascia mai il mio dispositivo?
- No. Tutta l’elaborazione delle immagini usa la Canvas API del browser e la FileReader API — JavaScript puramente lato client senza richieste al server. La scheda Network degli Strumenti per sviluppatori del browser mostra zero richieste in uscita durante la conversione delle immagini. Questo è verificabile indipendentemente; il codice sorgente è pubblico su github.com/convertitive.
- Quali sono i limiti di accuratezza e qualità del convertitore di immagini?
- Tre limitazioni: (1) profilo colore: Canvas disegna le immagini nello spazio colore interno del browser (sRGB sulla maggior parte dei dispositivi), quindi i profili ICC incorporati nelle immagini sorgente potrebbero essere eliminati; (2) EXIF/metadati: canvas.toBlob() rimuove tutti i metadati EXIF, IPTC e XMP; (3) la qualità è soggettiva — il parametro quality si mappa diversamente tra le implementazioni JPEG e WebP dei browser.
Related
Published May 14, 2026