API di Compressione Immagini#

Comprimi immagini PNG, JPEG e WebP con l'endpoint POST /v1/convert/compress-image — il formato non cambia mai (PNG in ingresso, PNG in uscita). La compressione è prima di tutto lossless: i metadati vengono rimossi e l'immagine viene ricodificata con le impostazioni lossless più aggressive per il suo formato, quindi il risultato non è mai più grande dell'input. Passa target_size_kb per impostare un budget di dimensione file; se la sola ottimizzazione lossless non basta a raggiungerlo, l'immagine viene ridimensionata verso il basso con le proporzioni bloccate finché non rientra nel budget.


Endpoint#

POST /v1/convert/compress-image

Content-Type: multipart/form-data

Input accettato: file .png, .jpg, .jpeg, .webp

Formato di output: lo stesso dell'input (image/png, image/jpeg o image/webp)


Autenticazione#

Richiede una chiave API privata oppure un token JWT generato da una chiave pubblica.

X-API-Key: sk_live_your_private_key

Oppure:

Authorization: Bearer <jwt_token>

Parametri della richiesta#

Parametro Tipo Obbligatorio Predefinito Descrizione
file file -- Il file immagine .png, .jpg, .jpeg o .webp da comprimere.
target_size_kb integer No -- Dimensione file di destinazione in kilobyte. Omesso: solo ottimizzazione lossless. Impostato: l'immagine viene inoltre ridimensionata verso il basso (proporzioni bloccate) finché non rientra nel target.
output_filename string No Nome del file di input Nome file di output personalizzato. L'estensione del file di input viene preservata.
direct_download boolean No true Se true, restituisce i byte grezzi dell'immagine. Se false, restituisce metadati JSON con un URL di download presigned.

Dettagli della conversione#

Fase 1 — lossless (sempre eseguita):

  • I metadati (EXIF, XMP, chunk di testo PNG) vengono rimossi; il profilo colore ICC e il flag di orientamento EXIF vengono preservati, così colori e rotazione non cambiano
  • PNG: ricodificato alla massima compressione zlib, più una conversione in palette quando l'immagine ha 256 colori unici o meno e il risultato è dimostrabilmente identico pixel per pixel
  • JPEG: ricodificato riutilizzando le tabelle di quantizzazione originali con codifica Huffman progressiva ottimizzata — non viene introdotta alcuna perdita di quantizzazione aggiuntiva
  • WebP: ricodifica true lossless (VP8L) al massimo livello di effort
  • Vince il più piccolo tra i byte originali e tutti i candidati — l'output non è mai più grande dell'input

Fase 2 — riduzione delle dimensioni (solo con target_size_kb, solo se la fase 1 non lo raggiunge):

  • L'immagine viene ridimensionata verso il basso con le proporzioni bloccate (ricampionamento LANCZOS) e ricodificata, cercando con una ricerca binaria sul fattore di scala le dimensioni più grandi che rientrano nel target
  • I JPEG ridimensionati e i WebP con sorgente lossy vengono ricodificati a qualità 85; i PNG e i WebP con sorgente lossless restano lossless alla dimensione ridotta
Nota sul best effort: Se il target è irraggiungibile anche alla scala minima, l'endpoint restituisce il file più piccolo che è riuscito a ottenere invece di un errore — controlla file_size (o l'header X-File-Size) per vedere qual è stato il risultato raggiunto.

Risposta#

Download diretto (direct_download=true, predefinito)#

HTTP 200 OK
Content-Type: image/png
Content-Disposition: inline; filename="photo_20260717_123456789.png"

Restituisce i byte grezzi dell'immagine nello stesso formato dell'input.

Risposta con metadati (direct_download=false)#

{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/compress-image/photo_20260717_123456789.png",
    "filename": "photo_20260717_123456789.png",
    "file_size": 45678,
    "conversion_time_seconds": 0.5
}

Esempi di codice#

Python#

import requests

with open("photo.png", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/compress-image",
        headers={"X-API-Key": "sk_live_your_private_key"},
        files={"file": ("photo.png", f)},
        data={"target_size_kb": 200}
    )

with open("photo_compressed.png", "wb") as out:
    out.write(response.content)

Node.js#

const form = new FormData();
form.append("file", fs.createReadStream("photo.png"));
form.append("target_size_kb", "200");

const response = await fetch("https://api.enconvert.com/v1/convert/compress-image", {
    method: "POST",
    headers: { "X-API-Key": "sk_live_your_private_key" },
    body: form
});

fs.writeFileSync("photo_compressed.png", Buffer.from(await response.arrayBuffer()));

PHP#

$ch = curl_init("https://api.enconvert.com/v1/convert/compress-image");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_live_your_private_key"],
    CURLOPT_POSTFIELDS => [
        "file" => new CURLFile("photo.png"),
        "target_size_kb" => 200
    ]
]);
$output = curl_exec($ch);
curl_close($ch);
file_put_contents("photo_compressed.png", $output);

Go#

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "photo.png")
file, _ := os.Open("photo.png")
io.Copy(part, file)
writer.WriteField("target_size_kb", "200")
writer.Close()

req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/compress-image", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_live_your_private_key")
resp, _ := http.DefaultClient.Do(req)

Risposte di errore#

Stato Condizione
400 Bad Request Il file non è un file .png, .jpg, .jpeg o .webp
400 Bad Request Il contenuto del file non corrisponde alla sua estensione (l'endpoint non cambia mai formato)
400 Bad Request Immagine animata (APNG / WebP animato) — non supportata
400 Bad Request target_size_kb è zero o negativo
422 Unprocessable Entity target_size_kb è presente ma non è un numero intero
400 Bad Request Conversione dell'immagine non riuscita (file corrotto o non supportato)
401 Unauthorized Chiave API / token JWT mancante o non valido
402 Payment Required Limite mensile di conversioni raggiunto
402 Payment Required Limite di storage raggiunto
413 Payload Too Large Il file supera la dimensione massima consentita dal piano
400 Bad Request L'area dell'immagine supera i 40.000.000 di pixel (protezione contro le bombe di decompressione)

Limiti#

Limite Valore
Dimensione massima del file Dipende dal piano (Free: 5 MB)
Dimensioni massime immagine 40.000.000 di pixel (es. 8000x5000)
Formati PNG, JPEG, WebP (solo statici — niente animazioni)
Dimensione target Best effort — i target irraggiungibili restituiscono il file più piccolo ottenibile
Conversioni mensili Dipende dal piano

Domande frequenti#

Come comprimo un'immagine senza perdere qualità?#

Invia l'immagine a /v1/convert/compress-image senza target_size_kb. L'endpoint rimuove i metadati e ricodifica con le impostazioni lossless più aggressive per il formato — PNG e WebP lossless restano identici pixel per pixel, e il JPEG mantiene le sue tabelle di quantizzazione originali quindi non viene introdotta alcuna ulteriore perdita di quantizzazione. Il risultato non è mai più grande del tuo input.

Come comprimo un'immagine fino a una dimensione file specifica?#

Passa target_size_kb con il tuo budget in kilobyte (ad esempio 200 per 200 KB). L'ottimizzazione lossless viene eseguita per prima; se il file è ancora oltre il budget, l'immagine viene ridimensionata verso il basso con le proporzioni bloccate finché non rientra. Se il target è irraggiungibile anche alla scala minima, ottieni il file più piccolo ottenibile invece di un errore.

La compressione cambia il formato dell'immagine?#

No, mai. PNG resta PNG, JPEG resta JPEG, WebP resta WebP — l'endpoint rifiuta i file il cui contenuto non corrisponde all'estensione invece di convertirli silenziosamente.

I metadati della mia immagine vengono rimossi?#

EXIF, XMP e i chunk di testo PNG vengono rimossi, il che spesso fa risparmiare spazio già da solo. Due cose vengono deliberatamente conservate: il profilo colore ICC (così i colori non cambiano nei viewer con gestione del colore) e il flag di orientamento EXIF (così le foto ruotate continuano a essere visualizzate correttamente).

Posso comprimere immagini animate?#

No. I file APNG e WebP animati vengono rifiutati con un errore 400 invece di essere silenziosamente appiattiti a un singolo fotogramma.