[sane-devel] [PATCH 3/3] Avoid attaching grayscale ICC profiles to rgb images, or vice-versa.

Aaron Muir Hamilton aaron at correspondwith.me
Mon Apr 17 12:07:40 UTC 2017


  If the ICC profile added does not match the colour format of the
  image, libpng will abort. This can leave the scanner motors in an
  incorrect state and possibly cause permanent damage.
---
 frontend/scanimage.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/frontend/scanimage.c b/frontend/scanimage.c
index 0f71422c..74546763 100644
--- a/frontend/scanimage.c
+++ b/frontend/scanimage.c
@@ -1208,7 +1208,27 @@ write_png_header (SANE_Frame format, int width, int height, int depth, const cha
       icc_buffer = sanei_load_icc_profile(icc_profile, &icc_size);
       if (icc_size > 0)
         {
-	  png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
+	  /* libpng will abort if the profile and image colour spaces do not match*/
+	  /* The data colour space field is at bytes 16 to 20 in an ICC profile */
+	  /* see: ICC.1:2010 § 7.2.6 */
+	  int is_gray_profile = strncmp(icc_buffer + 16, "GRAY", 4) == 0;
+	  int is_rgb_profile = strncmp(icc_buffer + 16, "RGB ", 4) == 0;
+	  if ((is_gray_profile && color_type == PNG_COLOR_TYPE_GRAY) ||
+	      (is_rgb_profile && color_type == PNG_COLOR_TYPE_RGB))
+	    {
+	      png_set_iCCP(*png_ptr, *info_ptr, basename(icc_profile), PNG_COMPRESSION_TYPE_BASE, icc_buffer, icc_size);
+	    }
+	  else
+	    {
+	      if (is_gray_profile)
+	        {
+		  fprintf(stderr, "Ignoring 'GRAY' space ICC profile because the image is RGB.\n");
+	        }
+	      if (is_rgb_profile)
+	        {
+		  fprintf(stderr, "Ignoring 'RGB ' space ICC profile because the image is Grayscale.\n");
+		}
+	    }
 	  free(icc_buffer);
 	}
     }
-- 
2.12.2




More information about the sane-devel mailing list