Skip to content

Addition of optional sharpening to resize. #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions vips.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
BICUBIC Interpolator = iota
BILINEAR
NOHALO
LBB
)

type Extend int
Expand All @@ -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
Expand All @@ -64,6 +75,7 @@ type Options struct {
Interpolator Interpolator
Gravity Gravity
Quality int
Sharpen *Sharpen
}

func init() {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
Expand Down
10 changes: 10 additions & 0 deletions vips.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};