]> git.eshelyaron.com Git - emacs.git/commitdiff
(XPutPixel): Handle monochrome images; used for masks.
authorJason Rumney <jasonr@gnu.org>
Sat, 25 Jan 2003 15:14:16 +0000 (15:14 +0000)
committerJason Rumney <jasonr@gnu.org>
Sat, 25 Jan 2003 15:14:16 +0000 (15:14 +0000)
[HAVE_PNG]: Sync with xfns.c version.
(png_load): Adjust colors for Windows. Use Windows
bitmaps. Disable color table lookups.

src/ChangeLog
src/w32fns.c

index b7c833928bad9551e59c1b7b55252d7d8df31add..bc02917930c3be72702836a6d409bb090dc6b280 100644 (file)
@@ -1,3 +1,10 @@
+2003-01-25  Jason Rumney  <jasonr@gnu.org>
+
+       * w32fns.c (XPutPixel): Handle monochrome images; used for masks.
+       [HAVE_PNG]: Sync with xfns.c version.
+       (png_load): Adjust colors for Windows. Use Windows
+       bitmaps. Disable color table lookups.
+
 2003-01-24  Andreas Schwab  <schwab@suse.de>
 
        * minibuf.c (Fminibuffer_message): Verify type of parameter.
index a1fa27cf742450f0e2a6b9c2f3eeba1e73c88fb1..1e54a07be72336b8d4c620a70f5b120e7b29b31a 100644 (file)
@@ -10812,24 +10812,40 @@ static void XPutPixel (ximg, x, y, color)
 {
   int width = ximg->info.bmiHeader.biWidth;
   int height = ximg->info.bmiHeader.biHeight;
-  int rowbytes = width * 3;
   unsigned char * pixel;
 
-  /* Don't support putting pixels in images with palettes.  */
-  xassert (ximg->info.bmiHeader.biBitCount == 24);
-
-  /* Ensure scanlines are aligned on 4 byte boundaries.  */
-  if (rowbytes % 4)
-    rowbytes += 4 - (rowbytes % 4);
-
-  pixel = ximg->data + y * rowbytes + x * 3;
-  /* Windows bitmaps are in BGR order.  */
-  *pixel = GetBValue (color);
-  *(pixel + 1) = GetGValue (color);
-  *(pixel + 2) = GetRValue (color);
+  /* True color images.  */
+  if (ximg->info.bmiHeader.biBitCount == 24)
+    {
+      int rowbytes = width * 3;
+      /* Ensure scanlines are aligned on 4 byte boundaries.  */
+      if (rowbytes % 4)
+       rowbytes += 4 - (rowbytes % 4);
+
+      pixel = ximg->data + y * rowbytes + x * 3;
+      /* Windows bitmaps are in BGR order.  */
+      *pixel = GetBValue (color);
+      *(pixel + 1) = GetGValue (color);
+      *(pixel + 2) = GetRValue (color);
+    }
+  /* Monochrome images.  */
+  else if (ximg->info.bmiHeader.biBitCount == 1)
+    {
+      int rowbytes = width / 8;
+      /* Ensure scanlines are aligned on 4 byte boundaries.  */
+      if (rowbytes % 4)
+       rowbytes += 4 - (rowbytes % 4);
+      pixel = ximg->data + y * rowbytes + x / 8;
+      /* Filter out palette info.  */
+      if (color & 0x00ffffff)
+       *pixel = *pixel | (1 << x % 8);
+      else
+       *pixel = *pixel & ~(1 << x % 8);
+    }
+  else
+    image_error ("XPutPixel: palette image not supported.", NULL, Qnil);
 }
 
-
 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
    RGB members are set.  F is the frame on which this all happens.
    COLORS will be freed; an existing IMG->pixmap will be freed, too.  */
@@ -11165,7 +11181,7 @@ x_build_heuristic_mask (f, img, how)
   image_background_transparent (img, f, img_dc);
 
   /* Put mask_img into img->mask.  */
-  x_destroy_x_image (mask_img);
+  x_destroy_x_image ((XImage *)mask_img);
   SelectObject (img_dc, prev);
   DeleteDC (img_dc);
 
@@ -11618,7 +11634,7 @@ png_image_p (object)
 {
   struct image_keyword fmt[PNG_LAST];
   bcopy (png_format, fmt, sizeof fmt);
-
+  
   if (!parse_image_spec (object, fmt, PNG_LAST, Qpng))
     return 0;
 
@@ -11675,7 +11691,7 @@ png_read_from_memory (png_ptr, data, length)
 
   if (length > tbr->len - tbr->index)
     png_error (png_ptr, "Read error");
-
+  
   bcopy (tbr->bytes + tbr->index, data, length);
   tbr->index = tbr->index + length;
 }
@@ -11697,14 +11713,13 @@ png_load (f, img)
   png_info *info_ptr = NULL, *end_info = NULL;
   FILE *volatile fp = NULL;
   png_byte sig[8];
-  png_byte *volatile pixels = NULL;
-  png_byte **volatile rows = NULL;
+  png_byte * volatile pixels = NULL;
+  png_byte ** volatile rows = NULL;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   png_byte channels;
   png_uint_32 row_bytes;
   int transparent_p;
-  char *gamma_str;
   double screen_gamma, image_gamma;
   int intent;
   struct png_memory_storage tbr;  /* Data to be read */
@@ -11719,31 +11734,31 @@ png_load (f, img)
     {
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
-        {
-          image_error ("Cannot find image file `%s'", specified_file, Qnil);
-          UNGCPRO;
-          return 0;
-        }
+       {
+         image_error ("Cannot find image file `%s'", specified_file, Qnil);
+         UNGCPRO;
+         return 0;
+       }
 
       /* Open the image file.  */
       fp = fopen (SDATA (file), "rb");
       if (!fp)
-        {
-          image_error ("Cannot open image file `%s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+       {
+         image_error ("Cannot open image file `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-          || !png_check_sig (sig, sizeof sig))
-        {
-          image_error ("Not a PNG file:` %s'", file, Qnil);
-          UNGCPRO;
-          fclose (fp);
-          return 0;
-        }
+         || !png_check_sig (sig, sizeof sig))
+       {
+         image_error ("Not a PNG file: `%s'", file, Qnil);
+         UNGCPRO;
+         fclose (fp);
+         return 0;
+       }
     }
   else
     {
@@ -11818,14 +11833,14 @@ png_load (f, img)
   png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                &interlace_type, NULL, NULL);
 
-  /* If image contains simply transparency data, we prefer to
+  /* If image contains simply transparency data, we prefer to 
      construct a clipping mask.  */
   if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
     transparent_p = 1;
   else
     transparent_p = 0;
 
-  /* This function is easier to write if we only have to handle
+  /* This function is easier to write if we only have to handle 
      one data format: RGB or RGBA with 8 bits per channel.  Let's
      transform other formats into that format.  */
 
@@ -11838,39 +11853,37 @@ png_load (f, img)
   png_set_expand (png_ptr);
 
   /* Convert grayscale images to RGB.  */
-  if (color_type == PNG_COLOR_TYPE_GRAY
+  if (color_type == PNG_COLOR_TYPE_GRAY 
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
     png_set_gray_to_rgb (png_ptr);
 
-  /* The value 2.2 is a guess for PC monitors from PNG example.c.  */
-  gamma_str = getenv ("SCREEN_GAMMA");
-  screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
+  screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
 
+#if 0 /* Avoid double gamma correction for PNG images. */
   /* Tell the PNG lib to handle gamma correction for us.  */
-
 #if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
   if (png_get_sRGB (png_ptr, info_ptr, &intent))
-    /* There is a special chunk in the image specifying the gamma.  */
-    png_set_sRGB (png_ptr, info_ptr, intent);
+    /* The libpng documentation says this is right in this case.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
   else
 #endif
   if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
     /* Image contains gamma information.  */
     png_set_gamma (png_ptr, screen_gamma, image_gamma);
   else
-    /* Use a default of 0.5 for the image gamma.  */
-    png_set_gamma (png_ptr, screen_gamma, 0.5);
+    /* Use the standard default for the image gamma.  */
+    png_set_gamma (png_ptr, screen_gamma, 0.45455);
+#endif /* if 0 */
 
   /* Handle alpha channel by combining the image with a background
      color.  Do this only if a real alpha channel is supplied.  For
      simple transparency, we prefer a clipping mask.  */
   if (!transparent_p)
     {
-      png_color_16 *image_background;
+      png_color_16 *image_bg;
       Lisp_Object specified_bg
        = image_spec_value (img->spec, QCbackground, NULL);
 
-
       if (STRINGP (specified_bg))
        /* The user specified `:background', use that.  */
        {
@@ -11880,36 +11893,38 @@ png_load (f, img)
              png_color_16 user_bg;
 
              bzero (&user_bg, sizeof user_bg);
-             user_bg.red = color.red;
-             user_bg.green = color.green;
-             user_bg.blue = color.blue;
+             user_bg.red = 256 * GetRValue (color);
+             user_bg.green = 256 * GetGValue (color);
+             user_bg.blue = 256 * GetBValue (color);
 
              png_set_background (png_ptr, &user_bg,
                                  PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
            }
        }
-      else if (png_get_bKGD (png_ptr, info_ptr, &image_background))
-       /* Image contains a background color with which to
+      else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
+       /* Image contains a background color with which to 
           combine the image.  */
-       png_set_background (png_ptr, image_background,
+       png_set_background (png_ptr, image_bg,
                            PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
        {
          /* Image does not contain a background color with which
-            to combine the image data via an alpha channel.  Use
+            to combine the image data via an alpha channel.  Use 
             the frame's background instead.  */
-         XColor color;
-         Colormap cmap;
+         COLORREF color;
          png_color_16 frame_background;
+         color = FRAME_BACKGROUND_PIXEL (f);
+#if 0 /* TODO : Colormap support.  */
+         Colormap cmap;
 
          cmap = FRAME_X_COLORMAP (f);
-         color.pixel = FRAME_BACKGROUND_PIXEL (f);
          x_query_color (f, &color);
+#endif
 
          bzero (&frame_background, sizeof frame_background);
-         frame_background.red = color.red;
-         frame_background.green = color.green;
-         frame_background.blue = color.blue;
+         frame_background.red = 256 * GetRValue (color);
+         frame_background.green = 256 * GetGValue (color);
+         frame_background.blue = 256 * GetBValue (color);
 
          png_set_background (png_ptr, &frame_background,
                              PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
@@ -11944,12 +11959,12 @@ png_load (f, img)
       fclose (fp);
       fp = NULL;
     }
-
+  
   /* Create the X image and pixmap.  */
   if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
                                    &img->pixmap))
     goto error;
-
+  
   /* Create an image and pixmap serving as mask if the PNG image
      contains an alpha channel.  */
   if (channels == 4
@@ -11958,13 +11973,14 @@ png_load (f, img)
                                       &mask_img, &img->mask))
     {
       x_destroy_x_image (ximg);
-      XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
+      DeleteObject (img->pixmap);
       img->pixmap = 0;
       goto error;
     }
-
   /* Fill the X image and mask from PNG data.  */
+#if 0 /* TODO: Color tables.  */
   init_color_table ();
+#endif
 
   for (y = 0; y < height; ++y)
     {
@@ -11974,22 +11990,25 @@ png_load (f, img)
        {
          unsigned r, g, b;
 
-         r = *p++ << 8;
-         g = *p++ << 8;
-         b = *p++ << 8;
+         r = *p++;
+         g = *p++;
+         b = *p++;
+#if 0 /* TODO: Color tables.  */
          XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
-
+#else
+         XPutPixel (ximg, x, y, PALETTERGB (r, g, b));
+#endif
          /* An alpha channel, aka mask channel, associates variable
-            transparency with an image.  Where other image formats
-            support binary transparency---fully transparent or fully
+            transparency with an image.  Where other image formats 
+            support binary transparency---fully transparent or fully 
             opaque---PNG allows up to 254 levels of partial transparency.
             The PNG library implements partial transparency by combining
             the image with a specified background color.
 
             I'm not sure how to handle this here nicely: because the
             background on which the image is displayed may change, for
-            real alpha channel support, it would be necessary to create
-            a new image for each possible background.
+            real alpha channel support, it would be necessary to create 
+            a new image for each possible background.  
 
             What I'm doing now is that a mask is created if we have
             boolean transparency information.  Otherwise I'm using
@@ -12011,14 +12030,21 @@ png_load (f, img)
       png_color_16 *bg;
       if (png_get_bKGD (png_ptr, info_ptr, &bg))
        {
+#if 0 /* TODO: Color tables.  */
          img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
+#else
+         img->background = PALETTERGB (bg->red / 256, bg->green / 256,
+                                       bg->blue / 256);
+#endif
          img->background_valid = 1;
        }
     }
 
+#if 0 /* TODO: Color tables.  */
   /* Remember colors allocated for this image.  */
   img->colors = colors_in_color_table (&img->ncolors);
   free_color_table ();
+#endif
 
   /* Clean up.  */
   png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);