1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-02 11:34:20 +02:00

Load ICO with vips_magickload

This commit is contained in:
DarthSim 2019-09-30 16:03:07 +06:00
parent 52152bcf47
commit 4d06d397fe
9 changed files with 58 additions and 50 deletions

View File

@ -47,7 +47,6 @@ RUN cd /root \
&& curl -Ls https://github.com/libvips/libvips/releases/download/v$VIPS_VERSION/vips-$VIPS_VERSION.tar.gz | tar -xz \
&& cd vips-$VIPS_VERSION \
&& ./configure \
--disable-magickload \
--without-python \
--without-tiff \
--without-OpenEXR \

View File

@ -17,7 +17,7 @@ imgproxy supports GIF output only when using libvips 8.7.0+ compiled with ImageM
## ICO support
imgproxy supports ICO output only when using libvips 8.7.0+ compiled with ImageMagick support. Official imgproxy Docker image supports ICO out of the box.
imgproxy supports ICO only when using libvips 8.7.0+ compiled with ImageMagick support. Official imgproxy Docker image supports ICO out of the box.
## HEIC support

1
go.mod
View File

@ -19,7 +19,6 @@ require (
github.com/honeybadger-io/honeybadger-go v0.4.0
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mat/besticon v3.9.0+incompatible
github.com/matoous/go-nanoid v0.0.0-20181114085210-eab626deece6
github.com/newrelic/go-agent v2.2.0+incompatible
github.com/pborman/uuid v0.0.0-20180906182336-adf5a7427709 // indirect

2
go.sum
View File

@ -68,8 +68,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mat/besticon v3.9.0+incompatible h1:SLaWKCE7ptsjWbQee8Sbx8F/WK4bw8b55tUV4mY0m/c=
github.com/mat/besticon v3.9.0+incompatible/go.mod h1:mA1auQYHt6CW5e7L9HJLmqVQC8SzNk2gVwouO0AbiEU=
github.com/matoous/go-nanoid v0.0.0-20181114085210-eab626deece6 h1:elv0VC5n2owefO3RvtKvS3i3/rw9LCrs0+tVFLbBlmQ=
github.com/matoous/go-nanoid v0.0.0-20181114085210-eab626deece6/go.mod h1:soqXi4beH2aAljcVvgIDqekDtnM2UZkGl47fniwq3J4=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=

View File

@ -1,28 +0,0 @@
package main
import (
"bytes"
"image"
"image/draw"
_ "github.com/mat/besticon/ico"
)
func icoData(data []byte) (out []byte, width int, height int, err error) {
var ico image.Image
ico, _, err = image.Decode(bytes.NewReader(data))
if err != nil {
return
}
// Ensure that image is in RGBA format
rgba := image.NewRGBA(ico.Bounds())
draw.Draw(rgba, ico.Bounds(), ico, image.Point{}, draw.Src)
width = rgba.Bounds().Dx()
height = rgba.Bounds().Dy()
out = rgba.Pix
return
}

View File

@ -5,32 +5,56 @@ import (
"io"
)
func DecodeIcoMeta(r io.Reader) (*Meta, error) {
func icoBestSize(r io.Reader) (width, height byte, page uint16, err error) {
var tmp [16]byte
if _, err := io.ReadFull(r, tmp[:6]); err != nil {
return nil, err
if _, err = io.ReadFull(r, tmp[:6]); err != nil {
return
}
count := binary.LittleEndian.Uint16(tmp[4:6])
width, height := byte(0), byte(0)
for i := uint16(0); i < count; i++ {
if _, err := io.ReadFull(r, tmp[:]); err != nil {
return nil, err
if _, err = io.ReadFull(r, tmp[:]); err != nil {
return
}
if tmp[0] > width || tmp[1] > height {
if tmp[0] > width || tmp[1] > height || tmp[0] == 0 || tmp[1] == 0 {
width = tmp[0]
height = tmp[1]
page = i
}
}
return
}
func BestIcoPage(r io.Reader) (int, error) {
_, _, page, err := icoBestSize(r)
return int(page), err
}
func DecodeIcoMeta(r io.Reader) (*Meta, error) {
bwidth, bheight, _, err := icoBestSize(r)
if err != nil {
return nil, err
}
width := int(bwidth)
height := int(bheight)
if width == 0 {
width = 256
}
if height == 0 {
height = 256
}
return &Meta{
Format: "ico",
Width: int(width),
Height: int(height),
Width: width,
Height: height,
}, nil
}

12
vips.c
View File

@ -80,6 +80,8 @@ vips_type_find_load_go(int imgtype) {
return vips_type_find("VipsOperation", "gifload_buffer");
case (SVG):
return vips_type_find("VipsOperation", "svgload_buffer");
case (ICO):
return vips_type_find("VipsOperation", "magickload_buffer");
case (HEIC):
return vips_type_find("VipsOperation", "heifload_buffer");
case (TIFF):
@ -161,6 +163,16 @@ vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out) {
#endif
}
int
vips_icoload_go(void *buf, size_t len, int page, VipsImage **out) {
#if VIPS_SUPPORT_MAGICK
return vips_magickload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "page", page, NULL);
#else
vips_error("vips_icoload_go", "Loading ICO is not supported (libvips 8.7+ reuired)");
return 1;
#endif
}
int
vips_heifload_go(void *buf, size_t len, VipsImage **out) {
#if VIPS_SUPPORT_HEIF

17
vips.go
View File

@ -8,12 +8,15 @@ package main
*/
import "C"
import (
"bytes"
"context"
"math"
"os"
"runtime"
"time"
"unsafe"
imageSize "github.com/imgproxy/imgproxy/image_size"
)
type vipsImage struct {
@ -88,6 +91,9 @@ func initVips() {
if int(C.vips_type_find_load_go(C.int(imageTypeSVG))) != 0 {
vipsTypeSupportLoad[imageTypeSVG] = true
}
if int(C.vips_type_find_load_go(C.int(imageTypeICO))) != 0 {
vipsTypeSupportLoad[imageTypeICO] = true
}
if int(C.vips_type_find_load_go(C.int(imageTypeHEIC))) != 0 {
vipsTypeSupportLoad[imageTypeHEIC] = true
}
@ -95,9 +101,6 @@ func initVips() {
vipsTypeSupportLoad[imageTypeTIFF] = true
}
// we load ICO with github.com/mat/besticon/ico and send decoded data to vips
vipsTypeSupportLoad[imageTypeICO] = true
if int(C.vips_type_find_save_go(C.int(imageTypeJPEG))) != 0 {
vipsTypeSupportSave[imageTypeJPEG] = true
}
@ -197,12 +200,12 @@ func (img *vipsImage) Load(data []byte, imgtype imageType, shrink int, scale flo
case imageTypeSVG:
err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(scale), &tmp)
case imageTypeICO:
rawData, width, height, icoErr := icoData(data)
if icoErr != nil {
return icoErr
bestPage, ierr := imageSize.BestIcoPage(bytes.NewBuffer(data))
if ierr != nil {
logWarning(ierr.Error())
}
tmp = C.vips_image_new_from_memory_copy(unsafe.Pointer(&rawData[0]), C.size_t(width*height*4), C.int(width), C.int(height), 4, C.VIPS_FORMAT_UCHAR)
err = C.vips_icoload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.int(bestPage), &tmp)
case imageTypeHEIC:
err = C.vips_heifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &tmp)
case imageTypeTIFF:

1
vips.h
View File

@ -31,6 +31,7 @@ int vips_pngload_go(void *buf, size_t len, VipsImage **out);
int vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out);
int vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out);
int vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out);
int vips_icoload_go(void *buf, size_t len, int page, VipsImage **out);
int vips_heifload_go(void *buf, size_t len, VipsImage **out);
int vips_tiffload_go(void *buf, size_t len, VipsImage **out);