Jelajahi Sumber

Return ICC hack & fix segfault on ICC check

DarthSim 3 tahun lalu
induk
melakukan
7770fcebc2
4 mengubah file dengan 42 tambahan dan 12 penghapusan
  1. 3 0
      CHANGELOG.md
  2. 31 0
      vips.c
  3. 7 12
      vips.go
  4. 1 0
      vips.h

+ 3 - 0
CHANGELOG.md

@@ -1,6 +1,9 @@
 # Changelog
 # Changelog
 
 
 ## [Unreleased]
 ## [Unreleased]
+### Fix
+- Fix performance regression in ICC profile handling.
+- Fix crashes while processing CMYK images without ICC profile.
 
 
 ## [2.16.5] - 2021-06-28
 ## [2.16.5] - 2021-06-28
 ### Change
 ### Change

+ 31 - 0
vips.c

@@ -355,6 +355,37 @@ vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale) {
   return 0;
   return 0;
 }
 }
 
 
+int
+vips_icc_is_srgb_iec61966(VipsImage *in) {
+  VIPS_BLOB_DATA_TYPE data;
+  size_t data_len;
+
+  // 1998-12-01
+  static char date[] = { 7, 206, 0, 2, 0, 9 };
+  // 2.1
+  static char version[] = { 2, 16, 0, 0 };
+
+  // The image had no profile and built-in CMYK was imported.
+  // Vips gives us an invalid data pointer when the built-in profile was imported,
+  // so we check this mark before receiving an actual profile.
+  // if (vips_image_get_typeof(in, "icc-cmyk-no-profile"))
+  //   return FALSE;
+
+  if (vips_image_get_blob(in, VIPS_META_ICC_NAME, &data, &data_len))
+    return FALSE;
+
+  // Less than header size
+  if (data_len < 128)
+    return FALSE;
+
+  // Predict it is sRGB IEC61966 2.1 by checking some header fields
+  return ((memcmp(data + 48, "IEC ",  4) == 0) && // Device manufacturer
+          (memcmp(data + 52, "sRGB",  4) == 0) && // Device model
+          (memcmp(data + 80, "HP  ",  4) == 0) && // Profile creator
+          (memcmp(data + 24, date,    6) == 0) && // Date of creation
+          (memcmp(data + 8,  version, 4) == 0));  // Version
+}
+
 int
 int
 vips_has_embedded_icc(VipsImage *in) {
 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;

+ 7 - 12
vips.go

@@ -558,12 +558,7 @@ func (img *vipsImage) ImportColourProfile() error {
 	}
 	}
 
 
 	if C.vips_has_embedded_icc(img.VipsImage) == 0 {
 	if C.vips_has_embedded_icc(img.VipsImage) == 0 {
-		// No embedded profile
-		if img.VipsImage.Type != C.VIPS_INTERPRETATION_CMYK {
-			// vips doesn't have built-in profile for other interpretations,
-			// so we can't do anything here
-			return nil
-		}
+		return nil
 	}
 	}
 
 
 	if C.vips_icc_import_go(img.VipsImage, &tmp) == 0 {
 	if C.vips_icc_import_go(img.VipsImage, &tmp) == 0 {
@@ -578,8 +573,8 @@ func (img *vipsImage) ImportColourProfile() error {
 func (img *vipsImage) ExportColourProfile() error {
 func (img *vipsImage) ExportColourProfile() error {
 	var tmp *C.VipsImage
 	var tmp *C.VipsImage
 
 
-	// Don't export is there's no embedded profile
-	if C.vips_has_embedded_icc(img.VipsImage) == 0 {
+	// Don't export is there's no embedded profile or embedded profile is sRGB
+	if C.vips_has_embedded_icc(img.VipsImage) == 0 || C.vips_icc_is_srgb_iec61966(img.VipsImage) == 1 {
 		return nil
 		return nil
 	}
 	}
 
 
@@ -595,8 +590,8 @@ func (img *vipsImage) ExportColourProfile() error {
 func (img *vipsImage) ExportColourProfileToSRGB() error {
 func (img *vipsImage) ExportColourProfileToSRGB() error {
 	var tmp *C.VipsImage
 	var tmp *C.VipsImage
 
 
-	// Don't export is there's no embedded profile
-	if C.vips_has_embedded_icc(img.VipsImage) == 0 {
+	// Don't export is there's no embedded profile or embedded profile is sRGB
+	if C.vips_has_embedded_icc(img.VipsImage) == 0 || C.vips_icc_is_srgb_iec61966(img.VipsImage) == 1 {
 		return nil
 		return nil
 	}
 	}
 
 
@@ -612,8 +607,8 @@ func (img *vipsImage) ExportColourProfileToSRGB() error {
 func (img *vipsImage) TransformColourProfile() error {
 func (img *vipsImage) TransformColourProfile() error {
 	var tmp *C.VipsImage
 	var tmp *C.VipsImage
 
 
-	// Don't transform is there's no embedded profile
-	if C.vips_has_embedded_icc(img.VipsImage) == 0 {
+	// Don't transform is there's no embedded profile or embedded profile is sRGB
+	if C.vips_has_embedded_icc(img.VipsImage) == 0 || C.vips_icc_is_srgb_iec61966(img.VipsImage) == 1 {
 		return nil
 		return nil
 	}
 	}
 
 

+ 1 - 0
vips.h

@@ -61,6 +61,7 @@ int vips_rad2float_go(VipsImage *in, VipsImage **out);
 int vips_resize_go(VipsImage *in, VipsImage **out, double scale);
 int vips_resize_go(VipsImage *in, VipsImage **out, double scale);
 int vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale);
 int vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale);
 
 
+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_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);