mirror of
https://github.com/talgo-cloud/bimg.git
synced 2026-03-17 11:16:34 -07:00
Merge pull request #356 from LarsFronius/avif-support
Adds AVIF support
This commit is contained in:
commit
152a6b1506
13 changed files with 111 additions and 12 deletions
|
|
@ -11,7 +11,8 @@ env:
|
||||||
# - LIBVIPS=8.7.4
|
# - LIBVIPS=8.7.4
|
||||||
# - LIBVIPS=8.8.4
|
# - LIBVIPS=8.8.4
|
||||||
# - LIBVIPS=8.9.2
|
# - LIBVIPS=8.9.2
|
||||||
- LIBVIPS=8.10.0
|
- LIBVIPS=8.10.1
|
||||||
|
- LIBVIPS=8.10.2
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
|
@ -26,7 +27,7 @@ install:
|
||||||
- docker build -t h2non/bimg:ci --build-arg LIBVIPS_VERSION=$LIBVIPS .
|
- docker build -t h2non/bimg:ci --build-arg LIBVIPS_VERSION=$LIBVIPS .
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- docker run h2non/bimg:ci sh -c 'export LD_LIBRARY_PATH=/vips/lib:$LD_LIBRARY_PATH; export PKG_CONFIG_PATH=/vips/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig; go vet . && golint . && go test -v -race -covermode=atomic -coverprofile=coverage.out'
|
- docker run h2non/bimg:ci sh -c 'export LD_LIBRARY_PATH=/vips/lib:/usr/local/lib:$LD_LIBRARY_PATH; export PKG_CONFIG_PATH=/vips/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/X11/lib/pkgconfig; go vet . && golint . && go test -v -race -covermode=atomic -coverprofile=coverage.out'
|
||||||
|
|
||||||
# after_success:
|
# after_success:
|
||||||
# - goveralls -coverprofile=coverage.out -service=travis-ci
|
# - goveralls -coverprofile=coverage.out -service=travis-ci
|
||||||
|
|
|
||||||
16
Dockerfile
16
Dockerfile
|
|
@ -2,6 +2,7 @@ FROM golang:1.14
|
||||||
LABEL maintainer "tomas@aparicio.me"
|
LABEL maintainer "tomas@aparicio.me"
|
||||||
|
|
||||||
ARG LIBVIPS_VERSION=8.9.2
|
ARG LIBVIPS_VERSION=8.9.2
|
||||||
|
ARG LIBHEIF_VERSION=1.9.1
|
||||||
ARG GOLANGCILINT_VERSION=1.29.0
|
ARG GOLANGCILINT_VERSION=1.29.0
|
||||||
|
|
||||||
# Installs libvips + required libraries
|
# Installs libvips + required libraries
|
||||||
|
|
@ -13,7 +14,18 @@ RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
gobject-introspection gtk-doc-tools libglib2.0-dev libjpeg62-turbo-dev libpng-dev \
|
gobject-introspection gtk-doc-tools libglib2.0-dev libjpeg62-turbo-dev libpng-dev \
|
||||||
libwebp-dev libtiff5-dev libgif-dev libexif-dev libxml2-dev libpoppler-glib-dev \
|
libwebp-dev libtiff5-dev libgif-dev libexif-dev libxml2-dev libpoppler-glib-dev \
|
||||||
swig libmagickwand-dev libpango1.0-dev libmatio-dev libopenslide-dev libcfitsio-dev \
|
swig libmagickwand-dev libpango1.0-dev libmatio-dev libopenslide-dev libcfitsio-dev \
|
||||||
libgsf-1-dev fftw3-dev liborc-0.4-dev librsvg2-dev libimagequant-dev libheif-dev && \
|
libgsf-1-dev fftw3-dev liborc-0.4-dev librsvg2-dev libimagequant-dev libaom-dev && \
|
||||||
|
cd /tmp && \
|
||||||
|
curl -fsSLO https://github.com/strukturag/libheif/releases/download/v${LIBHEIF_VERSION}/libheif-${LIBHEIF_VERSION}.tar.gz && \
|
||||||
|
tar zvxf libheif-${LIBHEIF_VERSION}.tar.gz && \
|
||||||
|
cd /tmp/libheif-${LIBHEIF_VERSION} && \
|
||||||
|
./configure --prefix=/vips && \
|
||||||
|
make && \
|
||||||
|
make install && \
|
||||||
|
echo '/vips/lib' > /etc/ld.so.conf.d/vips.conf && \
|
||||||
|
ldconfig -v && \
|
||||||
|
export LD_LIBRARY_PATH="/vips/lib:$LD_LIBRARY_PATH" && \
|
||||||
|
export PKG_CONFIG_PATH="/vips/lib/pkgconfig:$PKG_CONFIG_PATH" && \
|
||||||
cd /tmp && \
|
cd /tmp && \
|
||||||
curl -fsSLO https://github.com/libvips/libvips/releases/download/v${LIBVIPS_VERSION}/vips-${LIBVIPS_VERSION}.tar.gz && \
|
curl -fsSLO https://github.com/libvips/libvips/releases/download/v${LIBVIPS_VERSION}/vips-${LIBVIPS_VERSION}.tar.gz && \
|
||||||
tar zvxf vips-${LIBVIPS_VERSION}.tar.gz && \
|
tar zvxf vips-${LIBVIPS_VERSION}.tar.gz && \
|
||||||
|
|
@ -32,6 +44,8 @@ RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
make install && \
|
make install && \
|
||||||
ldconfig
|
ldconfig
|
||||||
|
|
||||||
|
ENV LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
|
||||||
|
|
||||||
# Install runtime dependencies
|
# Install runtime dependencies
|
||||||
# RUN DEBIAN_FRONTEND=noninteractive \
|
# RUN DEBIAN_FRONTEND=noninteractive \
|
||||||
# apt-get update && \
|
# apt-get update && \
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Small [Go](http://golang.org) package for fast high-level image processing using [libvips](https://github.com/jcupitt/libvips) via C bindings, providing a simple [programmatic API](#examples).
|
Small [Go](http://golang.org) package for fast high-level image processing using [libvips](https://github.com/jcupitt/libvips) via C bindings, providing a simple [programmatic API](#examples).
|
||||||
|
|
||||||
bimg was designed to be a small and efficient library supporting common [image operations](#supported-image-operations) such as crop, resize, rotate, zoom or watermark. It can read JPEG, PNG, WEBP natively, and optionally TIFF, PDF, GIF and SVG formats if `libvips@8.3+` is compiled with proper library bindings.
|
bimg was designed to be a small and efficient library supporting common [image operations](#supported-image-operations) such as crop, resize, rotate, zoom or watermark. It can read JPEG, PNG, WEBP natively, and optionally TIFF, PDF, GIF and SVG formats if `libvips@8.3+` is compiled with proper library bindings. Lastly AVIF is supported as of `libvips@8.9+`. For AVIF support `libheif` needs to be [compiled with an applicable AVIF en-/decoder](https://github.com/strukturag/libheif#compiling).
|
||||||
|
|
||||||
bimg is able to output images as JPEG, PNG and WEBP formats, including transparent conversion across them.
|
bimg is able to output images as JPEG, PNG and WEBP formats, including transparent conversion across them.
|
||||||
|
|
||||||
|
|
@ -53,7 +53,9 @@ If you're using `gopkg.in`, you can still rely in the `v0` without worrying abou
|
||||||
- C compatible compiler such as gcc 4.6+ or clang 3.0+
|
- C compatible compiler such as gcc 4.6+ or clang 3.0+
|
||||||
- Go 1.3+
|
- Go 1.3+
|
||||||
|
|
||||||
**Note**: `libvips` v8.3+ is required for GIF, PDF and SVG support.
|
**Note**:
|
||||||
|
* `libvips` v8.3+ is required for GIF, PDF and SVG support.
|
||||||
|
* `libvips` v8.9+ is required for AVIF support. `libheif` compiled with a AVIF en-/decoder also needs to be present.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -352,8 +352,8 @@ func TestImageAutoRotate(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
file string
|
file string
|
||||||
orientation int
|
orientation int
|
||||||
}{
|
}{
|
||||||
{"exif/Landscape_1.jpg", 1},
|
{"exif/Landscape_1.jpg", 1},
|
||||||
{"exif/Landscape_2.jpg", 1},
|
{"exif/Landscape_2.jpg", 1},
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ func TestMetadata(t *testing.T) {
|
||||||
{"test_icc_prophoto.jpg", "jpeg", 0, false, true, "srgb"},
|
{"test_icc_prophoto.jpg", "jpeg", 0, false, true, "srgb"},
|
||||||
{"test.png", "png", 0, true, false, "srgb"},
|
{"test.png", "png", 0, true, false, "srgb"},
|
||||||
{"test.webp", "webp", 0, false, false, "srgb"},
|
{"test.webp", "webp", 0, false, false, "srgb"},
|
||||||
|
{"test.avif", "avif", 0, false, false, "srgb"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,8 @@ type Options struct {
|
||||||
OutputICC string
|
OutputICC string
|
||||||
InputICC string
|
InputICC string
|
||||||
Palette bool
|
Palette bool
|
||||||
|
// Speed defines the AVIF encoders CPU effort. Valid values are 0-8.
|
||||||
|
Speed int
|
||||||
|
|
||||||
// private fields
|
// private fields
|
||||||
autoRotateOnly bool
|
autoRotateOnly bool
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func resizer(buf []byte, o Options) ([]byte, error) {
|
||||||
o = applyDefaults(o, imageType)
|
o = applyDefaults(o, imageType)
|
||||||
|
|
||||||
// Ensure supported type
|
// Ensure supported type
|
||||||
if !IsTypeSupported(o.Type) {
|
if !IsTypeSupportedSave(o.Type) {
|
||||||
return nil, errors.New("Unsupported image output type")
|
return nil, errors.New("Unsupported image output type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ func resizer(buf []byte, o Options) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If JPEG or HEIF image, retrieve the buffer
|
// If JPEG or HEIF image, retrieve the buffer
|
||||||
if rotated && (imageType == JPEG || imageType == HEIF) && !o.NoAutoRotate {
|
if rotated && (imageType == JPEG || imageType == HEIF || imageType == AVIF) && !o.NoAutoRotate {
|
||||||
buf, err = getImageBuffer(image)
|
buf, err = getImageBuffer(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -187,6 +187,7 @@ func saveImage(image *C.VipsImage, o Options) ([]byte, error) {
|
||||||
StripMetadata: o.StripMetadata,
|
StripMetadata: o.StripMetadata,
|
||||||
Lossless: o.Lossless,
|
Lossless: o.Lossless,
|
||||||
Palette: o.Palette,
|
Palette: o.Palette,
|
||||||
|
Speed: o.Speed,
|
||||||
}
|
}
|
||||||
// Finally get the resultant buffer
|
// Finally get the resultant buffer
|
||||||
return vipsSave(image, saveOptions)
|
return vipsSave(image, saveOptions)
|
||||||
|
|
|
||||||
BIN
testdata/test.avif
vendored
Normal file
BIN
testdata/test.avif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 253 KiB |
3
type.go
3
type.go
|
|
@ -30,6 +30,8 @@ const (
|
||||||
MAGICK
|
MAGICK
|
||||||
// HEIF represents the HEIC/HEIF/HVEC image type
|
// HEIF represents the HEIC/HEIF/HVEC image type
|
||||||
HEIF
|
HEIF
|
||||||
|
// AVIF represents the AVIF image type.
|
||||||
|
AVIF
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -48,6 +50,7 @@ var ImageTypes = map[ImageType]string{
|
||||||
SVG: "svg",
|
SVG: "svg",
|
||||||
MAGICK: "magick",
|
MAGICK: "magick",
|
||||||
HEIF: "heif",
|
HEIF: "heif",
|
||||||
|
AVIF: "avif",
|
||||||
}
|
}
|
||||||
|
|
||||||
// imageMutex is used to provide thread-safe synchronization
|
// imageMutex is used to provide thread-safe synchronization
|
||||||
|
|
|
||||||
18
type_test.go
18
type_test.go
|
|
@ -22,6 +22,7 @@ func TestDeterminateImageType(t *testing.T) {
|
||||||
{"test.heic", HEIF},
|
{"test.heic", HEIF},
|
||||||
{"test2.heic", HEIF},
|
{"test2.heic", HEIF},
|
||||||
{"test3.heic", HEIF},
|
{"test3.heic", HEIF},
|
||||||
|
{"test.avif", AVIF},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
|
|
@ -51,12 +52,16 @@ func TestDeterminateImageTypeName(t *testing.T) {
|
||||||
{"test.svg", "svg"},
|
{"test.svg", "svg"},
|
||||||
// {"test.jp2", "magick"},
|
// {"test.jp2", "magick"},
|
||||||
{"test.heic", "heif"},
|
{"test.heic", "heif"},
|
||||||
|
{"test.avif", "avif"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if file.expected == "heif" && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
if file.expected == "heif" && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if file.expected == "avif" && VipsMajorVersion <= 8 && VipsMinorVersion < 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
img, _ := os.Open(path.Join("testdata", file.name))
|
img, _ := os.Open(path.Join("testdata", file.name))
|
||||||
buf, _ := ioutil.ReadAll(img)
|
buf, _ := ioutil.ReadAll(img)
|
||||||
|
|
@ -73,13 +78,16 @@ func TestIsTypeSupported(t *testing.T) {
|
||||||
types := []struct {
|
types := []struct {
|
||||||
name ImageType
|
name ImageType
|
||||||
}{
|
}{
|
||||||
{JPEG}, {PNG}, {WEBP}, {GIF}, {PDF}, {HEIF},
|
{JPEG}, {PNG}, {WEBP}, {GIF}, {PDF}, {HEIF}, {AVIF},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range types {
|
for _, n := range types {
|
||||||
if n.name == HEIF && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
if n.name == HEIF && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if n.name == AVIF && VipsMajorVersion <= 8 && VipsMinorVersion < 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if IsTypeSupported(n.name) == false {
|
if IsTypeSupported(n.name) == false {
|
||||||
t.Fatalf("Image type %s is not valid", ImageTypes[n.name])
|
t.Fatalf("Image type %s is not valid", ImageTypes[n.name])
|
||||||
}
|
}
|
||||||
|
|
@ -97,12 +105,16 @@ func TestIsTypeNameSupported(t *testing.T) {
|
||||||
{"gif", true},
|
{"gif", true},
|
||||||
{"pdf", true},
|
{"pdf", true},
|
||||||
{"heif", true},
|
{"heif", true},
|
||||||
|
{"avif", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range types {
|
for _, n := range types {
|
||||||
if n.name == "heif" && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
if n.name == "heif" && VipsMajorVersion <= 8 && VipsMinorVersion < 8 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if n.name == "avif" && VipsMajorVersion <= 8 && VipsMinorVersion < 9 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if IsTypeNameSupported(n.name) != n.expected {
|
if IsTypeNameSupported(n.name) != n.expected {
|
||||||
t.Fatalf("Image type %s is not valid", n.name)
|
t.Fatalf("Image type %s is not valid", n.name)
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +133,9 @@ func TestIsTypeSupportedSave(t *testing.T) {
|
||||||
if VipsVersion >= "8.8.0" {
|
if VipsVersion >= "8.8.0" {
|
||||||
types = append(types, struct{ name ImageType }{HEIF})
|
types = append(types, struct{ name ImageType }{HEIF})
|
||||||
}
|
}
|
||||||
|
if VipsVersion >= "8.9.0" {
|
||||||
|
types = append(types, struct{ name ImageType }{AVIF})
|
||||||
|
}
|
||||||
|
|
||||||
for _, n := range types {
|
for _, n := range types {
|
||||||
if IsTypeSupportedSave(n.name) == false {
|
if IsTypeSupportedSave(n.name) == false {
|
||||||
|
|
@ -141,6 +156,7 @@ func TestIsTypeNameSupportedSave(t *testing.T) {
|
||||||
{"pdf", false},
|
{"pdf", false},
|
||||||
{"tiff", VipsVersion >= "8.5.0"},
|
{"tiff", VipsVersion >= "8.5.0"},
|
||||||
{"heif", VipsVersion >= "8.8.0"},
|
{"heif", VipsVersion >= "8.8.0"},
|
||||||
|
{"avif", VipsVersion >= "8.9.0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range types {
|
for _, n := range types {
|
||||||
|
|
|
||||||
14
vips.go
14
vips.go
|
|
@ -45,6 +45,7 @@ type VipsMemoryInfo struct {
|
||||||
|
|
||||||
// vipsSaveOptions represents the internal option used to talk with libvips.
|
// vipsSaveOptions represents the internal option used to talk with libvips.
|
||||||
type vipsSaveOptions struct {
|
type vipsSaveOptions struct {
|
||||||
|
Speed int
|
||||||
Quality int
|
Quality int
|
||||||
Compression int
|
Compression int
|
||||||
Type ImageType
|
Type ImageType
|
||||||
|
|
@ -190,6 +191,9 @@ func VipsIsTypeSupported(t ImageType) bool {
|
||||||
if t == HEIF {
|
if t == HEIF {
|
||||||
return int(C.vips_type_find_bridge(C.HEIF)) != 0
|
return int(C.vips_type_find_bridge(C.HEIF)) != 0
|
||||||
}
|
}
|
||||||
|
if t == AVIF {
|
||||||
|
return int(C.vips_type_find_bridge(C.HEIF)) != 0
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,6 +216,9 @@ func VipsIsTypeSupportedSave(t ImageType) bool {
|
||||||
if t == HEIF {
|
if t == HEIF {
|
||||||
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
|
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
|
||||||
}
|
}
|
||||||
|
if t == AVIF {
|
||||||
|
return int(C.vips_type_find_save_bridge(C.HEIF)) != 0
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,6 +494,7 @@ func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) {
|
||||||
strip := C.int(boolToInt(o.StripMetadata))
|
strip := C.int(boolToInt(o.StripMetadata))
|
||||||
lossless := C.int(boolToInt(o.Lossless))
|
lossless := C.int(boolToInt(o.Lossless))
|
||||||
palette := C.int(boolToInt(o.Palette))
|
palette := C.int(boolToInt(o.Palette))
|
||||||
|
speed := C.int(o.Speed)
|
||||||
|
|
||||||
if o.Type != 0 && !IsTypeSupportedSave(o.Type) {
|
if o.Type != 0 && !IsTypeSupportedSave(o.Type) {
|
||||||
return nil, fmt.Errorf("VIPS cannot save to %#v", ImageTypes[o.Type])
|
return nil, fmt.Errorf("VIPS cannot save to %#v", ImageTypes[o.Type])
|
||||||
|
|
@ -501,6 +509,8 @@ func vipsSave(image *C.VipsImage, o vipsSaveOptions) ([]byte, error) {
|
||||||
saveErr = C.vips_tiffsave_bridge(tmpImage, &ptr, &length)
|
saveErr = C.vips_tiffsave_bridge(tmpImage, &ptr, &length)
|
||||||
case HEIF:
|
case HEIF:
|
||||||
saveErr = C.vips_heifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless)
|
saveErr = C.vips_heifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless)
|
||||||
|
case AVIF:
|
||||||
|
saveErr = C.vips_avifsave_bridge(tmpImage, &ptr, &length, strip, quality, lossless, speed)
|
||||||
default:
|
default:
|
||||||
saveErr = C.vips_jpegsave_bridge(tmpImage, &ptr, &length, strip, quality, interlace)
|
saveErr = C.vips_jpegsave_bridge(tmpImage, &ptr, &length, strip, quality, interlace)
|
||||||
}
|
}
|
||||||
|
|
@ -735,6 +745,10 @@ func vipsImageType(buf []byte) ImageType {
|
||||||
// This is a HEIFS file, ftyphevc
|
// This is a HEIFS file, ftyphevc
|
||||||
return HEIF
|
return HEIF
|
||||||
}
|
}
|
||||||
|
if IsTypeSupported(HEIF) && buf[4] == 0x66 && buf[5] == 0x74 && buf[6] == 0x79 && buf[7] == 0x70 &&
|
||||||
|
buf[8] == 0x61 && buf[9] == 0x76 && buf[10] == 0x69 && buf[11] == 0x66 {
|
||||||
|
return AVIF
|
||||||
|
}
|
||||||
|
|
||||||
return UNKNOWN
|
return UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
vips.h
31
vips.h
|
|
@ -34,6 +34,7 @@ enum types {
|
||||||
SVG,
|
SVG,
|
||||||
MAGICK,
|
MAGICK,
|
||||||
HEIF,
|
HEIF,
|
||||||
|
AVIF
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -335,7 +336,7 @@ vips_pngsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int compr
|
||||||
"compression", compression,
|
"compression", compression,
|
||||||
"interlace", INT_TO_GBOOLEAN(interlace),
|
"interlace", INT_TO_GBOOLEAN(interlace),
|
||||||
"filter", VIPS_FOREIGN_PNG_FILTER_ALL,
|
"filter", VIPS_FOREIGN_PNG_FILTER_ALL,
|
||||||
"palette", INT_TO_GBOOLEAN(palette),
|
"palette", INT_TO_GBOOLEAN(palette),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
|
|
@ -367,6 +368,30 @@ vips_tiffsave_bridge(VipsImage *in, void **buf, size_t *len) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips_avifsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int quality, int lossless, int speed) {
|
||||||
|
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION > 10) || (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 10 && VIPS_MICRO_VERSION >= 2))
|
||||||
|
return vips_heifsave_buffer(in, buf, len,
|
||||||
|
"strip", INT_TO_GBOOLEAN(strip),
|
||||||
|
"Q", quality,
|
||||||
|
"lossless", INT_TO_GBOOLEAN(lossless),
|
||||||
|
"compression", VIPS_FOREIGN_HEIF_COMPRESSION_AV1,
|
||||||
|
"speed", speed,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
#elif (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 9))
|
||||||
|
return vips_heifsave_buffer(in, buf, len,
|
||||||
|
"strip", INT_TO_GBOOLEAN(strip),
|
||||||
|
"Q", quality,
|
||||||
|
"lossless", INT_TO_GBOOLEAN(lossless),
|
||||||
|
"compression", VIPS_FOREIGN_HEIF_COMPRESSION_AV1,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips_heifsave_bridge(VipsImage *in, void **buf, size_t *len, int strip, int quality, int lossless) {
|
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))
|
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
|
||||||
|
|
@ -431,6 +456,10 @@ vips_init_image (void *buf, size_t len, int imageType, VipsImage **out) {
|
||||||
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
|
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
|
||||||
} else if (imageType == HEIF) {
|
} else if (imageType == HEIF) {
|
||||||
code = vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL);
|
code = vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL);
|
||||||
|
#endif
|
||||||
|
#if (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 9)
|
||||||
|
} else if (imageType == AVIF) {
|
||||||
|
code = vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_RANDOM, NULL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
16
vips_test.go
16
vips_test.go
|
|
@ -58,6 +58,22 @@ func TestVipsSaveTiff(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVipsSaveAvif(t *testing.T) {
|
||||||
|
if !IsTypeSupportedSave(AVIF) {
|
||||||
|
t.Skipf("Format %#v is not supported", ImageTypes[AVIF])
|
||||||
|
}
|
||||||
|
image, _, _ := vipsRead(readImage("test.jpg"))
|
||||||
|
options := vipsSaveOptions{Quality: 95, Type: AVIF, Speed: 8}
|
||||||
|
buf, err := vipsSave(image, options)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error saving image type %v: %v", ImageTypes[AVIF], err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(buf) == 0 {
|
||||||
|
t.Fatalf("Empty saved '%v' image", ImageTypes[AVIF])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestVipsRotate(t *testing.T) {
|
func TestVipsRotate(t *testing.T) {
|
||||||
files := []struct {
|
files := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue