mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-03-22 20:21:28 +02:00
SVG sources support
This commit is contained in:
parent
280c64a55b
commit
5501c3cff7
@ -11,7 +11,7 @@ WORKDIR /go/src/github.com/DarthSim/imgproxy
|
||||
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
|
||||
&& apk --no-cache upgrade \
|
||||
&& apk add --no-cache curl ca-certificates go gcc g++ make musl-dev fftw-dev glib-dev expat-dev \
|
||||
libjpeg-turbo-dev libpng-dev libwebp-dev giflib-dev libexif-dev lcms2-dev
|
||||
libjpeg-turbo-dev libpng-dev libwebp-dev giflib-dev librsvg-dev libexif-dev lcms2-dev
|
||||
|
||||
# Build ImageMagick
|
||||
RUN cd /root \
|
||||
@ -77,7 +77,7 @@ LABEL maintainer="Sergey Alexandrovich <darthsim@gmail.com>"
|
||||
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
|
||||
&& apk --no-cache upgrade \
|
||||
&& apk add --no-cache bash ca-certificates fftw glib expat libjpeg-turbo libpng \
|
||||
libwebp giflib libexif lcms2 \
|
||||
libwebp giflib librsvg libgsf libexif lcms2 \
|
||||
&& rm -rf /var/cache/apk*
|
||||
|
||||
COPY --from=0 /usr/local/bin/imgproxy /usr/local/bin/
|
||||
|
@ -6,7 +6,8 @@ At the moment, imgproxy supports only the most popular Web image formats:
|
||||
* JPEG;
|
||||
* WebP;
|
||||
* GIF;
|
||||
* ICO.
|
||||
* ICO;
|
||||
* SVG _(source only)_.
|
||||
|
||||
## GIF support
|
||||
|
||||
|
@ -4,5 +4,6 @@ enum types {
|
||||
PNG,
|
||||
WEBP,
|
||||
GIF,
|
||||
ICO
|
||||
ICO,
|
||||
SVG
|
||||
};
|
||||
|
48
process.go
48
process.go
@ -73,6 +73,9 @@ func initVips() {
|
||||
if int(C.vips_type_find_load_go(C.int(imageTypeGIF))) != 0 {
|
||||
vipsTypeSupportLoad[imageTypeGIF] = true
|
||||
}
|
||||
if int(C.vips_type_find_load_go(C.int(imageTypeSVG))) != 0 {
|
||||
vipsTypeSupportLoad[imageTypeSVG] = true
|
||||
}
|
||||
|
||||
// we load ICO with github.com/mat/besticon/ico and send decoded data to vips
|
||||
vipsTypeSupportLoad[imageTypeICO] = true
|
||||
@ -140,7 +143,7 @@ func extractMeta(img *C.VipsImage) (int, int, int, bool) {
|
||||
return width, height, angle, flip
|
||||
}
|
||||
|
||||
func calcScale(width, height int, po *processingOptions) float64 {
|
||||
func calcScale(width, height int, po *processingOptions, imgtype imageType) float64 {
|
||||
// If we're going only to crop, we need only to scale down to DPR.
|
||||
// Scaling up while cropping is not optimal on this stage, we'll do it later if needed.
|
||||
if po.Resize == resizeCrop {
|
||||
@ -173,7 +176,7 @@ func calcScale(width, height int, po *processingOptions) float64 {
|
||||
|
||||
scale = scale * po.Dpr
|
||||
|
||||
if !po.Enlarge && scale > 1 {
|
||||
if !po.Enlarge && scale > 1 && imgtype != imageTypeSVG {
|
||||
return 1
|
||||
}
|
||||
|
||||
@ -274,22 +277,31 @@ func transformImage(ctx context.Context, img **C.struct__VipsImage, data []byte,
|
||||
|
||||
hasAlpha := vipsImageHasAlpha(*img)
|
||||
|
||||
if scale := calcScale(imgWidth, imgHeight, po); scale != 1 {
|
||||
// Do some shrink-on-load
|
||||
if scale < 1.0 && data != nil {
|
||||
if shrink := calcShink(scale, imgtype); shrink != 1 {
|
||||
scale = scale * float64(shrink)
|
||||
if scale := calcScale(imgWidth, imgHeight, po, imgtype); scale != 1 {
|
||||
if imgtype == imageTypeSVG && data != nil {
|
||||
// Load SVG with desired scale
|
||||
if tmp, err := vipsLoadImage(data, imgtype, 1, scale, false); err == nil {
|
||||
C.swap_and_clear(img, tmp)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Do some shrink-on-load
|
||||
if scale < 1.0 && data != nil {
|
||||
if shrink := calcShink(scale, imgtype); shrink != 1 {
|
||||
scale = scale * float64(shrink)
|
||||
|
||||
if tmp, err := vipsLoadImage(data, imgtype, shrink, false); err == nil {
|
||||
C.swap_and_clear(img, tmp)
|
||||
} else {
|
||||
return err
|
||||
if tmp, err := vipsLoadImage(data, imgtype, shrink, 1.0, false); err == nil {
|
||||
C.swap_and_clear(img, tmp)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = resizeImage(img, scale, hasAlpha); err != nil {
|
||||
return err
|
||||
if err = resizeImage(img, scale, hasAlpha); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update actual image size after resize
|
||||
@ -506,7 +518,7 @@ func processImage(ctx context.Context) ([]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
img, err := vipsLoadImage(data, imgtype, 1, po.Format == imageTypeGIF)
|
||||
img, err := vipsLoadImage(data, imgtype, 1, 1.0, po.Format == imageTypeGIF)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -546,7 +558,7 @@ func vipsPrepareWatermark() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
watermark, err = vipsLoadImage(data, imgtype, 1, false)
|
||||
watermark, err = vipsLoadImage(data, imgtype, 1, 1.0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -593,7 +605,7 @@ func vipsPrepareWatermark() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func vipsLoadImage(data []byte, imgtype imageType, shrink int, allPages bool) (*C.struct__VipsImage, error) {
|
||||
func vipsLoadImage(data []byte, imgtype imageType, shrink int, svgScale float64, allPages bool) (*C.struct__VipsImage, error) {
|
||||
var img *C.struct__VipsImage
|
||||
|
||||
err := C.int(0)
|
||||
@ -612,6 +624,8 @@ func vipsLoadImage(data []byte, imgtype imageType, shrink int, allPages bool) (*
|
||||
err = C.vips_webpload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.int(shrink), &img)
|
||||
case imageTypeGIF:
|
||||
err = C.vips_gifload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), pages, &img)
|
||||
case imageTypeSVG:
|
||||
err = C.vips_svgload_go(unsafe.Pointer(&data[0]), C.size_t(len(data)), C.double(svgScale), &img)
|
||||
case imageTypeICO:
|
||||
rawData, width, height, icoErr := icoData(data)
|
||||
if icoErr != nil {
|
||||
|
@ -29,6 +29,7 @@ const (
|
||||
imageTypeWEBP = imageType(C.WEBP)
|
||||
imageTypeGIF = imageType(C.GIF)
|
||||
imageTypeICO = imageType(C.ICO)
|
||||
imageTypeSVG = imageType(C.SVG)
|
||||
)
|
||||
|
||||
type processingHeaders struct {
|
||||
@ -45,6 +46,7 @@ var imageTypes = map[string]imageType{
|
||||
"webp": imageTypeWEBP,
|
||||
"gif": imageTypeGIF,
|
||||
"ico": imageTypeICO,
|
||||
"svg": imageTypeSVG,
|
||||
}
|
||||
|
||||
type gravityType int
|
||||
|
22
svg.go
Normal file
22
svg.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
goColor "image/color"
|
||||
"io"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register fake svg decoder. Since we need this only for type detecting, we can
|
||||
// return fake image sizes
|
||||
image.RegisterFormat(
|
||||
"svg",
|
||||
"<?xml ",
|
||||
func(io.Reader) (image.Image, error) {
|
||||
return image.NewRGBA(image.Rect(0, 0, 1, 1)), nil
|
||||
},
|
||||
func(io.Reader) (image.Config, error) {
|
||||
return image.Config{ColorModel: goColor.RGBAModel, Width: 1, Height: 1}, nil
|
||||
},
|
||||
)
|
||||
}
|
16
vips.h
16
vips.h
@ -12,6 +12,9 @@
|
||||
#define VIPS_SUPPORT_GIF \
|
||||
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 3))
|
||||
|
||||
#define VIPS_SUPPORT_SVG \
|
||||
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 3))
|
||||
|
||||
#define VIPS_SUPPORT_MAGICK \
|
||||
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
|
||||
|
||||
@ -52,6 +55,9 @@ vips_type_find_load_go(int imgtype) {
|
||||
if (imgtype == GIF) {
|
||||
return vips_type_find("VipsOperation", "gifload_buffer");
|
||||
}
|
||||
if (imgtype == SVG) {
|
||||
return vips_type_find("VipsOperation", "svgload_buffer");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -106,6 +112,16 @@ vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out) {
|
||||
#if VIPS_SUPPORT_SVG
|
||||
return vips_svgload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "scale", scale, NULL);
|
||||
#else
|
||||
vips_error("vips_svgload_go", "Loading SVG is not supported");
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
vips_get_exif_orientation(VipsImage *image) {
|
||||
const char *orientation;
|
||||
|
Loading…
x
Reference in New Issue
Block a user