+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));
+static void XPutPixel (XImage *, int, int, COLORREF);
+
+/* Non-zero means draw a cross on images having `:conversion
+ disabled'. */
+
+int cross_disabled_images;
+
+/* 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 */
+};
+
+/* Value is the intensity of the color whose red/green/blue values
+ are R, G, and B. */
+
+#define COLOR_INTENSITY(R, G, B) ((2 * (R) + 3 * (G) + (B)) / 6)
+
+
+/* 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;
+ struct image *img;
+ int rgb_p;
+{
+ int x, y;
+ XColor *colors, *p;
+ HDC hdc, bmpdc;
+ HGDIOBJ prev;
+
+ colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors);
+
+ /* Load the image into a memory device context. */
+ hdc = get_frame_dc (f);
+ bmpdc = CreateCompatibleDC (hdc);
+ release_frame_dc (f, hdc);
+ prev = SelectObject (bmpdc, img->pixmap);
+
+ /* 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)
+ {
+ /* TODO: palette support needed here? */
+ p->pixel = GetPixel (bmpdc, x, y);
+
+ if (rgb_p)
+ {
+ p->red = 256 * GetRValue (p->pixel);
+ p->green = 256 * GetGValue (p->pixel);
+ p->blue = 256 * GetBValue (p->pixel);
+ }
+ }
+ }
+
+ SelectObject (bmpdc, prev);
+ DeleteDC (bmpdc);
+
+ return colors;
+}
+
+/* Put a pixel of COLOR at position X, Y in XIMG. XIMG must have been
+ created with CreateDIBSection, with the pointer to the bit values
+ stored in ximg->data. */
+
+static void XPutPixel (ximg, x, y, color)
+ XImage * ximg;
+ int x, y;
+ COLORREF 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);
+}
+
+
+/* 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_from_xcolors (f, img, colors)
+ struct frame *f;
+ struct image *img;
+ XColor *colors;
+{
+ int x, y;
+ XImage *oimg;
+ Pixmap pixmap;
+ XColor *p;
+#if 0 /* TODO: color tables. */
+ init_color_table ();
+#endif
+ 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;
+#if 0 /* TODO: color tables. */
+ pixel = lookup_rgb_color (f, p->red, p->green, p->blue);
+#else
+ pixel = PALETTERGB (p->red / 256, p->green / 256, p->blue / 256);
+#endif
+ XPutPixel (oimg, x, y, pixel);
+ }
+
+ xfree (colors);
+ x_clear_image_1 (f, img, 1, 0, 1);
+
+ x_put_x_image (f, oimg, pixmap, img->width, img->height);
+ x_destroy_x_image (oimg);
+ img->pixmap = pixmap;
+#if 0 /* TODO: color tables. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+#endif
+}
+
+
+/* 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_detect_edges (f, img, matrix, color_adjust)
+ struct frame *f;
+ struct image *img;
+ int matrix[9], color_adjust;
+{
+ XColor *colors = x_to_xcolors (f, img, 1);
+ XColor *new, *p;
+ int x, y, i, sum;
+
+ for (i = sum = 0; i < 9; ++i)
+ sum += abs (matrix[i]);
+
+#define COLOR(A, X, Y) ((A) + (Y) * img->width + (X))
+
+ new = (XColor *) xmalloc (img->width * img->height * sizeof *new);
+
+ 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;
+ }