diff --git a/fixtures/test_image_colourspace_b_w.jpg b/fixtures/test_image_colourspace_b_w.jpg new file mode 100644 index 0000000..8afd5bc Binary files /dev/null and b/fixtures/test_image_colourspace_b_w.jpg differ diff --git a/image.go b/image.go index 75889fc..df41161 100644 --- a/image.go +++ b/image.go @@ -134,6 +134,12 @@ func (i *Image) Convert(t ImageType) ([]byte, error) { return i.Process(options) } +// Colour space conversion +func (i *Image) Colourspace(c Interpretation) ([]byte, error) { + options := Options{Interpretation: c} + return i.Process(options) +} + // Transform the image by custom options func (i *Image) Process(o Options) ([]byte, error) { image, err := Resize(i.buffer, o) diff --git a/image_test.go b/image_test.go index d097f21..dc56768 100644 --- a/image_test.go +++ b/image_test.go @@ -262,6 +262,14 @@ func TestImageMetadata(t *testing.T) { } } +func TestImageColourspaceBW(t *testing.T) { + buf, err := initImage("test.jpg").Colourspace(B_W) + if err != nil { + t.Errorf("Cannot process the image: %#v", err) + } + Write("fixtures/test_image_colourspace_b_w.jpg", buf) +} + func TestFluentInterface(t *testing.T) { image := initImage("test.jpg") _, err := image.CropByWidth(300) diff --git a/options.go b/options.go index d29ec3a..da7911e 100644 --- a/options.go +++ b/options.go @@ -55,6 +55,20 @@ const ( VERTICAL Direction = C.VIPS_DIRECTION_VERTICAL ) +type Interpretation int + +const ( + ERROR Interpretation = C.VIPS_INTERPRETATION_ERROR + MULTIBAND Interpretation = C.VIPS_INTERPRETATION_MULTIBAND + B_W Interpretation = C.VIPS_INTERPRETATION_B_W + CMYK Interpretation = C.VIPS_INTERPRETATION_CMYK + RGB Interpretation = C.VIPS_INTERPRETATION_RGB + sRGB Interpretation = C.VIPS_INTERPRETATION_sRGB + RGB16 Interpretation = C.VIPS_INTERPRETATION_RGB16 + GREY16 Interpretation = C.VIPS_INTERPRETATION_GREY16 + scRGB Interpretation = C.VIPS_INTERPRETATION_scRGB +) + const WATERMARK_FONT = "sans 10" // Color represents a traditional RGB color scheme @@ -97,4 +111,5 @@ type Options struct { Watermark Watermark Type ImageType Interpolator Interpolator + Interpretation Interpretation } diff --git a/resize.go b/resize.go index 72c517e..c71b312 100644 --- a/resize.go +++ b/resize.go @@ -122,6 +122,7 @@ func Resize(buf []byte, o Options) ([]byte, error) { Compression: o.Compression, Interlace: o.Interlace, NoProfile: o.NoProfile, + Interpretation: o.Interpretation, } // Finally save as buffer @@ -143,6 +144,9 @@ func applyDefaults(o *Options, imageType ImageType) { if o.Type == 0 { o.Type = imageType } + if o.Interpretation == 0 { + o.Interpretation = sRGB + } } func normalizeOperation(o *Options, inWidth, inHeight int) { diff --git a/vips.go b/vips.go index 5a100ce..90c653c 100644 --- a/vips.go +++ b/vips.go @@ -37,6 +37,7 @@ type vipsSaveOptions struct { Type ImageType Interlace bool NoProfile bool + Interpretation Interpretation } type vipsWatermarkOptions struct { @@ -227,6 +228,10 @@ func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) { length := C.size_t(0) err := C.int(0) interlace := C.int(boolToInt(o.Interlace)) + if o.Interpretation == 0 { + o.Interpretation = sRGB + } + interpretation := C.VipsInterpretation(o.Interpretation) // Remove ICC profile metadata if o.NoProfile { @@ -235,7 +240,7 @@ func vipsSave(image *C.struct__VipsImage, o vipsSaveOptions) ([]byte, error) { // Force RGB color space var outImage *C.struct__VipsImage - C.vips_colourspace_bridge(image, &outImage) + C.vips_colourspace_bridge(image, &outImage, interpretation) defer C.g_object_unref(C.gpointer(image)) defer C.g_object_unref(C.gpointer(outImage)) diff --git a/vips.h b/vips.h index e380b1e..476cabf 100644 --- a/vips.h +++ b/vips.h @@ -135,9 +135,9 @@ vips_extract_area_bridge(VipsImage *in, VipsImage **out, int left, int top, int }; int -vips_colourspace_bridge(VipsImage *in, VipsImage **out) +vips_colourspace_bridge(VipsImage *in, VipsImage **out, VipsInterpretation space) { - return vips_colourspace(in, out, VIPS_INTERPRETATION_sRGB, NULL); + return vips_colourspace(in, out, space, NULL); }; gboolean