]> git.eshelyaron.com Git - emacs.git/commitdiff
(QCmatrix, QCcolor_adjustment, QCmask, Qemboss)
authorGerd Moellmann <gerd@gnu.org>
Fri, 15 Sep 2000 11:48:16 +0000 (11:48 +0000)
committerGerd Moellmann <gerd@gnu.org>
Fri, 15 Sep 2000 11:48:16 +0000 (11:48 +0000)
(Qedge_detection, Qheuristic): New symbols.
(syms_of_xfns): Initialize new symbols.
(lookup_image): Handle `:mask X', `:algorithm emboss', and
`algorithm (edge-detection ...)'.
(xbm_format, xpm_format, pbm_format, png_format, jpeg_format):
(tiff_format, gif_format, gs_format): Add `:mask'.
(XBM_MASK, XPM_MASK, PBM_MASK, PNG_MASK, JPEG_MASK, TIFF_MASK)
(GIF_MASK, GS_MASK): New enumerators.
(x_laplace_read_row, x_laplace_write_row): Functions removed.
(emboss_matrix, laplace_matrix): New variables.
(x_to_xcolors, x_from_xcolors, x_detect_edges, x_emboss)
(x_edge_detection): New functions.
(x_laplace): Rewritten in terms of x_detect_edges.
(x_build_heuristic_mask): If image has a mask, free it.

src/xfns.c

index cd277a39e3432cb50dd6518ddce44b1fc07e48c2..02cc0ade3d2f52050f2ab1fe786fb149e3f4efd4 100644 (file)
@@ -779,6 +779,8 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
                                                             char *, char *,
                                                             int));
 static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
+                                 Lisp_Object));
 
 static struct x_frame_parm_table x_frame_parms[] =
 {
@@ -5033,11 +5035,11 @@ extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
 extern Lisp_Object QCdata;
 Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
 Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex;
+Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask;
 
 /* Other symbols.  */
 
-Lisp_Object Qlaplace;
+Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic;
 
 /* Time in seconds after which images should be removed from the cache
    if not displayed.  */
@@ -5050,6 +5052,7 @@ static void define_image_type P_ ((struct image_type *type));
 static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
 static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
 static void x_laplace P_ ((struct frame *, struct image *));
+static void x_emboss P_ ((struct frame *, struct image *));
 static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
                                       Lisp_Object));
 
@@ -5725,7 +5728,7 @@ lookup_image (f, spec)
        {
          /* Handle image type independent image attributes
             `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'.  */
-         Lisp_Object ascent, margin, relief, algorithm, heuristic_mask;
+         Lisp_Object ascent, margin, relief, algorithm;
          Lisp_Object file;
 
          ascent = image_spec_value (spec, QCascent, NULL);
@@ -5745,15 +5748,69 @@ lookup_image (f, spec)
              img->margin += abs (img->relief);
            }
 
-         /* Should we apply a Laplace edge-detection algorithm?  */
+         /* Should we apply an image transformation algorithm?  */
          algorithm = image_spec_value (spec, QCalgorithm, NULL);
-         if (img->pixmap && EQ (algorithm, Qlaplace))
-           x_laplace (f, img);
+         if (img->pixmap)
+           {
+             if (EQ (algorithm, Qlaplace))
+               x_laplace (f, img);
+             else if (EQ (algorithm, Qemboss))
+               x_emboss (f, img);
+             else if (CONSP (algorithm)
+                      && EQ (XCAR (algorithm), Qedge_detection))
+               {
+                 Lisp_Object tem;
+                 tem = XCDR (algorithm);
+                 if (CONSP (tem))
+                   x_edge_detection (f, img,
+                                     Fplist_get (tem, QCmatrix),
+                                     Fplist_get (tem, QCcolor_adjustment));
+               }
+           }
+
+         /* Manipulation of the image's mask.  */
+         if (img->pixmap)
+           {
+             /* `:heuristic-mask t'
+                `:mask heuristic'
+                       means build a mask heuristically.
+                `:heuristic-mask (R G B)'
+                `:mask (heuristic (R G B))'
+                       measn build a mask from color (R G B) in the
+                       image.
+                `:mask nil'
+                       means remove a mask, if any.  */
+             
+             Lisp_Object mask;
 
-         /* Should we built a mask heuristically?  */
-         heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL);
-         if (img->pixmap && !img->mask && !NILP (heuristic_mask))
-           x_build_heuristic_mask (f, img, heuristic_mask);
+             mask = image_spec_value (spec, QCheuristic_mask, NULL);
+             if (!NILP (mask))
+               x_build_heuristic_mask (f, img, mask);
+             else
+               {
+                 int found_p;
+                   
+                 mask = image_spec_value (spec, QCmask, &found_p);
+                 
+                 if (EQ (mask, Qheuristic))
+                   x_build_heuristic_mask (f, img, Qt);
+                 else if (CONSP (mask)
+                          && EQ (XCAR (mask), Qheuristic))
+                   {
+                     if (CONSP (XCDR (mask)))
+                       x_build_heuristic_mask (f, img, XCAR (XCDR (mask)));
+                     else
+                       x_build_heuristic_mask (f, img, XCDR (mask));
+                   }
+                 else if (NILP (mask) && found_p && img->mask)
+                   {
+                     BLOCK_INPUT;
+                     XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+                     img->mask = 0;
+                     UNBLOCK_INPUT;
+                   }
+               }
+           }
        }
     }
 
@@ -6026,6 +6083,7 @@ enum xbm_keyword_index
   XBM_RELIEF,
   XBM_ALGORITHM,
   XBM_HEURISTIC_MASK,
+  XBM_MASK,
   XBM_LAST
 };
 
@@ -6045,7 +6103,8 @@ static struct image_keyword xbm_format[XBM_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type XBM.  */
@@ -6654,6 +6713,7 @@ enum xpm_keyword_index
   XPM_RELIEF,
   XPM_ALGORITHM,
   XPM_HEURISTIC_MASK,
+  XPM_MASK,
   XPM_COLOR_SYMBOLS,
   XPM_LAST
 };
@@ -6671,6 +6731,7 @@ static struct image_keyword xpm_format[XPM_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":color-symbols",   IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
@@ -7087,133 +7148,253 @@ static void x_laplace_write_row P_ ((struct frame *, long *,
                                     int, XImage *, int));
 static void x_laplace_read_row P_ ((struct frame *, Colormap,
                                    XColor *, int, XImage *, int));
+static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int));
+static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *));
+static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int));
+
+/* Edge detection matrices for different edge-detection
+   strategies.  */
+
+static int emboss_matrix[9] = {
+   /* x - 1    x       x + 1  */
+        2,     -1,       0,            /* y - 1 */
+       -1,      0,        1,           /* y     */
+        0,      1,       -2            /* y + 1 */
+};
 
+static int laplace_matrix[9] = {
+   /* x - 1    x       x + 1  */
+        1,      0,       0,            /* y - 1 */
+        0,      0,        0,           /* y     */
+        0,      0,       -1            /* y + 1 */
+};
 
-/* Fill COLORS with RGB colors from row Y of image XIMG.  F is the
-   frame we operate on, CMAP is the color-map in effect, and WIDTH is
-   the width of one row in the image.  */
 
-static void
-x_laplace_read_row (f, cmap, colors, width, ximg, y)
+/* On frame F, return an array of XColor structures describing image
+   IMG->pixmap.  Each XColor structure has its pixel color set.  RGB_P
+   non-zero means also fill the red/green/blue members of the XColor
+   structures.  Value is a pointer to the array of XColors structures,
+   allocated with xmalloc; it must be freed by the caller.  */
+
+static XColor *
+x_to_xcolors (f, img, rgb_p)
      struct frame *f;
-     Colormap cmap;
-     XColor *colors;
-     int width;
-     XImage *ximg;
-     int y;
+     struct image *img;
+     int rgb_p;
 {
-  int x;
+  int x, y;
+  XColor *colors, *p;
+  XImage *ximg;
 
-  for (x = 0; x < width; ++x)
-    colors[x].pixel = XGetPixel (ximg, x, y);
+  BLOCK_INPUT;
+  
+  colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+
+  /* Get the X image IMG->pixmap.  */
+  ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
+                   0, 0, img->width, img->height, ~0, ZPixmap);
 
-  XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width);
+  /* Fill the `pixel' members of the XColor array.  I wished there
+     were an easy and portable way to circumvent XGetPixel.  */
+  p = colors;
+  for (y = 0; y < img->height; ++y)
+    {
+      XColor *row = p;
+      
+      for (x = 0; x < img->width; ++x, ++p)
+       p->pixel = XGetPixel (ximg, x, y);
+
+      if (rgb_p)
+       XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
+                     row, img->width);
+    }
+
+  XDestroyImage (ximg);
+
+  UNBLOCK_INPUT;
+  return colors;
 }
 
 
-/* Write row Y of image XIMG.  PIXELS is an array of WIDTH longs
-   containing the pixel colors to write.  F is the frame we are
-   working on.  */
+/* 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.  */
 
 static void
-x_laplace_write_row (f, pixels, width, ximg, y)
+x_from_xcolors (f, img, colors)
      struct frame *f;
-     long *pixels;
-     int width;
-     XImage *ximg;
-     int y;
+     struct image *img;
+     XColor *colors;
 {
-  int x;
+  int x, y;
+  XImage *oimg;
+  Pixmap pixmap;
+  XColor *p;
+  
+  BLOCK_INPUT;
+  init_color_table ();
   
-  for (x = 0; x < width; ++x)
-    XPutPixel (ximg, x, y, pixels[x]);
+  x_create_x_image_and_pixmap (f, img->width, img->height, 0,
+                              &oimg, &pixmap);
+  p = colors;
+  for (y = 0; y < img->height; ++y)
+    for (x = 0; x < img->width; ++x, ++p)
+      {
+       unsigned long pixel;
+       pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+       XPutPixel (oimg, x, y, pixel);
+      }
+
+  xfree (colors);
+  x_clear_image (f, img);
+
+  x_put_x_image (f, oimg, pixmap, img->width, img->height);
+  x_destroy_x_image (oimg);
+  img->pixmap = pixmap;
+  img->colors = colors_in_color_table (&img->ncolors);
+  free_color_table ();
+  UNBLOCK_INPUT;
 }
 
 
-/* Transform image IMG which is used on frame F with a Laplace
-   edge-detection algorithm.  The result is an image that can be used
-   to draw disabled buttons, for example.  */
+/* On frame F, perform edge-detection on image IMG.
+
+   MATRIX is a nine-element array specifying the transformation
+   matrix.  See emboss_matrix for an example.
+   
+   COLOR_ADJUST is a color adjustment added to each pixel of the
+   outgoing image.  */
 
 static void
-x_laplace (f, img)
+x_detect_edges (f, img, matrix, color_adjust)
      struct frame *f;
      struct image *img;
+     int matrix[9], color_adjust;
 {
-  Colormap cmap = FRAME_X_COLORMAP (f);
-  XImage *ximg, *oimg;
-  XColor *in[3];
-  long *out;
-  Pixmap pixmap;
-  int x, y, i;
-  long pixel;
-  int in_y, out_y, rc;
-  int mv2 = 45000;
+  XColor *colors = x_to_xcolors (f, img, 1);
+  XColor *new, *p;
+  int x, y, i, sum;
 
-  BLOCK_INPUT;
+  for (i = sum = 0; i < 9; ++i)
+    sum += abs (matrix[i]);
 
-  /* Get the X image IMG->pixmap.  */
-  ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
-                   0, 0, img->width, img->height, ~0, ZPixmap);
-
-  /* Allocate 3 input rows, and one output row of colors.  */
-  for (i = 0; i < 3; ++i)
-    in[i] = (XColor *) alloca (img->width * sizeof (XColor));
-  out = (long *) alloca (img->width * sizeof (long));
+#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
 
-  /* Create an X image for output.  */
-  rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
-                                   &oimg, &pixmap);
+  new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
 
-  /* Fill first two rows.  */
-  x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
-  x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
-  in_y = 2;
-
-  /* Write first row, all zeros.  */
-  init_color_table ();
-  pixel = lookup_rgb_color (f, 0, 0, 0);
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, 0);
-  out_y = 1;
+  for (y = 0; y < img->height; ++y)
+    {
+      p = COLOR (new, 0, y);
+      p->red = p->green = p->blue = 0xffff/2;
+      p = COLOR (new, img->width - 1, y);
+      p->red = p->green = p->blue = 0xffff/2;
+    }
+  
+  for (x = 1; x < img->width - 1; ++x)
+    {
+      p = COLOR (new, x, 0);
+      p->red = p->green = p->blue = 0xffff/2;
+      p = COLOR (new, x, img->height - 1);
+      p->red = p->green = p->blue = 0xffff/2;
+    }
 
-  for (y = 2; y < img->height; ++y)
+  for (y = 1; y < img->height - 1; ++y)
     {
-      int rowa = y % 3;
-      int rowb = (y + 2) % 3;
+      p = COLOR (new, 1, y);
+      
+      for (x = 1; x < img->width - 1; ++x, ++p)
+       {
+         int r, g, b, intensity, y1, x1;
+
+         r = g = b = i = 0;
+         for (y1 = y - 1; y1 < y + 2; ++y1)
+           for (x1 = x - 1; x1 < x + 2; ++x1, ++i)
+             if (matrix[i])
+               {
+                 XColor *t = COLOR (colors, x1, y1);
+                 r += matrix[i] * t->red;
+                 g += matrix[i] * t->green;
+                 b += matrix[i] * t->blue;
+               }
 
-      x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
+         r = (r / sum + color_adjust) & 0xffff;
+         g = (g / sum + color_adjust) & 0xffff;
+         b = (b / sum + color_adjust) & 0xffff;
 
-      for (x = 0; x < img->width - 2; ++x)
-       {
-         int r = 0xffff & (in[rowa][x].red + mv2 - in[rowb][x + 2].red);
-         int g = 0xffff & (in[rowa][x].green + mv2 - in[rowb][x + 2].green);
-         int b = 0xffff & (in[rowa][x].blue + mv2 - in[rowb][x + 2].blue);
-         out[x + 1] = lookup_rgb_color (f, r, g, b);
+         intensity = (2 * r + 3 * g + b) / 6;
+         p->red = p->green = p->blue = intensity;
        }
-
-      x_laplace_write_row (f, out, img->width, oimg, out_y++);
     }
 
-  /* Write last line, all zeros.  */
-  for (x = 0; x < img->width; ++x)
-    out[x] = pixel;
-  x_laplace_write_row (f, out, img->width, oimg, out_y);
+  xfree (colors);
+  x_from_xcolors (f, img, new);
 
-  /* Free the input image, and free resources of IMG.  */
-  XDestroyImage (ximg);
-  x_clear_image (f, img);
+#undef COLOR
+}
+
+
+/* Perform the pre-defined `emboss' edge-detection on image IMG
+   on frame F.  */
+
+static void
+x_emboss (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  x_detect_edges (f, img, emboss_matrix, 0xffff / 2);
+}
+
+
+/* Perform the pre-defined `laplace' edge-detection on image IMG
+   on frame F.  */
+
+static void
+x_laplace (f, img)
+     struct frame *f;
+     struct image *img;
+{
+  x_detect_edges (f, img, laplace_matrix, 45000);
+}
+
+
+/* Perform edge-detection on image IMG on frame F, with specified
+   transformation matrix MATRIX and color-adjustment COLOR_ADJUST.
+
+   MATRIX must be either
+
+   - a list of at least 9 numbers in row-major form
+   - a vector of at least 9 numbers
+
+   COLOR_ADJUST nil means use a default; otherwise it must be a
+   number.  */
+
+static void
+x_edge_detection (f, img, matrix, color_adjust)
+     struct frame *f;
+     struct image *img;
+     Lisp_Object matrix, color_adjust;
+{
+  int i = 0;
+  int trans[9];
   
-  /* Put the output image into pixmap, and destroy it.  */
-  x_put_x_image (f, oimg, pixmap, img->width, img->height);
-  x_destroy_x_image (oimg);
+  if (CONSP (matrix))
+    {
+      for (i = 0;
+          i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix));
+          ++i, matrix = XCDR (matrix))
+       trans[i] = XFLOATINT (XCAR (matrix));
+    }
+  else if (VECTORP (matrix) && ASIZE (matrix) >= 9)
+    {
+      for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i)
+       trans[i] = XFLOATINT (AREF (matrix, i));
+    }
 
-  /* Remember new pixmap and colors in IMG.  */
-  img->pixmap = pixmap;
-  img->colors = colors_in_color_table (&img->ncolors);
-  free_color_table ();
+  if (NILP (color_adjust))
+    color_adjust = make_number (0xffff / 2);
 
-  UNBLOCK_INPUT;
+  if (i == 9 && NUMBERP (color_adjust))
+    x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust));
 }
 
 
@@ -7236,6 +7417,12 @@ x_build_heuristic_mask (f, img, how)
   unsigned long bg = 0;
 
   BLOCK_INPUT;
+
+  if (img->mask)
+    {
+      XFreePixmap (FRAME_X_DISPLAY (f), img->mask);
+      img->mask = 0;
+    }
   
   /* Create an image and pixmap serving as mask.  */
   rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
@@ -7350,6 +7537,7 @@ enum pbm_keyword_index
   PBM_RELIEF,
   PBM_ALGORITHM,
   PBM_HEURISTIC_MASK,
+  PBM_MASK,
   PBM_LAST
 };
 
@@ -7365,7 +7553,8 @@ static struct image_keyword pbm_format[PBM_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type `pbm'.  */
@@ -7668,6 +7857,7 @@ enum png_keyword_index
   PNG_RELIEF,
   PNG_ALGORITHM,
   PNG_HEURISTIC_MASK,
+  PNG_MASK,
   PNG_LAST
 };
 
@@ -7683,7 +7873,8 @@ static struct image_keyword png_format[PNG_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type `png'.  */
@@ -8152,6 +8343,7 @@ enum jpeg_keyword_index
   JPEG_RELIEF,
   JPEG_ALGORITHM,
   JPEG_HEURISTIC_MASK,
+  JPEG_MASK,
   JPEG_LAST
 };
 
@@ -8167,7 +8359,8 @@ static struct image_keyword jpeg_format[JPEG_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type `jpeg'.  */
@@ -8514,6 +8707,7 @@ enum tiff_keyword_index
   TIFF_RELIEF,
   TIFF_ALGORITHM,
   TIFF_HEURISTIC_MASK,
+  TIFF_MASK,
   TIFF_LAST
 };
 
@@ -8529,7 +8723,8 @@ static struct image_keyword tiff_format[TIFF_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type `tiff'.  */
@@ -8838,6 +9033,7 @@ enum gif_keyword_index
   GIF_RELIEF,
   GIF_ALGORITHM,
   GIF_HEURISTIC_MASK,
+  GIF_MASK,
   GIF_IMAGE,
   GIF_LAST
 };
@@ -8855,6 +9051,7 @@ static struct image_keyword gif_format[GIF_LAST] =
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0},
   {":image",           IMAGE_NON_NEGATIVE_INTEGER_VALUE,       0}
 };
 
@@ -9151,6 +9348,7 @@ enum gs_keyword_index
   GS_RELIEF,
   GS_ALGORITHM,
   GS_HEURISTIC_MASK,
+  GS_MASK,
   GS_LAST
 };
 
@@ -9169,7 +9367,8 @@ static struct image_keyword gs_format[GS_LAST] =
   {":margin",          IMAGE_POSITIVE_INTEGER_VALUE,           0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
   {":algorithm",       IMAGE_DONT_CHECK_VALUE_TYPE,            0},
-  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0}
+  {":heuristic-mask",  IMAGE_DONT_CHECK_VALUE_TYPE,            0},
+  {":mask",            IMAGE_DONT_CHECK_VALUE_TYPE,            0}
 };
 
 /* Structure describing the image type `ghostscript'.  */
@@ -10421,7 +10620,19 @@ syms_of_xfns ()
 
   Qlaplace = intern ("laplace");
   staticpro (&Qlaplace);
-  
+  Qemboss = intern ("emboss");
+  staticpro (&Qemboss);
+  Qedge_detection = intern ("edge-detection");
+  staticpro (&Qedge_detection);
+  Qheuristic = intern ("heuristic");
+  staticpro (&Qheuristic);
+  QCmatrix = intern (":matrix");
+  staticpro (&QCmatrix);
+  QCcolor_adjustment = intern (":color-adjustment");
+  staticpro (&QCcolor_adjustment);
+  QCmask = intern (":mask");
+  staticpro (&QCmask);
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);