Adding support for heif (i.e. heic files).

master
Jeremy Gordon 6 years ago committed by Paul van Santen
parent 5a9d7f21d9
commit f9eadf55bb
No known key found for this signature in database
GPG Key ID: AD10F40CB69516B6

BIN
testdata/test.heic vendored

Binary file not shown.

@ -25,6 +25,8 @@ const (
SVG SVG
// MAGICK represents the libmagick compatible genetic image type. // MAGICK represents the libmagick compatible genetic image type.
MAGICK MAGICK
// HEIF represents the HEIC/HEIF/HVEC image type
HEIF
) )
// ImageType represents an image type value. // ImageType represents an image type value.
@ -45,6 +47,7 @@ var ImageTypes = map[ImageType]string{
PDF: "pdf", PDF: "pdf",
SVG: "svg", SVG: "svg",
MAGICK: "magick", MAGICK: "magick",
HEIF: "heif",
} }
// imageMutex is used to provide thread-safe synchronization // imageMutex is used to provide thread-safe synchronization

@ -19,6 +19,7 @@ func TestDeterminateImageType(t *testing.T) {
{"test.pdf", PDF}, {"test.pdf", PDF},
{"test.svg", SVG}, {"test.svg", SVG},
{"test.jp2", MAGICK}, {"test.jp2", MAGICK},
{"test.heic", HEIF},
} }
for _, file := range files { for _, file := range files {
@ -46,6 +47,7 @@ func TestDeterminateImageTypeName(t *testing.T) {
{"test.pdf", "pdf"}, {"test.pdf", "pdf"},
{"test.svg", "svg"}, {"test.svg", "svg"},
{"test.jp2", "magick"}, {"test.jp2", "magick"},
{"test.heic", "heif"},
} }
for _, file := range files { for _, file := range files {
@ -63,7 +65,7 @@ func TestIsTypeSupported(t *testing.T) {
types := []struct { types := []struct {
name ImageType name ImageType
}{ }{
{JPEG}, {PNG}, {WEBP}, {GIF}, {PDF}, {JPEG}, {PNG}, {WEBP}, {GIF}, {PDF}, {HEIF},
} }
for _, n := range types { for _, n := range types {
@ -83,6 +85,7 @@ func TestIsTypeNameSupported(t *testing.T) {
{"webp", true}, {"webp", true},
{"gif", true}, {"gif", true},
{"pdf", true}, {"pdf", true},
{"heif", true},
} }
for _, n := range types { for _, n := range types {
@ -101,6 +104,9 @@ func TestIsTypeSupportedSave(t *testing.T) {
if VipsVersion >= "8.5.0" { if VipsVersion >= "8.5.0" {
types = append(types, struct{ name ImageType }{TIFF}) types = append(types, struct{ name ImageType }{TIFF})
} }
if VipsVersion >= "8.8.0" {
types = append(types, struct{ name ImageType }{HEIF})
}
for _, n := range types { for _, n := range types {
if IsTypeSupportedSave(n.name) == false { if IsTypeSupportedSave(n.name) == false {
@ -120,6 +126,7 @@ func TestIsTypeNameSupportedSave(t *testing.T) {
{"gif", false}, {"gif", false},
{"pdf", false}, {"pdf", false},
{"tiff", VipsVersion >= "8.5.0"}, {"tiff", VipsVersion >= "8.5.0"},
{"heif", VipsVersion >= "8.8.0"},
} }
for _, n := range types { for _, n := range types {

@ -1,4 +1,4 @@
package bimg package bimg
// Version represents the current package semantic version. // Version represents the current package semantic version.
const Version = "1.0.18" const Version = "1.0.19"

@ -185,6 +185,9 @@ func VipsIsTypeSupported(t ImageType) bool {
if t == MAGICK { if t == MAGICK {
return int(C.vips_type_find_bridge(C.MAGICK)) != 0 return int(C.vips_type_find_bridge(C.MAGICK)) != 0
} }
if t == HEIF {
return int(C.vips_type_find_bridge(C.HEIF)) != 0
}
return false return false
} }
@ -204,6 +207,9 @@ func VipsIsTypeSupportedSave(t ImageType) bool {
if t == TIFF { if t == TIFF {
return int(C.vips_type_find_save_bridge(C.TIFF)) != 0 return int(C.vips_type_find_save_bridge(C.TIFF)) != 0
} }
if t == HEIF {
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
}
return false return false
} }
@ -431,6 +437,8 @@ func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) {
saveErr = C.vips_pngsave_bridge(tmpImage, &ptr, &length, strip, C.int(o.Compression), quality, interlace) saveErr = C.vips_pngsave_bridge(tmpImage, &ptr, &length, strip, C.int(o.Compression), quality, interlace)
case TIFF: case TIFF:
saveErr = C.vips_tiffsave_bridge(tmpImage, &ptr, &length) saveErr = C.vips_tiffsave_bridge(tmpImage, &ptr, &length)
case HEIF:
saveErr = C.vips_heifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless)
default: default:
saveErr = C.vips_jpegsave_bridge(tmpImage, &ptr, &length, strip, quality, interlace) saveErr = C.vips_jpegsave_bridge(tmpImage, &ptr, &length, strip, quality, interlace)
} }
@ -634,6 +642,12 @@ func vipsImageType(buf []byte) ImageType {
if IsTypeSupported(MAGICK) && strings.HasSuffix(readImageType(buf), "MagickBuffer") { if IsTypeSupported(MAGICK) && strings.HasSuffix(readImageType(buf), "MagickBuffer") {
return MAGICK return MAGICK
} }
// NOTE: libheif current;y only supports heic sub types; see:
// https://github.com/strukturag/libheif/issues/83#issuecomment-421427091
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
buf[8] == 0x68 && buf[9] == 0x65 && buf[10] == 0x69 && buf[11] == 0x63 {
return HEIF
}
return UNKNOWN return UNKNOWN
} }

@ -32,7 +32,10 @@ enum types {
GIF, GIF,
PDF, PDF,
SVG, SVG,
MAGICK MAGICK,
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
HEIF,
#endif
}; };
typedef struct { typedef struct {
@ -156,6 +159,11 @@ vips_type_find_bridge(int t) {
if (t == MAGICK) { if (t == MAGICK) {
return vips_type_find("VipsOperation", "magickload"); return vips_type_find("VipsOperation", "magickload");
} }
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
if (t == HEIF) {
return vips_type_find("VipsOperation", "heifload");
}
#endif
return 0; return 0;
} }
@ -173,6 +181,11 @@ vips_type_find_save_bridge(int t) {
if (t == JPEG) { if (t == JPEG) {
return vips_type_find("VipsOperation", "jpegsave_buffer"); return vips_type_find("VipsOperation", "jpegsave_buffer");
} }
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
if (t == HEIF) {
return vips_type_find("VipsOperation", "heifsave_buffer");
}
#endif
return 0; return 0;
} }
@ -324,6 +337,20 @@ vips_tiffsave_bridge(VipsImage *in, void **buf, size_t *len) {
#endif #endif
} }
int
vips_heifsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int quality, int lossless) {
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
return vips_heifsave_buffer(in, buf, len,
"strip", INT_TO_GBOOLEAN(strip),
"Q", quality,
"lossless", INT_TO_GBOOLEAN(lossless),
NULL
);
#else
return 0;
#endif
}
int int
vips_is_16bit (VipsInterpretation interpretation) { vips_is_16bit (VipsInterpretation interpretation) {
return interpretation == VIPS_INTERPRETATION_RGB16 || interpretation == VIPS_INTERPRETATION_GREY16; return interpretation == VIPS_INTERPRETATION_RGB16 || interpretation == VIPS_INTERPRETATION_GREY16;
@ -370,6 +397,10 @@ vips_init_image (void *buf, size_t len, int imageType, VipsImage **out) {
#endif #endif
} else if (imageType == MAGICK) { } else if (imageType == MAGICK) {
code = vips_magickload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL); code = vips_magickload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL);
#endif
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
} else if (imageType == HEIF) {
code = vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL);
#endif #endif
} }

Loading…
Cancel
Save