Python CFFI bindings for image format libraries
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 

119 lignes
3.5 KiB

#!/usr/bin/env python3
# libflif cffi bindings
# (c) 2017 Taeyeon Mori
import os
import re
import cffi
from simplecpp import simple_cpp
flif_headers = "/usr/include/FLIF"
# --------------------------------------------------------------
# helper source code
source = """
#include <FLIF/flif.h>
#include <Python.h>
/*
uint32_t flif_python_callback(uint32_t quality, int64_t bytes_read, uint8_t decode_over, void *user_data, void *context)
{
PyObject *py_callback = user_data;
if (!user_data)
{
PyErr_SetString(PyExc_ValueError, "user_data cannot be NULL for python callbacks");
return 0;
}
// TODO
} */
void flif_image_read_into_GRAY8(FLIF_IMAGE *image, void *buffer, size_t buffer_size)
{
uint32_t rows = flif_image_get_height(image);
uint32_t columns = flif_image_get_width(image);
for (uint32_t row = 0; row < rows && (row + 1) * columns <= buffer_size; ++row)
{
flif_image_read_row_GRAY8(image, row, buffer + row * columns, columns);
}
}
void flif_image_read_into_RGBA8(FLIF_IMAGE *image, void *buffer, size_t buffer_size)
{
uint32_t rows = flif_image_get_height(image);
uint32_t columns = flif_image_get_width(image);
for (uint32_t row = 0; row < rows && (row + 1) * columns * 4 <= buffer_size; ++row)
{
flif_image_read_row_RGBA8(image, row, buffer + row * columns * 4, columns * 4);
}
}
void flif_image_read_into_RGB8(FLIF_IMAGE *image, void *buffer, size_t buffer_size)
{
uint32_t rows = flif_image_get_height(image);
uint32_t columns = flif_image_get_width(image);
uint32_t row;
for (row = 0; row < rows && row * columns * 3 + columns * 4 <= buffer_size; ++row)
{
// Read RGBA8
uint8_t *row_buf = (uint8_t *)buffer + row * columns * 3;
flif_image_read_row_RGBA8(image, row, row_buf, columns * 4);
// Remove Alpha channel
for (uint32_t col = 1; col < columns; ++col)
{
row_buf[col * 3] = row_buf[col * 4];
row_buf[col * 3 + 1] = row_buf[col * 4 + 1];
row_buf[col * 3 + 2] = row_buf[col * 4 + 2];
}
}
// Last row
if (row < rows && buffer_size >= (row + 1) * columns * 3)
{
uint8_t lastrow_buf[columns * 4];
uint8_t *row_buf = (uint8_t *)buffer + row * columns * 3;
flif_image_read_row_RGBA8(image, row, lastrow_buf, columns * 4);
for (uint32_t col = 0; col < columns; ++col)
{
row_buf[col * 3] = lastrow_buf[col * 4];
row_buf[col * 3 + 1] = lastrow_buf[col * 4 + 1];
row_buf[col * 3 + 2] = lastrow_buf[col * 4 + 2];
}
}
}
"""
# --------------------------------------------------------------
# Initialize CFFI
libflif = cffi.FFI()
libflif.set_source("imglibs._libflif", source, libraries=["flif"])
# --------------------------------------------------------------
# Import libflif symbols
defs = {}
for header in ("flif_common.h", "flif_dec.h", "flif_enc.h"):
with open(os.path.join(flif_headers, header), "r") as f:
libflif.cdef("".join(simple_cpp(f, defs)))
# --------------------------------------------------------------
# Define above helper funcs
libflif.cdef("""
void flif_image_read_into_GRAY8(FLIF_IMAGE *image, void *buffer, size_t buffer_size);
void flif_image_read_into_RGBA8(FLIF_IMAGE *image, void *buffer, size_t buffer_size);
void flif_image_read_into_RGB8(FLIF_IMAGE *image, void *buffer, size_t buffer_size);
""")
# --------------------------------------------------------------
# Build
if __name__ == "__main__":
libflif.compile(verbose=True)