Formato output Delta PNG

Ottieni chiave API

Stai effettuando la migrazione da un altro provider? Check out our migration guide

Il formato di output Delta PNG può far risparmiare molta latenza e larghezza di banda, cosa particolarmente utile quando la latenza e la larghezza di banda sono un fattore da considerare, come le app mobili.

Richiede il caricamento sul client dei pixel nell'immagine originale, e l'applicazione di Delta PNG all'immagine originale per la produzione dell'immagine risultato.

Un esempio:

Originale

778 × 639 px

PNG regolare

409.048 byte

Delta PNG

110.904 byte
73& di risparmio.

Anche in questo esempio centrato sui capelli (peggior caso per il formato Delta PNG), i risparmi sono notevoli: 73%

Decodificazione di Delta PNG

Un file Delta PNG è un file PNG regolare e può essere letto da qualsiasi libreria software in grado di leggere file PNG. L'unica differenza rispetto a un risultato PNG regolare consiste nei valori di pixel. Lo sfondo è codificato come nero trasparente 0x00000000 e il primo piano come bianco trasparente 0x00FFFFFF. I pixel parzialmente trasparenti hanno i propri valori effettivi di colore.

Tipo di pixel Originale PNG regolare Delta PNG Fonte di output
Primo piano 0xFFrrggbb 0xFFrrggbb 0x00FFFFFF Originale
Sfondo 0xFFrrggbb 0x00000000 0x00000000 Delta PNG
Bordo 0xFFrrggbb 0x80rrggbb 0x80rrggbb Delta PNG

Ciò significa che quando decodifichi i valori di pixel Delta PNG, devi solamente prendere il valore di pixel attuale dall'Originale quando vedi il bianco trasparente 0x00FFFFFF. Gli altri pixel hanno lo stesso valore nel formato PNG regolare.

Ecco un esempio di codice TypeScript per la decodifica del formato Delta PNG:

export function decodeDeltaPngInPlace(originalPixels: Uint8Array, deltaPngPixels: Uint8Array): Uint8Array {
    const N = originalPixels.length / 4; // Array of RGBA values, div 4 to get number of pixels
    for (let i = 0; i < N; i++) {
        const i4 = i * 4;
        const alpha = deltaPngPixels[i4 + 3]; // JavaScript is RGBA, +3 to get alpha
        if (alpha == 0) {
            const r = deltaPngPixels[i4]; // JavaScript is RGBA, +0 to get red
            if (r == 0xFF) {
                // Transparent white => foreground => take values from original
                deltaPngPixels[i4] = originalPixels[i4];
                deltaPngPixels[i4 + 1] = originalPixels[i4 + 1];
                deltaPngPixels[i4 + 2] = originalPixels[i4 + 2];
                deltaPngPixels[i4 + 3] = originalPixels[i4 + 3];
            } // else transparent black => background => keep values
        } // else partially transparent => keep values
    }
    return deltaPngPixels;
}

Per maggiori informazioni sulle operazioni con immagini e dati di pixel in JavaScript, consulta l'eccellente guida Pixel manipulation with canvas tutorial sulla Mozilla Developer Network.

Avvertimento

La tua libreria di caricamento immagini deve essere in grado di preservare i valori di pixel anche per i pixel interamente trasparenti, come funziona normalmente.

Tuttavia, se usi per esempio Python e la nota libreria OpenCV, devi usare il flag cv2.IMREAD_UNCHANGED e caricare l'immagine nel seguente modo: cv2.imread(path, cv2.IMREAD_UNCHANGED). In caso contrario OpenCV altera i valori di pixel effettivi dei pixel completamente trasparenti.

Purtroppo OpenCV non applica nessuna informazione di rotazione conservata nell'immagine quando usi il flag. Per questo motivo restituiamo l'intestazione X-Input-Orientation per consentirti di applicare l'orientamento corretto all'immagine in tale caso.

Il seguente è un esempio di codice Python+OpenCV per applicare l'orientamento:

def apply_exif_rotation(im: np.ndarray, orientation: int) -> np.ndarray:
    # https://note.nkmk.me/en/python-opencv-numpy-rotate-flip/
    if 1 < orientation <= 8:
        if 2 == orientation:  # TOP-RIGHT, flip left-right, [1, 1] -> [-1, 1]
            im = cv2.flip(im, 1)
        elif 3 == orientation:  # BOTTOM-RIGHT, rotate 180
            im = cv2.rotate(im, cv2.ROTATE_180)
        elif 4 == orientation:  # BOTTOM-LEFT, flip up-down, [1, 1] -> [1, -1]
            im = cv2.flip(im, 0)
        elif 5 == orientation:  # LEFT-TOP, Rotate 90 and flip left-right
            im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
            im = cv2.flip(im, 1)
        elif 6 == orientation:  # RIGHT-TOP, Rotate 90
            im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
        elif 7 == orientation:  # RIGHT-BOTTOM,
            im = cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
            im = cv2.flip(im, 0)
        else:  # 8 == orientation:  # LEFT-BOTTOM, Rotate 270
            im = cv2.rotate(im, cv2.ROTATE_90_COUNTERCLOCKWISE)
    return im
Ottieni chiave API