Skip to content

Commit

Permalink
Adds optional parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbyttow committed Jan 19, 2021
1 parent 5fa8d51 commit f2de139
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 57 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ build: FORCE
test: FORCE
CGO_CFLAGS_ALLOW=-Xpreprocessor go test -v ./...

FORCE:
FORCE:
227 changes: 207 additions & 20 deletions vips/foreign.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@

#include "lang.h"

void set_bool_param(Param *p, gboolean b) {
p->type = PARAM_TYPE_BOOL;
p->value.b = b;
p->is_set = TRUE;
}

void set_int_param(Param *p, gint i) {
p->type = PARAM_TYPE_INT;
p->value.i = i;
p->is_set = TRUE;
}

void set_double_param(Param *p, gdouble d) {
p->type = PARAM_TYPE_DOUBLE;
p->value.d = d;
p->is_set = TRUE;
}

gboolean get_bool_param(Param *p) { return p->value.b; }
gboolean get_int_param(Param *p) { return p->value.i; }
gboolean get_double_param(Param *p) { return p->value.d; }

int load_image_buffer(LoadParams *params, void *buf, size_t len,
VipsImage **out) {
int code = 1;
Expand Down Expand Up @@ -51,30 +73,133 @@ int load_image_buffer(LoadParams *params, void *buf, size_t len,
return code;
}

typedef int (*VipsBuildOperationFn)(VipsOperation *operation,
SaveParams *params);
#define SET_BOOL(OP, PARAM, NAME) \
if (PARAM.is_set) { \
vips_object_set(VIPS_OBJECT(OP), NAME, get_bool_param(&PARAM), NULL); \
}

#define SET_INT(OP, PARAM, NAME) \
if (PARAM.is_set) { \
vips_object_set(VIPS_OBJECT(OP), NAME, get_int_param(&PARAM), NULL); \
}

typedef int (*SetLoadOptionsFn)(VipsOperation *operation, LoadParams *params);

int set_jpegload_options(VipsOperation *operation, LoadParams *params) {
SET_BOOL(operation, params->autorotate, "autorotate");
SET_BOOL(operation, params->fail, "fail");
SET_INT(operation, params->jpegShrink, "shrink");
return 0;
}

int set_pngload_options(VipsOperation *operation, LoadParams *params) {
return 0;
}

int set_webpload_options(VipsOperation *operation, LoadParams *params) {
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
return 0;
}

int set_tiffload_options(VipsOperation *operation, LoadParams *params) {
SET_BOOL(operation, params->autorotate, "autorotate");
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
return 0;
}

int set_gifload_options(VipsOperation *operation, LoadParams *params) {
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
return 0;
}

int set_pdfload_options(VipsOperation *operation, LoadParams *params) {
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
SET_INT(operation, params->dpi, "dpi");
return 0;
}

int set_svgload_options(VipsOperation *operation, LoadParams *params) {
SET_BOOL(operation, params->svgUnlimited, "unlimited");
SET_INT(operation, params->dpi, "dpi");
return 0;
}

int set_heifload_options(VipsOperation *operation, LoadParams *params) {
SET_BOOL(operation, params->autorotate, "autorotate");
SET_BOOL(operation, params->heifThumbnail, "thumbnail");
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
return 0;
}

int set_magickload_options(VipsOperation *operation, LoadParams *params) {
SET_INT(operation, params->page, "page");
SET_INT(operation, params->n, "n");
return 0;
}

int load_buffer(const char *operationName, void *buf, size_t len,
LoadParams *params, SetLoadOptionsFn setLoadOptions) {
VipsBlob *blob = vips_blob_new(NULL, buf, len);

VipsOperation *operation = vips_operation_new(operationName);
if (!operation) {
return 1;
}

if (vips_object_set(VIPS_OBJECT(operation), "buffer", blob, NULL)) {
vips_area_unref(VIPS_AREA(blob));
return 1;
}

vips_area_unref(VIPS_AREA(blob));

if (setLoadOptions(operation, params)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 1;
}

if (vips_cache_operation_buildp(&operation)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return 1;
}

g_object_get(VIPS_OBJECT(operation), "out", &params->outputImage, NULL);

g_object_unref(operation);

return 0;
}

typedef int (*SetSaveOptionsFn)(VipsOperation *operation, SaveParams *params);

int save_buffer(const char *operationName, SaveParams *params,
VipsBuildOperationFn buildFn) {
SetSaveOptionsFn setSaveOptions) {
VipsBlob *blob;
VipsOperation *operation = vips_operation_new(operationName);
if (!operation) {
return -1;
return 1;
}

if (vips_object_set(VIPS_OBJECT(operation), "in", params->inputImage, NULL)) {
return -1;
return 1;
}

if (buildFn(operation, params)) {
if (setSaveOptions(operation, params)) {
g_object_unref(operation);
return -1;
return 1;
}

if (vips_cache_operation_buildp(&operation)) {
vips_object_unref_outputs(VIPS_OBJECT(operation));
g_object_unref(operation);
return -1;
return 1;
}

g_object_get(VIPS_OBJECT(operation), "buffer", &blob, NULL);
Expand All @@ -91,7 +216,7 @@ int save_buffer(const char *operationName, SaveParams *params,
}

// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave-buffer
int set_jpeg_options(VipsOperation *operation, SaveParams *params) {
int set_jpegsave_options(VipsOperation *operation, SaveParams *params) {
vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata,
"optimize_coding", params->jpegOptimizeCoding, "interlace",
params->interlace, "subsample_mode", params->jpegSubsample,
Expand All @@ -100,23 +225,27 @@ int set_jpeg_options(VipsOperation *operation, SaveParams *params) {
if (params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}

return 0;
}

// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-pngsave-buffer
int set_png_options(VipsOperation *operation, SaveParams *params) {
int set_pngsave_options(VipsOperation *operation, SaveParams *params) {
vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata,
"compression", params->pngCompression, "interlace",
params->interlace, "filter", params->pngFilter, NULL);

if (params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}

return 0;
}

// todo: support additional params
// https://github.com/libvips/libvips/blob/master/libvips/foreign/webpsave.c#L524
// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-webpsave-buffer
int set_webp_options(VipsOperation *operation, SaveParams *params) {
int set_webpsave_options(VipsOperation *operation, SaveParams *params) {
vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata,
"lossless", params->webpLossless, "reduction_effort",
params->webpReductionEffort, NULL);
Expand All @@ -128,17 +257,19 @@ int set_webp_options(VipsOperation *operation, SaveParams *params) {

// todo: support additional params
// https://github.com/libvips/libvips/blob/master/libvips/foreign/heifsave.c#L653
int set_heif_options(VipsOperation *operation, SaveParams *params) {
int set_heifsave_options(VipsOperation *operation, SaveParams *params) {
vips_object_set(VIPS_OBJECT(operation), "lossless", params->heifLossless,
NULL);

if (params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}

return 0;
}

// https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-tiffsave-buffer
int set_tiff_options(VipsOperation *operation, SaveParams *params) {
int set_tiffsave_options(VipsOperation *operation, SaveParams *params) {
vips_object_set(VIPS_OBJECT(operation), "strip", params->stripMetadata,
"compression", params->tiffCompression, "predictor",
params->tiffPredictor, "pyramid", params->tiffPyramid,
Expand All @@ -149,26 +280,82 @@ int set_tiff_options(VipsOperation *operation, SaveParams *params) {
if (params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}

return 0;
}

int load_from_buffer(LoadParams *params, void *buf, size_t len) {
switch (params->inputFormat) {
case JPEG:
return load_buffer("jpegload_buffer", buf, len, params,
set_jpegload_options);
case PNG:
return load_buffer("pngload_buffer", buf, len, params,
set_pngload_options);
case WEBP:
return load_buffer("webpload_buffer", buf, len, params,
set_webpload_options);
case HEIF:
return load_buffer("heifload_buffer", buf, len, params,
set_heifload_options);
case TIFF:
return load_buffer("tiffload_buffer", buf, len, params,
set_tiffload_options);
case SVG:
return load_buffer("svgload_buffer", buf, len, params,
set_svgload_options);
case GIF:
return load_buffer("gifload_buffer", buf, len, params,
set_gifload_options);
case PDF:
return load_buffer("pdfload_buffer", buf, len, params,
set_pdfload_options);
case MAGICK:
return load_buffer("magickload_buffer", buf, len, params,
set_magickload_options);
default:
g_warning("Unsupported input type given: %d", params->inputFormat);
}
return 1;
}

int save_to_buffer(SaveParams *params) {
switch (params->outputFormat) {
case JPEG:
return save_buffer("jpegsave_buffer", params, set_jpeg_options);
return save_buffer("jpegsave_buffer", params, set_jpegsave_options);
case PNG:
return save_buffer("pngsave_buffer", params, set_png_options);
return save_buffer("pngsave_buffer", params, set_pngsave_options);
case WEBP:
return save_buffer("webpsave_buffer", params, set_webp_options);
return save_buffer("webpsave_buffer", params, set_webpsave_options);
case HEIF:
return save_buffer("heifsave_buffer", params, set_heif_options);
return save_buffer("heifsave_buffer", params, set_heifsave_options);
case TIFF:
return save_buffer("tiffsave_buffer", params, set_tiff_options);
return save_buffer("tiffsave_buffer", params, set_tiffsave_options);
default:
g_warning("Unsupported output type given: %d", params->outputFormat);
return -1;
}
return 1;
}

#define DEFAULT_PARAM \
{ \
type: \
PARAM_TYPE_NULL, value : 0, is_set : FALSE \
}

static LoadParams defaultLoadParams = {
inputBlob : NULL,
outputImage : NULL,
autorotate : DEFAULT_PARAM,
fail : DEFAULT_PARAM,
page : DEFAULT_PARAM,
n : DEFAULT_PARAM,
dpi : DEFAULT_PARAM,
jpegShrink : DEFAULT_PARAM,
heifThumbnail : DEFAULT_PARAM,
svgUnlimited : DEFAULT_PARAM,
};

static SaveParams defaultSaveParams = {
inputImage : NULL,
outputBuffer : NULL,
Expand Down Expand Up @@ -207,7 +394,7 @@ SaveParams create_save_params(ImageType outputFormat) {
}

LoadParams create_load_params(ImageType inputFormat) {
LoadParams params;
LoadParams params = defaultLoadParams;
params.inputFormat = inputFormat;
return params;
}
40 changes: 28 additions & 12 deletions vips/foreign.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ func vipsLoadFromBuffer(buf []byte, params *LoadParams) (*C.VipsImage, ImageType
defer runtime.KeepAlive(src)

var err error
var out *C.VipsImage

imageType := DetermineImageType(src)

Expand All @@ -231,11 +230,11 @@ func vipsLoadFromBuffer(buf []byte, params *LoadParams) (*C.VipsImage, ImageType

loadParams := createLoadParams(imageType, params)

if err := C.load_image_buffer(&loadParams, unsafe.Pointer(&src[0]), C.size_t(len(src)), &out); err != 0 {
return nil, ImageTypeUnknown, handleImageError(out)
if err := C.load_from_buffer(&loadParams, unsafe.Pointer(&src[0]), C.size_t(len(src))); err != 0 {
return nil, ImageTypeUnknown, handleImageError(loadParams.outputImage)
}

return out, imageType, nil
return loadParams.outputImage, imageType, nil
}

func bmpToPNG(src []byte) ([]byte, error) {
Expand All @@ -255,14 +254,31 @@ func bmpToPNG(src []byte) ([]byte, error) {

func createLoadParams(format ImageType, params *LoadParams) C.LoadParams {
p := C.create_load_params(C.ImageType(format))
p.autorotate = C.int(boolToInt(params.AutoRotate))
p.fail = C.int(boolToInt(params.FailOnError))
p.page = C.int(params.Page)
p.n = C.int(params.NumPages)
p.dpi = C.gdouble(params.Density)
p.jpegShrink = C.int(params.JpegShrinkFactor)
p.heifThumbnail = C.int(boolToInt(params.HeifThumbnail))
p.svgUnlimited = C.int(boolToInt(params.SvgUnlimited))

if params.AutoRotate.IsSet() {
C.set_bool_param(&p.autorotate, toGboolean(params.AutoRotate.Get()))
}
if params.FailOnError.IsSet() {
C.set_bool_param(&p.fail, toGboolean(params.FailOnError.Get()))
}
if params.Page.IsSet() {
C.set_int_param(&p.page, C.gint(params.Page.Get()))
}
if params.NumPages.IsSet() {
C.set_int_param(&p.page, C.gint(params.NumPages.Get()))
}
if params.Density.IsSet() {
C.set_int_param(&p.dpi, C.gint(params.Density.Get()))
}
if params.JpegShrinkFactor.IsSet() {
C.set_int_param(&p.jpegShrink, C.gint(params.JpegShrinkFactor.Get()))
}
if params.HeifThumbnail.IsSet() {
C.set_bool_param(&p.heifThumbnail, toGboolean(params.HeifThumbnail.Get()))
}
if params.SvgUnlimited.IsSet() {
C.set_bool_param(&p.svgUnlimited, toGboolean(params.SvgUnlimited.Get()))
}
return p
}

Expand Down
Loading

0 comments on commit f2de139

Please sign in to comment.