Vous migrez depuis un autre fournisseur ? Check out our migration guide
Le format de sortie Delta PNG permet d'économiser beaucoup de latence et de bande passante, et est particulièrement utile dans les scénarios critiques en matière de latence et de bande passante, comme les applications mobiles.
Cela nécessite que les pixels de l'image d'origine soient chargés sur le client, puis que le Delta PNG soit appliqué à l'image d'origine pour produire l'image résultante.
Exemple :
Même dans cet exemple centré sur les cheveux (qui est le pire des cas pour le format Delta PNG), les économies sont significatives : 73 %
Un fichier Delta PNG est un fichier PNG ordinaire et peut être lu par n’importe quelle bibliothèque logicielle capable de lire les PNG. La seule différence par rapport à un résultat PNG classique réside dans les valeurs des pixels elles-mêmes. L'arrière-plan est codé en noir transparent 0x00000000
et le premier plan en blanc transparent 0x00FFFFFF
. Les pixels partiellement transparents ont leurs valeurs de couleur réelles.
Type de pixels | Original | PNG classique | Delta PNG | Source de sortie |
---|---|---|---|---|
Avant-plan |
0xFFrrggbb
|
0xFFrrggbb
|
0x00FFFFFF
|
Original |
Arrière-plan |
0xFFrrggbb
|
0x00000000
|
0x00000000
|
Delta PNG |
Bord |
0xFFrrggbb
|
0x80rrggbb
|
0x80rrggbb
|
Delta PNG |
Cela signifie que lorsque vous décodez les valeurs de pixels Delta PNG, vous devez extraire la valeur réelle des pixels de l'original lorsque vous rencontrez un blanc transparent 0x00FFFFFF
. Les autres pixels ont les mêmes valeurs que celles du format PNG classique.
Voici un exemple de code TypeScript pour décoder le 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; }
Pour en savoir plus sur l'utilisation des données d'image et de pixels en JavaScript, consultez l'excellent didacticiel Manipulation des pixels avec canevas sur le réseau de développeurs Mozilla.
824 / 5,000 Translation results Translation result Votre bibliothèque de chargement d'images doit être capable de conserver les valeurs des pixels même pour les pixels entièrement transparents, ce qui correspong au fonctionnement normal.
Cependant, si vous utilisez par ex. Python et la célèbre bibliothèque OpenCV, vous devez alors utiliser l'indicateur cv2.IMREAD_UNCHANGED
et charger l'image comme ceci : cv2.imread(path, cv2.IMREAD_UNCHANGED)
. Sinon, OpenCV écrasera les valeurs réelles des pixels entièrement transparents.
Malheureusement, OpenCV n'applique aucune information de rotation stockée dans l'image lorsque vous utilisez cet indicateur. C'est pourquoi nous renvoyons l'en-tête X-Input-Orientation
afin que vous puissiez appliquer la bonne orientation à l'image dans ce scénario.
Voici un exemple de code Python+OpenCV pour appliquer l'orientation :
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