Python CFFI bindings for image format libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

119 lines
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)