Formato del resultado Delta PNG

Obtener la clave de la API

¿Está inmigrando desde otro proveedor? Check out our migration guide

El formato del resultado Delta PNG puede ahorrar latencia y ancho de banda y es especialmente útil en situaciones en las cuales la latencia y el ancho de banda son sumamente importantes, como en aplicaciones móviles.

Requiere que los píxeles de la imagen original se carguen en el cliente, y luego, se aplica el formato Delta PNG a la imagen original para producir la imagen.

Un ejemplo:

Original

778× 639 px

PNG regular

409.048 bytes

Delta PNG

110.904 bytes
Ahorro del 73%.

Hasta en este ejemplo centrado en el cabello (que es el peor de los casos para el formato Delta PNG), los ahorros son considerables: 73%

Descodificación de Delta PNG

Un Delta PNG es solo un archivo PNG normal y lo puede leer cualquier biblioteca de software capaz de leer los PNG. La única diferencia en comparación con el PNG regular es los valores de los píxeles. El fondo está codificado como negro transparente 0x00000000 y el primer plano como blanco transparente 0x00FFFFFF. Los píxeles parcialmente transparentes tienen sus valores de color reales.

Tipo de píxeles Original PNG regular Delta PNG Fuente del resultado
Primer plano 0xFFrrggbb 0xFFrrggbb 0x00FFFFFF Original
Fondo 0xFFrrggbb 0x00000000 0x00000000 Delta PNG
Borde 0xFFrrggbb 0x80rrggbb 0x80rrggbb Delta PNG

Esto significa que cuando está descodificando los valores de los píxeles de Delta PNG, necesita obtener el valor real de los píxeles del Original cuando encuentra blanco transparente 0x00FFFFFF. Los otros píxeles tienen los mismos valores que tiene el formato PNG regular.

Este es un ejemplo del código de TypeScript para descodificar el 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;
}

Para obtener más información sobre cómo manejar sobre una imagen y los datos de los píxeles en JavaScript, consulte el excelente tutorial Manipulación de píxeles con canvas en la red de desarrolladores de Mozilla.

Advertencias

La biblioteca de carga de imágenes debe poder preservar los valores de los píxeles hasta para los píxeles completamente transparentes, que es como normalmente funciona.

Sin embargo, si está usando, p. ej. Python y la conocida biblioteca OpenCV, entonces necesitará usar la etiqueta cv2.IMREAD_UNCHANGED y cargar la imagen the esta manera: cv2.imread(path, cv2.IMREAD_UNCHANGED) De lo contrario, OpenCV destruirá los valores reales de los píxeles completamente transparentes.

Desafortunadamente, OpenCV no aplica ninguna información de rotación almacenada en la imagen cuando se usa esa etiqueta. Es por eso que devolvemos el encabezado X-Input-Orientation para que el usuario pueda aplicar la orientación correcta a la imagen en esta situación.

Este es un ejemplo del código de Python+OpenCV para aplicar la orientación:

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
Obtener la clave de la API