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:
Bahkan dalam contoh yang sangat sederhana ini (yang merupakan skenario terburuk untuk format Delta PNG), penghematannya signifikan: 73%
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.
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