diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f1fcd5..e6367d32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ - TIFF and BMP support; - Using Application Default Credentials when `IMGPROXY_USE_GCS` is set to `true` but `IMGPROXY_GCS_KEY` is not set. **Note:** If you use `IMGPROXY_GCS_KEY`, it's recommended to set `IMGPROXY_USE_GCS` to `true` since it may be required by future versions to enable GCS support; -- Setting `IMGPROXY_REPORT_DOWNLOADING_ERRORS` to `false` disables reporting of downloading errors. +- Setting `IMGPROXY_REPORT_DOWNLOADING_ERRORS` to `false` disables reporting of downloading errors; +- SVG passthrough. When source image and requested format are SVG, image will be returned without changes. ## v2.5.0 diff --git a/download.go b/download.go index 5713cd13..134c63e6 100644 --- a/download.go +++ b/download.go @@ -111,7 +111,7 @@ func checkTypeAndDimensions(r io.Reader) (imageType, error) { } imgtype, imgtypeOk := imageTypes[meta.Format] - if !imgtypeOk || !vipsTypeSupportLoad[imgtype] { + if !imgtypeOk || !imageTypeLoadSupport(imgtype) { return imageTypeUnknown, errSourceImageTypeNotSupported } diff --git a/image_type.go b/image_type.go index 0dd2fde2..582c3ba1 100644 --- a/image_type.go +++ b/image_type.go @@ -50,6 +50,7 @@ var ( imageTypeWEBP: "image/webp", imageTypeGIF: "image/gif", imageTypeICO: "image/x-icon", + imageTypeSVG: "image/svg+xml", imageTypeHEIC: "image/heif", imageTypeBMP: "image/bmp", imageTypeTIFF: "image/tiff", @@ -61,6 +62,7 @@ var ( imageTypeWEBP: "inline; filename=\"%s.webp\"", imageTypeGIF: "inline; filename=\"%s.gif\"", imageTypeICO: "inline; filename=\"%s.ico\"", + imageTypeSVG: "inline; filename=\"%s.svg\"", imageTypeHEIC: "inline; filename=\"%s.heic\"", imageTypeBMP: "inline; filename=\"%s.bmp\"", imageTypeTIFF: "inline; filename=\"%s.tiff\"", diff --git a/process.go b/process.go index 01fa5dd9..c530674c 100644 --- a/process.go +++ b/process.go @@ -10,6 +10,16 @@ import ( const msgSmartCropNotSupported = "Smart crop is not supported by used version of libvips" +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] +} + +func imageTypeSaveSupport(imgtype imageType) bool { + return imgtype == imageTypeSVG || vipsTypeSupportSave[imgtype] +} + func extractMeta(img *vipsImage) (int, int, int, bool) { width := img.Width() height := img.Height() @@ -545,17 +555,25 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) { if po.Format == imageTypeUnknown { switch { - case po.PreferWebP && vipsTypeSupportSave[imageTypeWEBP]: + case po.PreferWebP && imageTypeSaveSupport(imageTypeWEBP): po.Format = imageTypeWEBP - case vipsTypeSupportSave[imgdata.Type] && imgdata.Type != imageTypeHEIC && imgdata.Type != imageTypeTIFF: + case imageTypeSaveSupport(imgdata.Type) && imgdata.Type != imageTypeHEIC && imgdata.Type != imageTypeTIFF: po.Format = imgdata.Type default: po.Format = imageTypeJPEG } - } else if po.EnforceWebP && vipsTypeSupportSave[imageTypeWEBP] { + } else if po.EnforceWebP && imageTypeSaveSupport(imageTypeWEBP) { po.Format = imageTypeWEBP } + if po.Format == imageTypeSVG { + if imgdata.Type != imageTypeSVG { + return []byte{}, func() {}, errConvertingNonSvgToSvg + } + + return imgdata.Data, func() {}, nil + } + if !vipsSupportSmartcrop { if po.Gravity.Type == gravitySmart { logWarning(msgSmartCropNotSupported) diff --git a/processing_options.go b/processing_options.go index 14ff4d3f..fdda22f3 100644 --- a/processing_options.go +++ b/processing_options.go @@ -641,7 +641,7 @@ func applyFormatOption(po *processingOptions, args []string) error { return fmt.Errorf("Invalid image format: %s", args[0]) } - if !vipsTypeSupportSave[po.Format] { + if !imageTypeSaveSupport(po.Format) { return fmt.Errorf("Resulting image format is not supported: %s", po.Format) }