diff --git a/image.go b/image.go index a3fd629b..53e8d8ea 100644 --- a/image.go +++ b/image.go @@ -196,6 +196,12 @@ func (i *Image) Gamma(exponent float64) ([]byte, error) { return i.Process(options) } +// AddGamma returns the alpha added image buffer. +func (i *Image) AddAlpha() ([]byte, error) { + options := Options{AddAlpha: true} + return i.Process(options) +} + // Process processes the image based on the given transformation options, // talking with libvips bindings accordingly and returning the resultant // image buffer. diff --git a/options.go b/options.go index 59c8c187..a8285c33 100644 --- a/options.go +++ b/options.go @@ -246,6 +246,7 @@ type Options struct { OutputICC string InputICC string Palette bool + AddAlpha bool // Speed defines the AVIF encoders CPU effort. Valid values are: // 0-8 for AVIF encoding. // 0-9 for PNG encoding. diff --git a/resizer.go b/resizer.go index 43be52f5..27ea283e 100644 --- a/resizer.go +++ b/resizer.go @@ -154,6 +154,12 @@ func resizer(buf []byte, o Options) ([]byte, error) { return nil, err } + // Add Alpha, if necessary + image, err = addAlpha(image, o) + if err != nil { + return nil, err + } + return saveImage(image, o) } @@ -437,6 +443,17 @@ func applyGamma(image *C.VipsImage, o Options) (*C.VipsImage, error) { return image, nil } +func addAlpha(image *C.VipsImage, o Options) (*C.VipsImage, error) { + var err error + if o.AddAlpha { + image, err = vipsAddAlpha(image, 255.0) + if err != nil { + return nil, err + } + } + return image, nil +} + func zoomImage(image *C.VipsImage, zoom int) (*C.VipsImage, error) { if zoom == 0 { return image, nil diff --git a/testdata/test.exr b/testdata/test.exr new file mode 100644 index 00000000..bed7d484 Binary files /dev/null and b/testdata/test.exr differ diff --git a/type.go b/type.go index 7b027fdf..cca31535 100644 --- a/type.go +++ b/type.go @@ -32,6 +32,8 @@ const ( HEIF // AVIF represents the AVIF image type. AVIF + // EXR represents the EXR image type. + EXR ) var ( @@ -51,6 +53,7 @@ var ImageTypes = map[ImageType]string{ MAGICK: "magick", HEIF: "heif", AVIF: "avif", + EXR: "exr", } // imageMutex is used to provide thread-safe synchronization diff --git a/type_test.go b/type_test.go index 40ae09ad..d8e384bc 100644 --- a/type_test.go +++ b/type_test.go @@ -23,6 +23,7 @@ func TestDeterminateImageType(t *testing.T) { {"test2.heic", HEIF}, {"test3.heic", HEIF}, {"test.avif", AVIF}, + {"test.exr", EXR}, } for _, file := range files { @@ -53,6 +54,7 @@ func TestDeterminateImageTypeName(t *testing.T) { // {"test.jp2", "magick"}, {"test.heic", "heif"}, {"test.avif", "avif"}, + {"test.exr", "exr"}, } for _, file := range files { @@ -106,6 +108,7 @@ func TestIsTypeNameSupported(t *testing.T) { {"pdf", true}, {"heif", true}, {"avif", true}, + {"exr", true}, } for _, n := range types { diff --git a/vips.go b/vips.go index 911a5f9c..96f4093d 100644 --- a/vips.go +++ b/vips.go @@ -205,6 +205,9 @@ func VipsIsTypeSupported(t ImageType) bool { if t == AVIF { return int(C.vips_type_find_bridge(C.HEIF)) != 0 } + if t == EXR { + return int(C.vips_type_find_bridge(C.MAGICK)) != 0 + } return false } @@ -767,6 +770,10 @@ func vipsImageType(buf []byte) ImageType { buf[8] == 0x61 && buf[9] == 0x76 && buf[10] == 0x69 && buf[11] == 0x66 { return AVIF } + if IsTypeSupported(EXR) && buf[0] == 0x76 && buf[1] == 0x2f && + buf[2] == 0x31 && buf[3] == 0x01 { + return EXR + } return UNKNOWN } @@ -818,6 +825,17 @@ func max(x int) int { return int(math.Max(float64(x), 0)) } +func vipsAddAlpha(image *C.VipsImage, alpha float64) (*C.VipsImage, error) { + var out *C.VipsImage + defer C.g_object_unref(C.gpointer(image)) + + err := C.vips_add_band(image, &out, C.double(alpha)) + if err != 0 { + return nil, catchVipsError() + } + return out, nil +} + func vipsDrawWatermark(image *C.VipsImage, o WatermarkImage) (*C.VipsImage, error) { var out *C.VipsImage