Initial push
This commit is contained in:
0
src/data/__init__.py
Normal file
0
src/data/__init__.py
Normal file
0
src/data/cbindings/__init__.py
Normal file
0
src/data/cbindings/__init__.py
Normal file
15
src/data/cbindings/ctypes_cdll_example_not_working/compile.sh
Executable file
15
src/data/cbindings/ctypes_cdll_example_not_working/compile.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# . CONFIG.sh
|
||||
|
||||
# set -o xtrace ## To debug scripts
|
||||
# set -o errexit ## To exit on error
|
||||
# set -o errunset ## To exit if a variable is referenced but not set
|
||||
|
||||
function main() {
|
||||
cd "$(dirname "")"
|
||||
echo "Working Dir: " $(pwd)
|
||||
|
||||
gcc -shared -o pixels_to_cairo_surface.so -fPIC pixels_to_cairo_surface.c
|
||||
}
|
||||
main "$@";
|
@@ -0,0 +1,71 @@
|
||||
# Python imports
|
||||
import ctypes
|
||||
|
||||
# Lib imports
|
||||
import cairo
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
def _pixels_to_cairo_surface(
|
||||
pixbuf: GdkPixbuf.Pixbuf,
|
||||
width: int,
|
||||
height: int
|
||||
) -> cairo.ImageSurface:
|
||||
rowstride = pixbuf.get_rowstride()
|
||||
has_alpha = pixbuf.get_has_alpha()
|
||||
n_channels = pixbuf.get_n_channels()
|
||||
pixels = memoryview(pixbuf.get_pixels())
|
||||
|
||||
cairo_stride = width * 4
|
||||
cairo_data = bytearray(height * cairo_stride)
|
||||
|
||||
lib = ctypes.cdll.LoadLibrary(".pixels_to_cairo_surface.so")
|
||||
IntArray = ctypes.c_int * len(pixels)
|
||||
pixel_buffer = IntArray(*pixels)
|
||||
lib.pixels_to_cairo_surface.restype = ctypes.POINTER(ctypes.c_uint * (height * cairo_stride))
|
||||
lib.pixels_to_cairo_surface.argtypes = [
|
||||
ctypes.c_int,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_int,
|
||||
ctypes.c_int,
|
||||
ctypes.c_int,
|
||||
ctypes.POINTER(ctypes.c_int)
|
||||
]
|
||||
|
||||
_cairo_data = lib.pixels_to_cairo_surface(
|
||||
rowstride,
|
||||
has_alpha,
|
||||
n_channels,
|
||||
width,
|
||||
height,
|
||||
pixel_buffer
|
||||
)
|
||||
|
||||
cairo_data = _cairo_data.contents
|
||||
|
||||
return cairo.ImageSurface.create_for_data(
|
||||
cairo_data,
|
||||
cairo.FORMAT_ARGB32,
|
||||
width,
|
||||
height,
|
||||
cairo_stride
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
img_path = ""
|
||||
pixbuf = Gtk.Image.new_from_file(img_path).get_pixbuf()
|
||||
width = pixbuf.get_width()
|
||||
height = pixbuf.get_height()
|
||||
_pixels_to_cairo_surface(pixbuf, width, height)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -0,0 +1,38 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
unsigned int *pixels_to_cairo_surface(
|
||||
const int rowstride,
|
||||
const bool has_alpha,
|
||||
const int n_channels,
|
||||
const int width,
|
||||
const int height,
|
||||
const int* pixels
|
||||
) {
|
||||
int cairo_stride = width * 4;
|
||||
unsigned int* cairo_data = malloc(sizeof(unsigned int) * height * cairo_stride);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int p_offset = y * rowstride + x * n_channels;
|
||||
int c_offset = y * cairo_stride + x * 4;
|
||||
|
||||
int r = pixels[p_offset];
|
||||
int g = pixels[p_offset + 1];
|
||||
int b = pixels[p_offset + 2];
|
||||
int a = (has_alpha) ? pixels[p_offset + 3] : 255;
|
||||
|
||||
// Premultiply alpha (important for correct rendering in Cairo)
|
||||
int r_premul = (r * a) / 255;
|
||||
int g_premul = (g * a) / 255;
|
||||
int b_premul = (b * a) / 255;
|
||||
|
||||
// Cairo expects data in BGRA (ARGB32 native endianness)
|
||||
cairo_data[c_offset + 0] = b_premul;
|
||||
cairo_data[c_offset + 1] = g_premul;
|
||||
cairo_data[c_offset + 2] = r_premul;
|
||||
cairo_data[c_offset + 3] = a;
|
||||
}
|
||||
}
|
||||
|
||||
return cairo_data;
|
||||
}
|
9
src/data/cbindings/pixbuf2cairo.py
Normal file
9
src/data/cbindings/pixbuf2cairo.py
Normal file
@@ -0,0 +1,9 @@
|
||||
def __bootstrap__():
|
||||
global __bootstrap__, __loader__, __file__
|
||||
import sys, pkg_resources, importlib.util
|
||||
__file__ = pkg_resources.resource_filename(__name__, 'pixbuf2cairo.cpython-313-x86_64-linux-gnu.so')
|
||||
__loader__ = None; del __bootstrap__, __loader__
|
||||
spec = importlib.util.spec_from_file_location(__name__,__file__)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
__bootstrap__()
|
15
src/data/cbindings/python_package_works/compile.sh
Executable file
15
src/data/cbindings/python_package_works/compile.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# . CONFIG.sh
|
||||
|
||||
# set -o xtrace ## To debug scripts
|
||||
# set -o errexit ## To exit on error
|
||||
# set -o errunset ## To exit if a variable is referenced but not set
|
||||
|
||||
function main() {
|
||||
cd "$(dirname "")"
|
||||
echo "Working Dir: " $(pwd)
|
||||
|
||||
python3 setup.py build && python3 setup.py install --user
|
||||
}
|
||||
main "$@";
|
80
src/data/cbindings/python_package_works/pixbuf2cairo.c
Normal file
80
src/data/cbindings/python_package_works/pixbuf2cairo.c
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <Python.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static PyObject* pixbuf_to_cairo_data(PyObject* self, PyObject* args) {
|
||||
PyObject *py_pixbuf;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &py_pixbuf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GdkPixbuf *pixbuf = (GdkPixbuf *) PyLong_AsVoidPtr(py_pixbuf);
|
||||
if (!GDK_IS_PIXBUF(pixbuf)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Invalid GdkPixbuf pointer.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int width = gdk_pixbuf_get_width(pixbuf);
|
||||
int height = gdk_pixbuf_get_height(pixbuf);
|
||||
int rowstride = gdk_pixbuf_get_rowstride(pixbuf);
|
||||
int n_channels = gdk_pixbuf_get_n_channels(pixbuf);
|
||||
gboolean has_alpha = gdk_pixbuf_get_has_alpha(pixbuf);
|
||||
const guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
|
||||
|
||||
int cairo_stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
|
||||
Py_ssize_t buffer_size = height * cairo_stride;
|
||||
|
||||
guchar *cairo_data = malloc(buffer_size);
|
||||
if (!cairo_data) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y) {
|
||||
const guchar *src = pixels + y * rowstride;
|
||||
guchar *dst = cairo_data + y * cairo_stride;
|
||||
|
||||
for (int x = 0; x < width; ++x) {
|
||||
const guchar *p = src + x * n_channels;
|
||||
guchar *q = dst + x * 4;
|
||||
|
||||
guchar r = p[0];
|
||||
guchar g = p[1];
|
||||
guchar b = p[2];
|
||||
guchar a = 255;
|
||||
|
||||
if (has_alpha) {
|
||||
a = p[3];
|
||||
r = (r * a) / 255;
|
||||
g = (g * a) / 255;
|
||||
b = (b * a) / 255;
|
||||
}
|
||||
|
||||
q[0] = b;
|
||||
q[1] = g;
|
||||
q[2] = r;
|
||||
q[3] = a;
|
||||
}
|
||||
}
|
||||
|
||||
return PyBytes_FromStringAndSize((const char *) cairo_data, buffer_size);
|
||||
}
|
||||
|
||||
static PyMethodDef Methods[] = {
|
||||
{"pixbuf_to_cairo_data", pixbuf_to_cairo_data, METH_VARARGS, "Convert GdkPixbuf* to compatible Cairo ImageSurface data format."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"pixbuf2cairo",
|
||||
NULL,
|
||||
-1,
|
||||
Methods
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC PyInit_pixbuf2cairo(void) {
|
||||
return PyModule_Create(&moduledef);
|
||||
}
|
31
src/data/cbindings/python_package_works/setup.py
Normal file
31
src/data/cbindings/python_package_works/setup.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from setuptools import setup, Extension
|
||||
import gi
|
||||
gi.require_version("GdkPixbuf", "2.0")
|
||||
|
||||
from gi.repository import GdkPixbuf
|
||||
from gi.repository import GObject
|
||||
|
||||
pkg_config_args = [
|
||||
"--cflags", "--libs",
|
||||
"gdk-pixbuf-2.0",
|
||||
"cairo"
|
||||
]
|
||||
|
||||
from subprocess import check_output
|
||||
|
||||
def get_pkgconfig_flags(flag_type):
|
||||
return check_output(["pkg-config", flag_type] + pkg_config_args).decode().split()
|
||||
|
||||
ext = Extension(
|
||||
"pixbuf2cairo",
|
||||
sources=["pixbuf2cairo.c"],
|
||||
include_dirs=[],
|
||||
extra_compile_args=get_pkgconfig_flags("--cflags"),
|
||||
extra_link_args=get_pkgconfig_flags("--libs")
|
||||
)
|
||||
|
||||
setup(
|
||||
name="pixbuf2cairo",
|
||||
version="0.1",
|
||||
ext_modules=[ext]
|
||||
)
|
11
src/data/event.py
Normal file
11
src/data/event.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import cairo
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Event:
|
||||
def __init__(self):
|
||||
super(Event, self).__init__()
|
11
src/data/mouse_buttons.py
Normal file
11
src/data/mouse_buttons.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class MouseButton:
|
||||
LEFT_BUTTON = 1
|
||||
MIDDLE_BUTTON = 2
|
||||
RIGHT_BUTTON = 3
|
13
src/data/point.py
Normal file
13
src/data/point.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Point:
|
||||
def __init__(self, x = 0, y = 0):
|
||||
super(Point, self).__init__()
|
||||
|
||||
self.x: int = x
|
||||
self.y: int = y
|
10
src/data/points.py
Normal file
10
src/data/points.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Points(list):
|
||||
def __init__(self):
|
||||
super(Points, self).__init__()
|
Reference in New Issue
Block a user