You've already forked imgproxy
mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-11-27 22:48:53 +02:00
Fix handling ICC profiles with vips 8.15+
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
- Set `Error` status for errorred traces in OpenTelemetry.
|
- Set `Error` status for errorred traces in OpenTelemetry.
|
||||||
- Fix URL parsing error when a non-http(s) URL contains a `%` symbol outside of the percent-encoded sequence.
|
- Fix URL parsing error when a non-http(s) URL contains a `%` symbol outside of the percent-encoded sequence.
|
||||||
- Fix importing ICC profiles for 16-bit images with an alpha channel.
|
- Fix importing ICC profiles for 16-bit images with an alpha channel.
|
||||||
|
- Fix handling ICC profiles with vips 8.15+.
|
||||||
- (pro) Fix opject detection accuracy when using YOLOv8 or YOLOv10 models.
|
- (pro) Fix opject detection accuracy when using YOLOv8 or YOLOv10 models.
|
||||||
- (pro) Fix usage of the `obj` and `objw` gravity types inside the `crop` processing option.
|
- (pro) Fix usage of the `obj` and `objw` gravity types inside the `crop` processing option.
|
||||||
- (pro) Fix detecting of width and height when orientation is specified in EXIF but EXIF info is not requested.
|
- (pro) Fix detecting of width and height when orientation is specified in EXIF but EXIF info is not requested.
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ func exportColorProfile(pctx *pipelineContext, img *vips.Image, po *options.Proc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vips 8.15+ tends to lose the colour profile during some color conversions.
|
||||||
|
// We probably have a backup of the colour profile, so we need to restore it.
|
||||||
|
img.RestoreColourProfile()
|
||||||
|
|
||||||
if img.ColourProfileImported() {
|
if img.ColourProfileImported() {
|
||||||
if keepProfile {
|
if keepProfile {
|
||||||
// We imported ICC profile and want to keep it,
|
// We imported ICC profile and want to keep it,
|
||||||
|
|||||||
@@ -22,11 +22,17 @@ func importColorProfile(pctx *pipelineContext, img *vips.Image, po *options.Proc
|
|||||||
// The image is linear. If we keep its ICC, we'll get wrong colors after
|
// The image is linear. If we keep its ICC, we'll get wrong colors after
|
||||||
// converting it to sRGB
|
// converting it to sRGB
|
||||||
img.RemoveColourProfile()
|
img.RemoveColourProfile()
|
||||||
} else if convertToLinear || !img.IsRGB() {
|
} else {
|
||||||
|
// vips 8.15+ tends to lose the colour profile during some color conversions.
|
||||||
|
// We need to backup the colour profile before the conversion and restore it later.
|
||||||
|
img.BackupColourProfile()
|
||||||
|
|
||||||
|
if convertToLinear || !img.IsRGB() {
|
||||||
if err := img.ImportColourProfile(); err != nil {
|
if err := img.ImportColourProfile(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if convertToLinear {
|
if convertToLinear {
|
||||||
return img.LinearColourspace()
|
return img.LinearColourspace()
|
||||||
|
|||||||
52
vips/vips.c
52
vips/vips.c
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#define VIPS_META_PALETTE_BITS_DEPTH "palette-bit-depth"
|
#define VIPS_META_PALETTE_BITS_DEPTH "palette-bit-depth"
|
||||||
|
|
||||||
|
#define IMGPROXY_META_ICC_NAME "imgproxy-icc-profile"
|
||||||
|
|
||||||
int
|
int
|
||||||
vips_initialize()
|
vips_initialize()
|
||||||
{
|
{
|
||||||
@@ -430,6 +432,55 @@ vips_has_embedded_icc(VipsImage *in)
|
|||||||
return vips_image_get_typeof(in, VIPS_META_ICC_NAME) != 0;
|
return vips_image_get_typeof(in, VIPS_META_ICC_NAME) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips_icc_backup(VipsImage *in, VipsImage **out)
|
||||||
|
{
|
||||||
|
if (vips_copy(in, out, NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!vips_image_get_typeof(in, VIPS_META_ICC_NAME))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const void *data = NULL;
|
||||||
|
size_t data_len = 0;
|
||||||
|
|
||||||
|
if (vips_image_get_blob(in, VIPS_META_ICC_NAME, &data, &data_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data || data_len < 128)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vips_image_remove(*out, IMGPROXY_META_ICC_NAME);
|
||||||
|
vips_image_set_blob_copy(*out, IMGPROXY_META_ICC_NAME, data, data_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips_icc_restore(VipsImage *in, VipsImage **out)
|
||||||
|
{
|
||||||
|
if (vips_copy(in, out, NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (vips_image_get_typeof(in, VIPS_META_ICC_NAME) ||
|
||||||
|
!vips_image_get_typeof(in, IMGPROXY_META_ICC_NAME))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const void *data = NULL;
|
||||||
|
size_t data_len = 0;
|
||||||
|
|
||||||
|
if (vips_image_get_blob(in, IMGPROXY_META_ICC_NAME, &data, &data_len))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!data || data_len < 128)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vips_image_remove(*out, VIPS_META_ICC_NAME);
|
||||||
|
vips_image_set_blob_copy(*out, VIPS_META_ICC_NAME, data, data_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
vips_icc_import_go(VipsImage *in, VipsImage **out)
|
vips_icc_import_go(VipsImage *in, VipsImage **out)
|
||||||
{
|
{
|
||||||
@@ -506,6 +557,7 @@ vips_icc_remove(VipsImage *in, VipsImage **out)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
vips_image_remove(*out, VIPS_META_ICC_NAME);
|
vips_image_remove(*out, VIPS_META_ICC_NAME);
|
||||||
|
vips_image_remove(*out, IMGPROXY_META_ICC_NAME);
|
||||||
vips_image_remove(*out, "exif-ifd0-WhitePoint");
|
vips_image_remove(*out, "exif-ifd0-WhitePoint");
|
||||||
vips_image_remove(*out, "exif-ifd0-PrimaryChromaticities");
|
vips_image_remove(*out, "exif-ifd0-PrimaryChromaticities");
|
||||||
vips_image_remove(*out, "exif-ifd2-ColorSpace");
|
vips_image_remove(*out, "exif-ifd2-ColorSpace");
|
||||||
|
|||||||
20
vips/vips.go
20
vips/vips.go
@@ -736,6 +736,26 @@ func (img *Image) IsLinear() bool {
|
|||||||
return C.vips_image_guess_interpretation(img.VipsImage) == C.VIPS_INTERPRETATION_scRGB
|
return C.vips_image_guess_interpretation(img.VipsImage) == C.VIPS_INTERPRETATION_scRGB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (img *Image) BackupColourProfile() {
|
||||||
|
var tmp *C.VipsImage
|
||||||
|
|
||||||
|
if C.vips_icc_backup(img.VipsImage, &tmp) == 0 {
|
||||||
|
C.swap_and_clear(&img.VipsImage, tmp)
|
||||||
|
} else {
|
||||||
|
log.Warningf("Can't backup ICC profile: %s", Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (img *Image) RestoreColourProfile() {
|
||||||
|
var tmp *C.VipsImage
|
||||||
|
|
||||||
|
if C.vips_icc_restore(img.VipsImage, &tmp) == 0 {
|
||||||
|
C.swap_and_clear(&img.VipsImage, tmp)
|
||||||
|
} else {
|
||||||
|
log.Warningf("Can't restore ICC profile: %s", Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (img *Image) ImportColourProfile() error {
|
func (img *Image) ImportColourProfile() error {
|
||||||
var tmp *C.VipsImage
|
var tmp *C.VipsImage
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ int vips_resize_go(VipsImage *in, VipsImage **out, double wscale, double hscale)
|
|||||||
|
|
||||||
int vips_icc_is_srgb_iec61966(VipsImage *in);
|
int vips_icc_is_srgb_iec61966(VipsImage *in);
|
||||||
int vips_has_embedded_icc(VipsImage *in);
|
int vips_has_embedded_icc(VipsImage *in);
|
||||||
|
int vips_icc_backup(VipsImage *in, VipsImage **out);
|
||||||
|
int vips_icc_restore(VipsImage *in, VipsImage **out);
|
||||||
int vips_icc_import_go(VipsImage *in, VipsImage **out);
|
int vips_icc_import_go(VipsImage *in, VipsImage **out);
|
||||||
int vips_icc_export_go(VipsImage *in, VipsImage **out);
|
int vips_icc_export_go(VipsImage *in, VipsImage **out);
|
||||||
int vips_icc_export_srgb(VipsImage *in, VipsImage **out);
|
int vips_icc_export_srgb(VipsImage *in, VipsImage **out);
|
||||||
|
|||||||
Reference in New Issue
Block a user