Don't assume that ImageMagick uses a 16-bit quantum.
[bpt/emacs.git] / src / image.c
index bfbdfbc..f7c3ef5 100644 (file)
@@ -21,13 +21,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "sysstdio.h"
 #include <unistd.h>
 
-#ifdef HAVE_PNG
-#if defined HAVE_LIBPNG_PNG_H
-# include <libpng/png.h>
-#else
+/* Include this before including <setjmp.h> to work around bugs with
+   older libpng; see Bug#17429.  */
+#if defined HAVE_PNG && !defined HAVE_NS
 # include <png.h>
 #endif
-#endif
 
 #include <setjmp.h>
 #include <c-ctype.h>
@@ -1233,6 +1231,18 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
   return img->background_transparent;
 }
 
+/* Store F's background color into *BGCOLOR.  */
+static void
+x_query_frame_background_color (struct frame *f, XColor *bgcolor)
+{
+#ifndef HAVE_NS
+  bgcolor->pixel = FRAME_BACKGROUND_PIXEL (f);
+  x_query_color (f, bgcolor);
+#else
+  ns_query_color (FRAME_BACKGROUND_COLOR (f), bgcolor, 1);
+#endif
+}
+
 \f
 /***********************************************************************
                  Helper functions for X image types
@@ -5506,7 +5516,7 @@ png_image_p (Lisp_Object object)
 #endif /* HAVE_PNG || HAVE_NS */
 
 
-#ifdef HAVE_PNG
+#if defined HAVE_PNG && !defined HAVE_NS
 
 #ifdef WINDOWSNT
 /* PNG library details.  */
@@ -5884,43 +5894,23 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       /* png_color_16 *image_bg; */
       Lisp_Object specified_bg
        = image_spec_value (img->spec, QCbackground, NULL);
-      int shift = (bit_depth == 16) ? 0 : 8;
+      XColor color;
 
-      if (STRINGP (specified_bg))
+      /* If the user specified a color, try to use it; if not, use the
+        current frame background, ignoring any default background
+        color set by the image.  */
+      if (STRINGP (specified_bg)
+         ? x_defined_color (f, SSDATA (specified_bg), &color, false)
+         : (x_query_frame_background_color (f, &color), true))
        /* The user specified `:background', use that.  */
        {
-         XColor color;
-         if (x_defined_color (f, SSDATA (specified_bg), &color, 0))
-           {
-             png_color_16 user_bg;
-
-             memset (&user_bg, 0, sizeof user_bg);
-             user_bg.red = color.red >> shift;
-             user_bg.green = color.green >> shift;
-             user_bg.blue = color.blue >> shift;
-
-             fn_png_set_background (png_ptr, &user_bg,
-                                    PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
-           }
-       }
-      else
-       {
-         /* We use the current frame background, ignoring any default
-            background color set by the image.  */
-#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
-         XColor color;
-         png_color_16 frame_background;
+         int shift = bit_depth == 16 ? 0 : 8;
+         png_color_16 bg = { 0 };
+         bg.red = color.red >> shift;
+         bg.green = color.green >> shift;
+         bg.blue = color.blue >> shift;
 
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
-         x_query_color (f, &color);
-
-         memset (&frame_background, 0, sizeof frame_background);
-         frame_background.red = color.red >> shift;
-         frame_background.green = color.green >> shift;
-         frame_background.blue = color.blue >> shift;
-#endif /* HAVE_X_WINDOWS */
-
-         fn_png_set_background (png_ptr, &frame_background,
+         fn_png_set_background (png_ptr, &bg,
                                 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }
     }
@@ -6062,9 +6052,8 @@ png_load (struct frame *f, struct image *img)
   return png_load_body (f, img, &c);
 }
 
-#else /* HAVE_PNG */
+#elif defined HAVE_NS
 
-#ifdef HAVE_NS
 static bool
 png_load (struct frame *f, struct image *img)
 {
@@ -6072,10 +6061,8 @@ png_load (struct frame *f, struct image *img)
                         image_spec_value (img->spec, QCfile, NULL),
                         image_spec_value (img->spec, QCdata, NULL));
 }
-#endif  /* HAVE_NS */
 
-
-#endif /* !HAVE_PNG */
+#endif /* HAVE_NS */
 
 
 \f
@@ -6262,9 +6249,6 @@ struct my_jpeg_error_mgr
       MY_JPEG_INVALID_IMAGE_SIZE,
       MY_JPEG_CANNOT_CREATE_X
     } failure_code;
-#ifdef lint
-  FILE *fp;
-#endif
 };
 
 
@@ -6479,7 +6463,8 @@ jpeg_load_body (struct frame *f, struct image *img,
 {
   Lisp_Object file, specified_file;
   Lisp_Object specified_data;
-  FILE *fp = NULL;
+  /* The 'volatile' silences a bogus diagnostic; see GCC bug 54561.  */
+  FILE * IF_LINT (volatile) fp = NULL;
   JSAMPARRAY buffer;
   int row_stride, x, y;
   XImagePtr ximg = NULL;
@@ -6512,8 +6497,6 @@ jpeg_load_body (struct frame *f, struct image *img,
       return 0;
     }
 
-  IF_LINT (mgr->fp = fp);
-
   /* Customize libjpeg's error handling to call my_error_exit when an
      error is detected.  This function will perform a longjmp.  */
   mgr->cinfo.err = fn_jpeg_std_error (&mgr->pub);
@@ -6552,9 +6535,6 @@ jpeg_load_body (struct frame *f, struct image *img,
       return 0;
     }
 
-  /* Silence a bogus diagnostic; see GCC bug 54561.  */
-  IF_LINT (fp = mgr->fp);
-
   /* Create the JPEG decompression object.  Let it read from fp.
         Read the JPEG image header.  */
   fn_jpeg_CreateDecompress (&mgr->cinfo, JPEG_LIB_VERSION, sizeof *&mgr->cinfo);
@@ -8236,14 +8216,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
     specified_bg = image_spec_value (img->spec, QCbackground, NULL);
     if (!STRINGP (specified_bg)
        || !x_defined_color (f, SSDATA (specified_bg), &bgcolor, 0))
-      {
-#ifndef HAVE_NS
-       bgcolor.pixel = FRAME_BACKGROUND_PIXEL (f);
-       x_query_color (f, &bgcolor);
-#else
-       ns_query_color (FRAME_BACKGROUND_COLOR (f), &bgcolor, 1);
-#endif
-      }
+      x_query_frame_background_color (f, &bgcolor);
 
     bg_wand = NewPixelWand ();
     PixelSetRed   (bg_wand, (double) bgcolor.red   / 65535);
@@ -8395,6 +8368,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 #endif /* HAVE_MAGICKEXPORTIMAGEPIXELS */
     {
       size_t image_height;
+      double color_scale = 65535.0 / QuantumRange;
 
       /* Try to create a x pixmap to hold the imagemagick pixmap.  */
       if (!image_create_x_image_and_pixmap (f, img, width, height, 0,
@@ -8435,9 +8409,9 @@ imagemagick_load_image (struct frame *f, struct image *img,
               PixelGetMagickColor (pixels[x], &pixel);
               XPutPixel (ximg, x, y,
                          lookup_rgb_color (f,
-                                           pixel.red,
-                                           pixel.green,
-                                           pixel.blue));
+                                          color_scale * pixel.red,
+                                          color_scale * pixel.green,
+                                          color_scale * pixel.blue));
             }
         }
       DestroyPixelIterator (iterator);
@@ -8879,14 +8853,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   specified_bg = image_spec_value (img->spec, QCbackground, NULL);
   if (!STRINGP (specified_bg)
       || !x_defined_color (f, SSDATA (specified_bg), &background, 0))
-    {
-#ifndef HAVE_NS
-      background.pixel = FRAME_BACKGROUND_PIXEL (f);
-      x_query_color (f, &background);
-#else
-      ns_query_color (FRAME_BACKGROUND_COLOR (f), &background, 1);
-#endif
-    }
+    x_query_frame_background_color (f, &background);
 
   /* SVG pixmaps specify transparency in the last byte, so right
      shift 8 bits to get rid of it, since emacs doesn't support