From 2fcf9ff0cc9008fcd0169c7f6a2a68fc2e21c634 Mon Sep 17 00:00:00 2001 From: Viktor Sokolov Date: Mon, 30 Jun 2025 15:35:20 +0200 Subject: [PATCH] AsyncSource -> ImgproxySource --- vips/source.c | 146 +++++++++++-------------------------------------- vips/source.go | 16 +++--- vips/source.h | 27 ++++----- vips/vips.c | 52 +++++++++--------- vips/vips.go | 12 ++-- vips/vips.h | 17 +++--- 6 files changed, 94 insertions(+), 176 deletions(-) diff --git a/vips/source.c b/vips/source.c index 2294a374..cfd52f2e 100644 --- a/vips/source.c +++ b/vips/source.c @@ -1,166 +1,86 @@ #include "source.h" -// --- async source ---------------------------------------------------------------------- - // define glib subtype for vips async source -#define VIPS_TYPE_ASYNC_SOURCE (vips_async_source_get_type()) -G_DEFINE_FINAL_TYPE(VipsAsyncSource, vips_async_source, VIPS_TYPE_SOURCE) +#define VIPS_TYPE_IMGPROXY_SOURCE (vips_imgproxy_source_get_type()) +G_DEFINE_FINAL_TYPE(VipsImgproxySource, vips_imgproxy_source, VIPS_TYPE_SOURCE) -extern void closeAsyncReader(uintptr_t handle); -extern gint64 asyncReaderSeek(uintptr_t handle, gint64 offset, int whence); -extern gint64 asyncReaderRead(uintptr_t handle, gpointer buffer, gint64 size); - -// loads jpeg from a source -int -vips_jpegload_source_go(VipsAsyncSource *source, int shrink, VipsImage **out) -{ - if (shrink > 1) - return vips_jpegload_source(VIPS_SOURCE(source), out, "shrink", shrink, - NULL); - - return vips_jpegload_source(VIPS_SOURCE(source), out, NULL); -} - -// loads xjl from source -int -vips_jxlload_source_go(VipsAsyncSource *source, int pages, VipsImage **out) -{ - return vips_jxlload_source(VIPS_SOURCE(source), out, "n", pages, NULL); -} - -int -vips_pngload_source_go(VipsAsyncSource *source, VipsImage **out, int unlimited) -{ - return vips_pngload_source( - VIPS_SOURCE(source), out, - "unlimited", unlimited, - NULL); -} - -int -vips_webpload_source_go(VipsAsyncSource *source, double scale, int pages, VipsImage **out) -{ - return vips_webpload_source( - VIPS_SOURCE(source), out, - "scale", scale, - "n", pages, - NULL); -} - -int -vips_gifload_source_go(VipsAsyncSource *source, int pages, VipsImage **out) -{ - return vips_gifload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL); -} - -int -vips_svgload_source_go(VipsAsyncSource *source, double scale, VipsImage **out, int unlimited) -{ - // libvips limits the minimal scale to 0.001, so we have to scale down dpi - // for lower scale values - double dpi = 72.0; - if (scale < 0.001) { - dpi *= VIPS_MAX(scale / 0.001, 0.001); - scale = 0.001; - } - - return vips_svgload_source( - VIPS_SOURCE(source), out, - "scale", scale, - "dpi", dpi, - "unlimited", unlimited, - NULL); -} - -int -vips_heifload_source_go(VipsAsyncSource *source, VipsImage **out, int thumbnail) -{ - return vips_heifload_source( - VIPS_SOURCE(source), out, - "access", VIPS_ACCESS_SEQUENTIAL, - "thumbnail", thumbnail, - NULL); -} - -int -vips_tiffload_source_go(VipsAsyncSource *source, VipsImage **out) -{ - return vips_tiffload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); -} +extern void closeImgproxyReader(uintptr_t handle); +extern gint64 imgproxyReaderSeek(uintptr_t handle, gint64 offset, int whence); +extern gint64 imgproxyReaderRead(uintptr_t handle, gpointer buffer, gint64 size); // dereferences source void -unref_source(VipsAsyncSource *source) +unref_imgproxy_source(VipsImgproxySource *source) { VIPS_UNREF(source); } -// read function for vips async source +// read function for vips imgproxy source static gint64 -vips_async_source_read(VipsSource *source, void *buffer, size_t length) +vips_imgproxy_source_read(VipsSource *source, void *buffer, size_t length) { - VipsAsyncSource *self = (VipsAsyncSource *) source; + VipsImgproxySource *self = (VipsImgproxySource *) source; - gint64 read_length = asyncReaderRead(self->readerHandle, buffer, length); + gint64 read_length = imgproxyReaderRead(self->readerHandle, buffer, length); if (read_length < 0) { - vips_error("vips_async_source_read", "failed to read from async source"); + vips_error("vips_imgproxy_source_read", "failed to read from imgproxy source"); } return read_length; } -// seek function for vips async source. whence can be SEEK_SET (0), SEEK_CUR (1), or SEEK_END (2). +// seek function for vips imgproxy source. whence can be SEEK_SET (0), SEEK_CUR (1), or SEEK_END (2). static gint64 -vips_async_source_seek(VipsSource *source, gint64 offset, int whence) +vips_imgproxy_source_seek(VipsSource *source, gint64 offset, int whence) { - VipsAsyncSource *self = (VipsAsyncSource *) source; + VipsImgproxySource *self = (VipsImgproxySource *) source; - gint64 actual_offset = asyncReaderSeek(self->readerHandle, offset, whence); + gint64 actual_offset = imgproxyReaderSeek(self->readerHandle, offset, whence); if (actual_offset < 0) { - vips_error("vips_async_source_seek", "failed to seek in async source"); + vips_error("vips_imgproxy_source_seek", "failed to seek in imgproxy source"); } return actual_offset; } static void -vips_async_source_dispose(GObject *gobject) +vips_imgproxy_source_dispose(GObject *gobject) { - VipsAsyncSource *source = (VipsAsyncSource *) gobject; + VipsImgproxySource *source = (VipsImgproxySource *) gobject; - closeAsyncReader(source->readerHandle); + closeImgproxyReader(source->readerHandle); - G_OBJECT_CLASS(vips_async_source_parent_class)->dispose(gobject); + G_OBJECT_CLASS(vips_imgproxy_source_parent_class)->dispose(gobject); } -// attaches seek/read handlers to the async source class +// attaches seek/read handlers to the imgproxy source class static void -vips_async_source_class_init(VipsAsyncSourceClass *klass) +vips_imgproxy_source_class_init(VipsImgproxySourceClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS(klass); VipsObjectClass *object_class = VIPS_OBJECT_CLASS(klass); VipsSourceClass *source_class = VIPS_SOURCE_CLASS(klass); - object_class->nickname = "async_source"; - object_class->description = "async input source"; + object_class->nickname = "imgproxy_source"; + object_class->description = "imgproxy input source"; - gobject_class->dispose = vips_async_source_dispose; + gobject_class->dispose = vips_imgproxy_source_dispose; - source_class->read = vips_async_source_read; - source_class->seek = vips_async_source_seek; + source_class->read = vips_imgproxy_source_read; + source_class->seek = vips_imgproxy_source_seek; } -// initializes the async source (nothing to do here yet) +// initializes the imgproxy source (nothing to do here yet) static void -vips_async_source_init(VipsAsyncSource *source) +vips_imgproxy_source_init(VipsImgproxySource *source) { } -// creates a new async source with the given reader handle -VipsAsyncSource * -vips_new_async_source(uintptr_t readerHandle) +// creates a new imgproxy source with the given reader handle +VipsImgproxySource * +vips_new_imgproxy_source(uintptr_t readerHandle) { - VipsAsyncSource *source = g_object_new(VIPS_TYPE_ASYNC_SOURCE, NULL); + VipsImgproxySource *source = g_object_new(VIPS_TYPE_IMGPROXY_SOURCE, NULL); source->readerHandle = readerHandle; return source; } diff --git a/vips/source.go b/vips/source.go index e639a3c7..499c8e15 100644 --- a/vips/source.go +++ b/vips/source.go @@ -13,16 +13,16 @@ import ( "unsafe" ) -//export closeAsyncReader -func closeAsyncReader(handle C.uintptr_t) { +//export closeImgproxyReader +func closeImgproxyReader(handle C.uintptr_t) { h := cgo.Handle(handle) h.Delete() } // calls seek() on the async reader via it's handle from the C side // -//export asyncReaderSeek -func asyncReaderSeek(handle C.uintptr_t, offset C.int64_t, whence int) C.int64_t { +//export imgproxyReaderSeek +func imgproxyReaderSeek(handle C.uintptr_t, offset C.int64_t, whence int) C.int64_t { h := cgo.Handle(handle) reader, ok := h.Value().(io.ReadSeeker) if !ok { @@ -39,8 +39,8 @@ func asyncReaderSeek(handle C.uintptr_t, offset C.int64_t, whence int) C.int64_t // calls read() on the async reader via it's handle from the C side // -//export asyncReaderRead -func asyncReaderRead(handle C.uintptr_t, pointer unsafe.Pointer, size C.int64_t) C.int64_t { +//export imgproxyReaderRead +func imgproxyReaderRead(handle C.uintptr_t, pointer unsafe.Pointer, size C.int64_t) C.int64_t { h := cgo.Handle(handle) reader, ok := h.Value().(io.ReadSeeker) if !ok { @@ -59,7 +59,7 @@ func asyncReaderRead(handle C.uintptr_t, pointer unsafe.Pointer, size C.int64_t) } // newVipsSource creates a new VipsAsyncSource from an io.ReadSeeker. -func newVipsAsyncSource(r io.ReadSeeker) *C.VipsAsyncSource { +func newVipsImgproxySource(r io.ReadSeeker) *C.VipsImgproxySource { handler := cgo.NewHandle(r) - return C.vips_new_async_source(C.uintptr_t(handler)) + return C.vips_new_imgproxy_source(C.uintptr_t(handler)) } diff --git a/vips/source.h b/vips/source.h index 406b4aaf..f6dca285 100644 --- a/vips/source.h +++ b/vips/source.h @@ -4,29 +4,24 @@ #include #include +#ifndef VIPS_IMGPROXY_SOURCE_H +#define VIPS_IMGPROXY_SOURCE_H + // vips async source -typedef struct _VipsAsyncSource { +typedef struct _VipsImgproxySource { VipsSource source; // class designator uintptr_t readerHandle; // async reader handler -} VipsAsyncSource; +} VipsImgproxySource; // glib class for vips async source -typedef struct _VipsAsyncSourceClass { +typedef struct _VipsImgproxySourceClass { VipsSourceClass parent_class; -} VipsAsyncSourceClass; - -// vips async source read functions -int vips_jpegload_source_go(VipsAsyncSource *source, int shrink, VipsImage **out); -int vips_jxlload_source_go(VipsAsyncSource *source, int pages, VipsImage **out); -int vips_pngload_source_go(VipsAsyncSource *source, VipsImage **out, int unlimited); -int vips_webpload_source_go(VipsAsyncSource *source, double scale, int pages, VipsImage **out); -int vips_gifload_source_go(VipsAsyncSource *source, int pages, VipsImage **out); -int vips_svgload_source_go(VipsAsyncSource *source, double scale, VipsImage **out, int unlimited); -int vips_heifload_source_go(VipsAsyncSource *source, VipsImage **out, int thumbnail); -int vips_tiffload_source_go(VipsAsyncSource *source, VipsImage **out); +} VipsImgproxySourceClass; // creates new vips async source from a reader handle -VipsAsyncSource *vips_new_async_source(uintptr_t readerHandle); +VipsImgproxySource *vips_new_imgproxy_source(uintptr_t readerHandle); + +#endif // unreferences the source, which leads to reader close -void unref_source(VipsAsyncSource *source); +void unref_imgproxy_source(VipsImgproxySource *source); diff --git a/vips/vips.c b/vips/vips.c index 4f4e8912..ecdbdfe5 100644 --- a/vips/vips.c +++ b/vips/vips.c @@ -55,37 +55,39 @@ vips_health() return res; } +// loads jpeg from a source int -vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out) +vips_jpegload_source_go(VipsImgproxySource *source, int shrink, VipsImage **out) { if (shrink > 1) - return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", shrink, + return vips_jpegload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", shrink, NULL); - return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); + return vips_jpegload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); +} + +// loads xjl from source +int +vips_jxlload_source_go(VipsImgproxySource *source, int pages, VipsImage **out) +{ + return vips_jxlload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL); } int -vips_jxlload_go(void *buf, size_t len, int pages, VipsImage **out) +vips_pngload_source_go(VipsImgproxySource *source, VipsImage **out, int unlimited) { - return vips_jxlload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL); -} - -int -vips_pngload_go(void *buf, size_t len, VipsImage **out, int unlimited) -{ - return vips_pngload_buffer( - buf, len, out, + return vips_pngload_source( + VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "unlimited", unlimited, NULL); } int -vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out) +vips_webpload_source_go(VipsImgproxySource *source, double scale, int pages, VipsImage **out) { - return vips_webpload_buffer( - buf, len, out, + return vips_webpload_source( + VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "scale", scale, "n", pages, @@ -93,13 +95,13 @@ vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out } int -vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out) +vips_gifload_source_go(VipsImgproxySource *source, int pages, VipsImage **out) { - return vips_gifload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL); + return vips_gifload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL); } int -vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out, int unlimited) +vips_svgload_source_go(VipsImgproxySource *source, double scale, VipsImage **out, int unlimited) { // libvips limits the minimal scale to 0.001, so we have to scale down dpi // for lower scale values @@ -109,8 +111,8 @@ vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out, int unlimi scale = 0.001; } - return vips_svgload_buffer( - buf, len, out, + return vips_svgload_source( + VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "scale", scale, "dpi", dpi, @@ -119,19 +121,19 @@ vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out, int unlimi } int -vips_heifload_go(void *buf, size_t len, VipsImage **out, int thumbnail) +vips_heifload_source_go(VipsImgproxySource *source, VipsImage **out, int thumbnail) { - return vips_heifload_buffer( - buf, len, out, + return vips_heifload_source( + VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, "thumbnail", thumbnail, NULL); } int -vips_tiffload_go(void *buf, size_t len, VipsImage **out) +vips_tiffload_source_go(VipsImgproxySource *source, VipsImage **out) { - return vips_tiffload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); + return vips_tiffload_source(VIPS_SOURCE(source), out, "access", VIPS_ACCESS_SEQUENTIAL, NULL); } int diff --git a/vips/vips.go b/vips/vips.go index ece718f4..0f2a976c 100644 --- a/vips/vips.go +++ b/vips/vips.go @@ -345,7 +345,8 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64, err := C.int(0) reader := bytes.NewReader(imgdata.Data) - source := newVipsAsyncSource(reader) + source := newVipsImgproxySource(reader) + defer C.unref_imgproxy_source(source) switch imgdata.Type { case imagetype.JPEG: @@ -365,11 +366,9 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64, case imagetype.TIFF: err = C.vips_tiffload_source_go(source, &tmp) default: - C.unref_source(source) return newVipsError("Usupported image type to load") } if err != 0 { - C.unref_source(source) return Error() } @@ -393,10 +392,11 @@ func (img *Image) LoadThumbnail(imgdata *imagedata.ImageData) error { var tmp *C.VipsImage - data := unsafe.Pointer(&imgdata.Data[0]) - dataSize := C.size_t(len(imgdata.Data)) + reader := bytes.NewReader(imgdata.Data) + source := newVipsImgproxySource(reader) + defer C.unref_imgproxy_source(source) - if err := C.vips_heifload_go(data, dataSize, &tmp, C.int(1)); err != 0 { + if err := C.vips_heifload_source_go(source, &tmp, C.int(1)); err != 0 { return Error() } diff --git a/vips/vips.h b/vips/vips.h index 39fd474c..2e7f2f1e 100644 --- a/vips/vips.h +++ b/vips/vips.h @@ -4,6 +4,7 @@ #include #include #include +#include "source.h" typedef struct _RGB { double r; @@ -22,14 +23,14 @@ int gif_resolution_limit(); int vips_health(); -int vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out); -int vips_jxlload_go(void *buf, size_t len, int pages, VipsImage **out); -int vips_pngload_go(void *buf, size_t len, VipsImage **out, int unlimited); -int vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out); -int vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out); -int vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out, int unlimited); -int vips_heifload_go(void *buf, size_t len, VipsImage **out, int thumbnail); -int vips_tiffload_go(void *buf, size_t len, VipsImage **out); +int vips_jpegload_source_go(VipsImgproxySource *source, int shrink, VipsImage **out); +int vips_jxlload_source_go(VipsImgproxySource *source, int pages, VipsImage **out); +int vips_pngload_source_go(VipsImgproxySource *source, VipsImage **out, int unlimited); +int vips_webpload_source_go(VipsImgproxySource *source, double scale, int pages, VipsImage **out); +int vips_gifload_source_go(VipsImgproxySource *source, int pages, VipsImage **out); +int vips_svgload_source_go(VipsImgproxySource *source, double scale, VipsImage **out, int unlimited); +int vips_heifload_source_go(VipsImgproxySource *source, VipsImage **out, int thumbnail); +int vips_tiffload_source_go(VipsImgproxySource *source, VipsImage **out); int vips_black_go(VipsImage **out, int width, int height, int bands);