diff --git a/README.md b/README.md index bad079e..d4799d2 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,40 @@ if err != nil { // do some with your resized image `buf` ``` +An image can be sharpened after resizing: + +```go +sharpen := vips.Sharpen{ + Radius: 1, + X1: 1.1, + Y2: 3, + Y3: 6, + M1: 0.3, + M2: 0.3, +} +options := vips.Options{ + Width: 800, + Height: 600, + Crop: false, + Extend: vips.EXTEND_WHITE, + Interpolator: vips.BILINEAR, + Gravity: vips.CENTRE, + Quality: 95, + Sharpen: &sharpen, +} +f, _ := os.Open("/tmp/test.jpg") +inBuf, _ := ioutil.ReadAll(f) +buf, err := vips.Resize(inBuf, options) +if err != nil { + fmt.Fprintln(os.Stderr, err) + return +} +// do some with your resized image `buf` +``` + +Information on sharpening can be found in the VIPS [documentation](http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-convolution.html#vips-sharpen). +The sample values above give a pleasing on screen sharpening without too many messy artefacts at most sizes. + ## Performance Test by @lovell diff --git a/vips.go b/vips.go index 0a30bf4..3aaf510 100644 --- a/vips.go +++ b/vips.go @@ -37,6 +37,7 @@ const ( BICUBIC Interpolator = iota BILINEAR NOHALO + LBB ) type Extend int @@ -50,10 +51,20 @@ var interpolations = map[Interpolator]string{ BICUBIC: "bicubic", BILINEAR: "bilinear", NOHALO: "nohalo", + LBB: "lbb", } func (i Interpolator) String() string { return interpolations[i] } +type Sharpen struct { + Radius int + X1 float64 + Y2 float64 + Y3 float64 + M1 float64 + M2 float64 +} + type Options struct { Height int Width int @@ -64,6 +75,7 @@ type Options struct { Interpolator Interpolator Gravity Gravity Quality int + Sharpen *Sharpen } func init() { @@ -155,6 +167,7 @@ func Resize(buf []byte, o Options) ([]byte, error) { case o.Width > 0 && o.Height > 0: xf := float64(inWidth) / float64(o.Width) yf := float64(inHeight) / float64(o.Height) + if o.Crop { factor = math.Min(xf, yf) } else { @@ -307,6 +320,15 @@ func Resize(buf []byte, o Options) ([]byte, error) { debug("canvased same as affined") } + if o.Sharpen != nil { + err := C.vips_sharpen_0(image, &tmpImage, C.int(o.Sharpen.Radius), C.double(o.Sharpen.X1), C.double(o.Sharpen.Y2), C.double(o.Sharpen.Y3), C.double(o.Sharpen.M1), C.double(o.Sharpen.M2)) + if err != 0 { + return nil, resizeError() + } + C.g_object_unref(C.gpointer(image)) + image = tmpImage + } + // Always convert to sRGB colour space C.vips_colourspace_0(image, &tmpImage, C.VIPS_INTERPRETATION_sRGB) C.g_object_unref(C.gpointer(image)) diff --git a/vips.h b/vips.h index e02a4e4..016ca5b 100644 --- a/vips.h +++ b/vips.h @@ -67,3 +67,13 @@ vips_jpegsave_custom(VipsImage *in, void **buf, size_t *len, int strip, int qual { return vips_jpegsave_buffer(in, buf, len, "strip", strip, "Q", quality, "optimize_coding", TRUE, "interlace", interlace, NULL); } + +int +vips_sharpen_0(VipsImage *in, VipsImage **out, int radius, double x1, double y2, double y3, double m1, double m2) { + return vips_sharpen(in, out, "radius", radius, "x1", x1, "y2", y2, "y3", y3, "m1", m1, "m2", m2, NULL); +}; + +int +vips_resize_0(VipsImage *in, VipsImage **out, double scale, VipsInterpolate *interpolator) { + return vips_resize(in, out, scale, "interpolate", interpolator, NULL); +}; \ No newline at end of file