diff --git a/type.go b/type.go index dc92aca..260adbf 100644 --- a/type.go +++ b/type.go @@ -51,23 +51,28 @@ var ImageTypes = map[ImageType]string{ // for SupportedImageTypes map. var imageMutex = &sync.RWMutex{} +// SupportedImageType represents whether a type can be loaded and/or saved by +// the current libvips compilation. +type SupportedImageType struct { + Load bool + Save bool +} + // SupportedImageTypes stores the optional image type supported // by the current libvips compilation. // Note: lazy evaluation as demand is required due // to bootstrap runtime limitation with C/libvips world. -var SupportedImageTypes = map[ImageType]bool{} +var SupportedImageTypes = map[ImageType]SupportedImageType{} // discoverSupportedImageTypes is used to fill SupportedImageTypes map. func discoverSupportedImageTypes() { imageMutex.Lock() - SupportedImageTypes[JPEG] = VipsIsTypeSupported(JPEG) - SupportedImageTypes[PNG] = VipsIsTypeSupported(PNG) - SupportedImageTypes[GIF] = VipsIsTypeSupported(GIF) - SupportedImageTypes[WEBP] = VipsIsTypeSupported(WEBP) - SupportedImageTypes[SVG] = VipsIsTypeSupported(SVG) - SupportedImageTypes[TIFF] = VipsIsTypeSupported(TIFF) - SupportedImageTypes[PDF] = VipsIsTypeSupported(PDF) - SupportedImageTypes[MAGICK] = VipsIsTypeSupported(MAGICK) + for imageType := range ImageTypes { + SupportedImageTypes[imageType] = SupportedImageType{ + Load: VipsIsTypeSupported(imageType), + Save: VipsIsTypeSupportedSave(imageType), + } + } imageMutex.Unlock() } @@ -102,7 +107,7 @@ func DetermineImageTypeName(buf []byte) string { // IsImageTypeSupportedByVips returns true if the given image type // is supported by current libvips compilation. -func IsImageTypeSupportedByVips(t ImageType) bool { +func IsImageTypeSupportedByVips(t ImageType) SupportedImageType { imageMutex.RLock() // Discover supported image types and cache the result @@ -113,25 +118,45 @@ func IsImageTypeSupportedByVips(t ImageType) bool { } // Check if image type is actually supported - isSupported, ok := SupportedImageTypes[t] + supported, ok := SupportedImageTypes[t] if !itShouldDiscover { imageMutex.RUnlock() } - return ok && isSupported + if ok { + return supported + } + return SupportedImageType{Load: false, Save: false} } // IsTypeSupported checks if a given image type is supported func IsTypeSupported(t ImageType) bool { _, ok := ImageTypes[t] - return ok && IsImageTypeSupportedByVips(t) + return ok && IsImageTypeSupportedByVips(t).Load } // IsTypeNameSupported checks if a given image type name is supported func IsTypeNameSupported(t string) bool { for imageType, name := range ImageTypes { if name == t { - return IsImageTypeSupportedByVips(imageType) + return IsImageTypeSupportedByVips(imageType).Load + } + } + return false +} + +// IsTypeSupportedSave checks if a given image type is support for saving +func IsTypeSupportedSave(t ImageType) bool { + _, ok := ImageTypes[t] + return ok && IsImageTypeSupportedByVips(t).Save +} + +// IsTypeNameSupportedSave checks if a given image type name is supported for +// saving +func IsTypeNameSupportedSave(t string) bool { + for imageType, name := range ImageTypes { + if name == t { + return IsImageTypeSupportedByVips(imageType).Save } } return false diff --git a/type_test.go b/type_test.go index e769f53..9c83b0f 100644 --- a/type_test.go +++ b/type_test.go @@ -66,7 +66,7 @@ func TestIsTypeSupported(t *testing.T) { for _, n := range types { if IsTypeSupported(n.name) == false { - t.Fatal("Image type is not valid") + t.Fatalf("Image type %#v is not valid", ImageTypes[n.name]) } } } @@ -85,7 +85,44 @@ func TestIsTypeNameSupported(t *testing.T) { for _, n := range types { if IsTypeNameSupported(n.name) != n.expected { - t.Fatal("Image type is not valid") + t.Fatalf("Image type %#v is not valid", n.name) + } + } +} + +func TestIsTypeSupportedSave(t *testing.T) { + types := []struct { + name ImageType + }{ + {JPEG}, {PNG}, {WEBP}, + } + if VipsVersion >= "8.5.0" { + types = append(types, struct{ name ImageType }{TIFF}) + } + + for _, n := range types { + if IsTypeSupportedSave(n.name) == false { + t.Fatalf("Image type %#v is not valid", ImageTypes[n.name]) + } + } +} + +func TestIsTypeNameSupportedSave(t *testing.T) { + types := []struct { + name string + expected bool + }{ + {"jpeg", true}, + {"png", true}, + {"webp", true}, + {"gif", false}, + {"pdf", false}, + {"tiff", VipsVersion >= "8.5.0"}, + } + + for _, n := range types { + if IsTypeNameSupportedSave(n.name) != n.expected { + t.Fatalf("Image type %#v is not valid", n.name) } } } diff --git a/vips.go b/vips.go index 83ff2b0..1544b4a 100644 --- a/vips.go +++ b/vips.go @@ -386,7 +386,7 @@ func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) { interlace := C.int(boolToInt(o.Interlace)) quality := C.int(o.Quality) - if o.Type != 0 && !VipsIsTypeSupportedSave(o.Type) { + if o.Type != 0 && !IsTypeSupportedSave(o.Type) { return nil, fmt.Errorf("VIPS cannot save to %#v", ImageTypes[o.Type]) } var ptr unsafe.Pointer @@ -520,24 +520,24 @@ func vipsImageType(buf []byte) ImageType { if buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF { return JPEG } - if IsImageTypeSupportedByVips(WEBP) && buf[8] == 0x57 && buf[9] == 0x45 && buf[10] == 0x42 && buf[11] == 0x50 { + if IsTypeSupported(WEBP) && buf[8] == 0x57 && buf[9] == 0x45 && buf[10] == 0x42 && buf[11] == 0x50 { return WEBP } - if IsImageTypeSupportedByVips(TIFF) && + if IsTypeSupported(TIFF) && ((buf[0] == 0x49 && buf[1] == 0x49 && buf[2] == 0x2A && buf[3] == 0x0) || (buf[0] == 0x4D && buf[1] == 0x4D && buf[2] == 0x0 && buf[3] == 0x2A)) { return TIFF } - if IsImageTypeSupportedByVips(GIF) && buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 { + if IsTypeSupported(GIF) && buf[0] == 0x47 && buf[1] == 0x49 && buf[2] == 0x46 { return GIF } - if IsImageTypeSupportedByVips(PDF) && buf[0] == 0x25 && buf[1] == 0x50 && buf[2] == 0x44 && buf[3] == 0x46 { + if IsTypeSupported(PDF) && buf[0] == 0x25 && buf[1] == 0x50 && buf[2] == 0x44 && buf[3] == 0x46 { return PDF } - if IsImageTypeSupportedByVips(SVG) && IsSVGImage(buf) { + if IsTypeSupported(SVG) && IsSVGImage(buf) { return SVG } - if IsImageTypeSupportedByVips(MAGICK) && strings.HasSuffix(readImageType(buf), "MagickBuffer") { + if IsTypeSupported(MAGICK) && strings.HasSuffix(readImageType(buf), "MagickBuffer") { return MAGICK } return UNKNOWN diff --git a/vips_test.go b/vips_test.go index bbbee9e..7001c32 100644 --- a/vips_test.go +++ b/vips_test.go @@ -46,7 +46,7 @@ func TestVipsSave(t *testing.T) { } func TestVipsSaveTiff(t *testing.T) { - if !VipsIsTypeSupportedSave(TIFF) { + if !IsTypeSupportedSave(TIFF) { t.Skipf("Format %#v is not supported", ImageTypes[TIFF]) } image, _, _ := vipsRead(readImage("test.jpg"))