1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-07 11:36:25 +02:00

Load ICO without imagemagick

This commit is contained in:
DarthSim 2019-10-03 21:43:33 +06:00
parent bda7e1e53d
commit a3d894a697
5 changed files with 45 additions and 30 deletions

View File

@ -5,7 +5,7 @@ import (
"io"
)
func icoBestSize(r io.Reader) (width, height byte, page uint16, err error) {
func icoBestSize(r io.Reader) (width, height byte, offset uint32, size uint32, err error) {
var tmp [16]byte
if _, err = io.ReadFull(r, tmp[:6]); err != nil {
@ -22,20 +22,21 @@ func icoBestSize(r io.Reader) (width, height byte, page uint16, err error) {
if tmp[0] > width || tmp[1] > height || tmp[0] == 0 || tmp[1] == 0 {
width = tmp[0]
height = tmp[1]
page = i
size = binary.LittleEndian.Uint32(tmp[8:12])
offset = binary.LittleEndian.Uint32(tmp[12:16])
}
}
return
}
func BestIcoPage(r io.Reader) (int, error) {
_, _, page, err := icoBestSize(r)
return int(page), err
func BestIcoPage(r io.Reader) (int, int, error) {
_, _, offset, size, err := icoBestSize(r)
return int(offset), int(size), err
}
func DecodeIcoMeta(r io.Reader) (*Meta, error) {
bwidth, bheight, _, err := icoBestSize(r)
bwidth, bheight, _, _, err := icoBestSize(r)
if err != nil {
return nil, err
}

View File

@ -1,10 +1,13 @@
package main
import (
"bytes"
"context"
"fmt"
"math"
"runtime"
imageSize "github.com/imgproxy/imgproxy/image_size"
"golang.org/x/sync/errgroup"
)
@ -13,7 +16,9 @@ const msgSmartCropNotSupported = "Smart crop is not supported by used version of
var errConvertingNonSvgToSvg = newError(422, "Converting non-SVG images to SVG is not supported", "Converting non-SVG images to SVG is not supported")
func imageTypeLoadSupport(imgtype imageType) bool {
return imgtype == imageTypeSVG || vipsTypeSupportLoad[imgtype]
return imgtype == imageTypeSVG ||
imgtype == imageTypeICO ||
vipsTypeSupportLoad[imgtype]
}
func imageTypeSaveSupport(imgtype imageType) bool {
@ -541,6 +546,29 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
return nil
}
func getIcoData(imgdata *imageData) (*imageData, error) {
offset, size, err := imageSize.BestIcoPage(bytes.NewBuffer(imgdata.Data))
if err != nil {
return nil, err
}
data := imgdata.Data[offset : offset+size]
meta, err := imageSize.DecodeMeta(bytes.NewBuffer(data))
if err != nil {
return nil, err
}
if imgtype, ok := imageTypes[meta.Format]; ok && vipsTypeSupportLoad[imgtype] {
return &imageData{
Data: data,
Type: imgtype,
}, nil
}
return nil, fmt.Errorf("Can't load %s from ICO", meta.Format)
}
func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
@ -584,6 +612,15 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
return []byte{}, func() {}, errSourceImageTypeNotSupported
}
if imgdata.Type == imageTypeICO {
icodata, err := getIcoData(imgdata)
if err != nil {
return nil, func() {}, err
}
imgdata = icodata
}
if !vipsSupportSmartcrop {
if po.Gravity.Type == gravitySmart {
logWarning(msgSmartCropNotSupported)

12
vips.c
View File

@ -80,8 +80,6 @@ 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 (BMP):
@ -167,16 +165,6 @@ 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

10
vips.go
View File

@ -8,15 +8,12 @@ package main
*/
import "C"
import (
"bytes"
"context"
"math"
"os"
"runtime"
"time"
"unsafe"
imageSize "github.com/imgproxy/imgproxy/image_size"
)
type vipsImage struct {
@ -157,13 +154,6 @@ func (img *vipsImage) Load(data []byte, imgtype imageType, shrink int, scale flo
err = C.vips_gifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.int(pages), &tmp)
case imageTypeSVG:
err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(scale), &tmp)
case imageTypeICO:
bestPage, ierr := imageSize.BestIcoPage(bytes.NewBuffer(data))
if ierr != nil {
logWarning(ierr.Error())
}
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 imageTypeBMP:

1
vips.h
View File

@ -32,7 +32,6 @@ 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_bmpload_go(void *buf, size_t len, VipsImage **out);
int vips_tiffload_go(void *buf, size_t len, VipsImage **out);