Format Keluaran PNG Delta

Dapatkan Kunci API

Bermigrasi dari penyedia lain? Check out our migration guide

Format keluaran Delta PNG dapat menghemat banyak latensi dan bandwidth, dan sangat berguna dalam skenario kritis latensi & bandwidth seperti aplikasi seluler.

Hal ini mengharuskan piksel dalam gambar asli dimuat di klien, dan kemudian Delta PNG diterapkan ke gambar asli untuk menghasilkan gambar hasil.

Contohnya:

Asli

778 × 639 px

PNG biasa

409.048 byte

Delta PNG

110.904 byte
Penghematan 73%.

Bahkan dalam contoh yang sangat sederhana ini (yang merupakan skenario terburuk untuk format Delta PNG), penghematannya signifikan: 73%

Menguraikan Delta PNG

Delta PNG hanyalah file PNG biasa dan dapat dibaca oleh perpustakaan perangkat lunak apa pun yang mampu membaca PNG. Satu-satunya perbedaan dibandingkan dengan hasil PNG biasa adalah pada nilai pikselnya sendiri. Latar belakang dikodekan sebagai 0x00000000 hitam transparan dan latar depan sebagai 0x00FFFFFF putih transparan. Piksel yang sebagian transparan memiliki nilai warna sebenarnya.

Tipe Piksel Asli PNG biasa Delta PNG Sumber Keluaran
Latar Depan 0xFFrrggbb 0xFFrrggbb 0x00FFFFFF Asli
Latar Belakang 0xFFrrggbb 0x00000000 0x00000000 Delta PNG
Tepi 0xFFrrggbb 0x80rrggbb 0x80rrggbb Delta PNG

Artinya saat Anda mendekode nilai piksel Delta PNG, Anda perlu mengambil nilai piksel sebenarnya dari Aslinya saat Anda menemukan 0x00FFFFFF putih transparan. Piksel lainnya memiliki nilai yang sama seperti pada format PNG biasa.

Berikut adalah contoh kode TypeScript untuk mendekode format 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;
}

Untuk mempelajari lebih lanjut tentang pengoperasian data gambar dan piksel dalam JavaScript, lihat tutorial manipulasi piksel dengan kanvas yang luar biasa di Jaringan Pengembang Mozilla.

Peringatan

Pustaka pemuatan gambar Anda harus dapat mempertahankan nilai piksel bahkan untuk piksel yang sepenuhnya transparan, seperti itulah cara kerjanya biasanya.

Namun, jika Anda menggunakan mis. Python dan pustaka OpenCV yang terkenal, maka Anda perlu menggunakan flag cv2.IMREAD_UNCHANGED dan memuat gambar seperti ini: cv2.imread(path, cv2.IMREAD_UNCHANGED). Jika tidak, OpenCV akan merusak nilai piksel sebenarnya dari piksel yang sepenuhnya transparan.

Sayangnya OpenCV tidak menerapkan informasi rotasi apa pun yang disimpan dalam gambar saat Anda menggunakan tanda tersebut. Inilah sebabnya kami mengembalikan header X-Input-Orientation sehingga Anda bisa menerapkan orientasi yang benar pada gambar dalam skenario ini.

Berikut adalah contoh kode Python+OpenCV untuk menerapkan orientasi:

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
Dapatkan Kunci API