AsyncSource -> ImgproxySource

This commit is contained in:
Viktor Sokolov
2025-06-30 15:35:20 +02:00
parent 27e867141e
commit 2fcf9ff0cc
6 changed files with 94 additions and 176 deletions

View File

@@ -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;
}

View File

@@ -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))
}

View File

@@ -4,29 +4,24 @@
#include <vips/vips.h>
#include <vips/connection.h>
#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);

View File

@@ -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

View File

@@ -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()
}

View File

@@ -4,6 +4,7 @@
#include <vips/vips.h>
#include <vips/vips7compat.h>
#include <vips/vector.h>
#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);