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:
parent
bda7e1e53d
commit
a3d894a697
@ -5,7 +5,7 @@ import (
|
|||||||
"io"
|
"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
|
var tmp [16]byte
|
||||||
|
|
||||||
if _, err = io.ReadFull(r, tmp[:6]); err != nil {
|
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 {
|
if tmp[0] > width || tmp[1] > height || tmp[0] == 0 || tmp[1] == 0 {
|
||||||
width = tmp[0]
|
width = tmp[0]
|
||||||
height = tmp[1]
|
height = tmp[1]
|
||||||
page = i
|
size = binary.LittleEndian.Uint32(tmp[8:12])
|
||||||
|
offset = binary.LittleEndian.Uint32(tmp[12:16])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func BestIcoPage(r io.Reader) (int, error) {
|
func BestIcoPage(r io.Reader) (int, int, error) {
|
||||||
_, _, page, err := icoBestSize(r)
|
_, _, offset, size, err := icoBestSize(r)
|
||||||
return int(page), err
|
return int(offset), int(size), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeIcoMeta(r io.Reader) (*Meta, error) {
|
func DecodeIcoMeta(r io.Reader) (*Meta, error) {
|
||||||
bwidth, bheight, _, err := icoBestSize(r)
|
bwidth, bheight, _, _, err := icoBestSize(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
39
process.go
39
process.go
@ -1,10 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
|
imageSize "github.com/imgproxy/imgproxy/image_size"
|
||||||
"golang.org/x/sync/errgroup"
|
"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")
|
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 {
|
func imageTypeLoadSupport(imgtype imageType) bool {
|
||||||
return imgtype == imageTypeSVG || vipsTypeSupportLoad[imgtype]
|
return imgtype == imageTypeSVG ||
|
||||||
|
imgtype == imageTypeICO ||
|
||||||
|
vipsTypeSupportLoad[imgtype]
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageTypeSaveSupport(imgtype imageType) bool {
|
func imageTypeSaveSupport(imgtype imageType) bool {
|
||||||
@ -541,6 +546,29 @@ func transformAnimated(ctx context.Context, img *vipsImage, data []byte, po *pro
|
|||||||
return nil
|
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) {
|
func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
defer runtime.UnlockOSThread()
|
defer runtime.UnlockOSThread()
|
||||||
@ -584,6 +612,15 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
|
|||||||
return []byte{}, func() {}, errSourceImageTypeNotSupported
|
return []byte{}, func() {}, errSourceImageTypeNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if imgdata.Type == imageTypeICO {
|
||||||
|
icodata, err := getIcoData(imgdata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, func() {}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
imgdata = icodata
|
||||||
|
}
|
||||||
|
|
||||||
if !vipsSupportSmartcrop {
|
if !vipsSupportSmartcrop {
|
||||||
if po.Gravity.Type == gravitySmart {
|
if po.Gravity.Type == gravitySmart {
|
||||||
logWarning(msgSmartCropNotSupported)
|
logWarning(msgSmartCropNotSupported)
|
||||||
|
12
vips.c
12
vips.c
@ -80,8 +80,6 @@ vips_type_find_load_go(int imgtype) {
|
|||||||
return vips_type_find("VipsOperation", "gifload_buffer");
|
return vips_type_find("VipsOperation", "gifload_buffer");
|
||||||
case (SVG):
|
case (SVG):
|
||||||
return vips_type_find("VipsOperation", "svgload_buffer");
|
return vips_type_find("VipsOperation", "svgload_buffer");
|
||||||
case (ICO):
|
|
||||||
return vips_type_find("VipsOperation", "magickload_buffer");
|
|
||||||
case (HEIC):
|
case (HEIC):
|
||||||
return vips_type_find("VipsOperation", "heifload_buffer");
|
return vips_type_find("VipsOperation", "heifload_buffer");
|
||||||
case (BMP):
|
case (BMP):
|
||||||
@ -167,16 +165,6 @@ vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out) {
|
|||||||
#endif
|
#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
|
int
|
||||||
vips_heifload_go(void *buf, size_t len, VipsImage **out) {
|
vips_heifload_go(void *buf, size_t len, VipsImage **out) {
|
||||||
#if VIPS_SUPPORT_HEIF
|
#if VIPS_SUPPORT_HEIF
|
||||||
|
10
vips.go
10
vips.go
@ -8,15 +8,12 @@ package main
|
|||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
imageSize "github.com/imgproxy/imgproxy/image_size"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type vipsImage struct {
|
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)
|
err = C.vips_gifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.int(pages), &tmp)
|
||||||
case imageTypeSVG:
|
case imageTypeSVG:
|
||||||
err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(scale), &tmp)
|
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:
|
case imageTypeHEIC:
|
||||||
err = C.vips_heifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &tmp)
|
err = C.vips_heifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), &tmp)
|
||||||
case imageTypeBMP:
|
case imageTypeBMP:
|
||||||
|
1
vips.h
1
vips.h
@ -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_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_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_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_heifload_go(void *buf, size_t len, VipsImage **out);
|
||||||
int vips_bmpload_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);
|
int vips_tiffload_go(void *buf, size_t len, VipsImage **out);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user