diff options
| author | Gerd Moellmann | 2000-09-15 11:48:16 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-09-15 11:48:16 +0000 |
| commit | 4a8e312c92d7127c0bffb93ff64f7fa240e1aae1 (patch) | |
| tree | d6ab7e90028093b6178a30bc55f07db8eb848260 /src | |
| parent | fe83b953b198b65ea6eddb76bc12f5bd5880eb77 (diff) | |
| download | emacs-4a8e312c92d7127c0bffb93ff64f7fa240e1aae1.tar.gz emacs-4a8e312c92d7127c0bffb93ff64f7fa240e1aae1.zip | |
(QCmatrix, QCcolor_adjustment, QCmask, Qemboss)
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xfns.c | 423 |
1 files changed, 317 insertions, 106 deletions
diff --git a/src/xfns.c b/src/xfns.c index cd277a39e34..02cc0ade3d2 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -779,6 +779,8 @@ static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *, | |||
| 779 | char *, char *, | 779 | char *, char *, |
| 780 | int)); | 780 | int)); |
| 781 | static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object)); | 781 | static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object)); |
| 782 | static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object, | ||
| 783 | Lisp_Object)); | ||
| 782 | 784 | ||
| 783 | static struct x_frame_parm_table x_frame_parms[] = | 785 | static struct x_frame_parm_table x_frame_parms[] = |
| 784 | { | 786 | { |
| @@ -5033,11 +5035,11 @@ extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; | |||
| 5033 | extern Lisp_Object QCdata; | 5035 | extern Lisp_Object QCdata; |
| 5034 | Lisp_Object QCtype, QCascent, QCmargin, QCrelief; | 5036 | Lisp_Object QCtype, QCascent, QCmargin, QCrelief; |
| 5035 | Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask; | 5037 | Lisp_Object QCalgorithm, QCcolor_symbols, QCheuristic_mask; |
| 5036 | Lisp_Object QCindex; | 5038 | Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; |
| 5037 | 5039 | ||
| 5038 | /* Other symbols. */ | 5040 | /* Other symbols. */ |
| 5039 | 5041 | ||
| 5040 | Lisp_Object Qlaplace; | 5042 | Lisp_Object Qlaplace, Qemboss, Qedge_detection, Qheuristic; |
| 5041 | 5043 | ||
| 5042 | /* Time in seconds after which images should be removed from the cache | 5044 | /* Time in seconds after which images should be removed from the cache |
| 5043 | if not displayed. */ | 5045 | if not displayed. */ |
| @@ -5050,6 +5052,7 @@ static void define_image_type P_ ((struct image_type *type)); | |||
| 5050 | static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); | 5052 | static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); |
| 5051 | static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); | 5053 | static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); |
| 5052 | static void x_laplace P_ ((struct frame *, struct image *)); | 5054 | static void x_laplace P_ ((struct frame *, struct image *)); |
| 5055 | static void x_emboss P_ ((struct frame *, struct image *)); | ||
| 5053 | static int x_build_heuristic_mask P_ ((struct frame *, struct image *, | 5056 | static int x_build_heuristic_mask P_ ((struct frame *, struct image *, |
| 5054 | Lisp_Object)); | 5057 | Lisp_Object)); |
| 5055 | 5058 | ||
| @@ -5725,7 +5728,7 @@ lookup_image (f, spec) | |||
| 5725 | { | 5728 | { |
| 5726 | /* Handle image type independent image attributes | 5729 | /* Handle image type independent image attributes |
| 5727 | `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */ | 5730 | `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */ |
| 5728 | Lisp_Object ascent, margin, relief, algorithm, heuristic_mask; | 5731 | Lisp_Object ascent, margin, relief, algorithm; |
| 5729 | Lisp_Object file; | 5732 | Lisp_Object file; |
| 5730 | 5733 | ||
| 5731 | ascent = image_spec_value (spec, QCascent, NULL); | 5734 | ascent = image_spec_value (spec, QCascent, NULL); |
| @@ -5745,15 +5748,69 @@ lookup_image (f, spec) | |||
| 5745 | img->margin += abs (img->relief); | 5748 | img->margin += abs (img->relief); |
| 5746 | } | 5749 | } |
| 5747 | 5750 | ||
| 5748 | /* Should we apply a Laplace edge-detection algorithm? */ | 5751 | /* Should we apply an image transformation algorithm? */ |
| 5749 | algorithm = image_spec_value (spec, QCalgorithm, NULL); | 5752 | algorithm = image_spec_value (spec, QCalgorithm, NULL); |
| 5750 | if (img->pixmap && EQ (algorithm, Qlaplace)) | 5753 | if (img->pixmap) |
| 5751 | x_laplace (f, img); | 5754 | { |
| 5755 | if (EQ (algorithm, Qlaplace)) | ||
| 5756 | x_laplace (f, img); | ||
| 5757 | else if (EQ (algorithm, Qemboss)) | ||
| 5758 | x_emboss (f, img); | ||
| 5759 | else if (CONSP (algorithm) | ||
| 5760 | && EQ (XCAR (algorithm), Qedge_detection)) | ||
| 5761 | { | ||
| 5762 | Lisp_Object tem; | ||
| 5763 | tem = XCDR (algorithm); | ||
| 5764 | if (CONSP (tem)) | ||
| 5765 | x_edge_detection (f, img, | ||
| 5766 | Fplist_get (tem, QCmatrix), | ||
| 5767 | Fplist_get (tem, QCcolor_adjustment)); | ||
| 5768 | } | ||
| 5769 | } | ||
| 5770 | |||
| 5771 | /* Manipulation of the image's mask. */ | ||
| 5772 | if (img->pixmap) | ||
| 5773 | { | ||
| 5774 | /* `:heuristic-mask t' | ||
| 5775 | `:mask heuristic' | ||
| 5776 | means build a mask heuristically. | ||
| 5777 | `:heuristic-mask (R G B)' | ||
| 5778 | `:mask (heuristic (R G B))' | ||
| 5779 | measn build a mask from color (R G B) in the | ||
| 5780 | image. | ||
| 5781 | `:mask nil' | ||
| 5782 | means remove a mask, if any. */ | ||
| 5783 | |||
| 5784 | Lisp_Object mask; | ||
| 5752 | 5785 | ||
| 5753 | /* Should we built a mask heuristically? */ | 5786 | mask = image_spec_value (spec, QCheuristic_mask, NULL); |
| 5754 | heuristic_mask = image_spec_value (spec, QCheuristic_mask, NULL); | 5787 | if (!NILP (mask)) |
| 5755 | if (img->pixmap && !img->mask && !NILP (heuristic_mask)) | 5788 | x_build_heuristic_mask (f, img, mask); |
| 5756 | x_build_heuristic_mask (f, img, heuristic_mask); | 5789 | else |
| 5790 | { | ||
| 5791 | int found_p; | ||
| 5792 | |||
| 5793 | mask = image_spec_value (spec, QCmask, &found_p); | ||
| 5794 | |||
| 5795 | if (EQ (mask, Qheuristic)) | ||
| 5796 | x_build_heuristic_mask (f, img, Qt); | ||
| 5797 | else if (CONSP (mask) | ||
| 5798 | && EQ (XCAR (mask), Qheuristic)) | ||
| 5799 | { | ||
| 5800 | if (CONSP (XCDR (mask))) | ||
| 5801 | x_build_heuristic_mask (f, img, XCAR (XCDR (mask))); | ||
| 5802 | else | ||
| 5803 | x_build_heuristic_mask (f, img, XCDR (mask)); | ||
| 5804 | } | ||
| 5805 | else if (NILP (mask) && found_p && img->mask) | ||
| 5806 | { | ||
| 5807 | BLOCK_INPUT; | ||
| 5808 | XFreePixmap (FRAME_X_DISPLAY (f), img->mask); | ||
| 5809 | img->mask = 0; | ||
| 5810 | UNBLOCK_INPUT; | ||
| 5811 | } | ||
| 5812 | } | ||
| 5813 | } | ||
| 5757 | } | 5814 | } |
| 5758 | } | 5815 | } |
| 5759 | 5816 | ||
| @@ -6026,6 +6083,7 @@ enum xbm_keyword_index | |||
| 6026 | XBM_RELIEF, | 6083 | XBM_RELIEF, |
| 6027 | XBM_ALGORITHM, | 6084 | XBM_ALGORITHM, |
| 6028 | XBM_HEURISTIC_MASK, | 6085 | XBM_HEURISTIC_MASK, |
| 6086 | XBM_MASK, | ||
| 6029 | XBM_LAST | 6087 | XBM_LAST |
| 6030 | }; | 6088 | }; |
| 6031 | 6089 | ||
| @@ -6045,7 +6103,8 @@ static struct image_keyword xbm_format[XBM_LAST] = | |||
| 6045 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 6103 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 6046 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 6104 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 6047 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6105 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6048 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 6106 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6107 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 6049 | }; | 6108 | }; |
| 6050 | 6109 | ||
| 6051 | /* Structure describing the image type XBM. */ | 6110 | /* Structure describing the image type XBM. */ |
| @@ -6654,6 +6713,7 @@ enum xpm_keyword_index | |||
| 6654 | XPM_RELIEF, | 6713 | XPM_RELIEF, |
| 6655 | XPM_ALGORITHM, | 6714 | XPM_ALGORITHM, |
| 6656 | XPM_HEURISTIC_MASK, | 6715 | XPM_HEURISTIC_MASK, |
| 6716 | XPM_MASK, | ||
| 6657 | XPM_COLOR_SYMBOLS, | 6717 | XPM_COLOR_SYMBOLS, |
| 6658 | XPM_LAST | 6718 | XPM_LAST |
| 6659 | }; | 6719 | }; |
| @@ -6671,6 +6731,7 @@ static struct image_keyword xpm_format[XPM_LAST] = | |||
| 6671 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 6731 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 6672 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6732 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6673 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 6733 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 6734 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 6674 | {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 6735 | {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0} |
| 6675 | }; | 6736 | }; |
| 6676 | 6737 | ||
| @@ -7087,133 +7148,253 @@ static void x_laplace_write_row P_ ((struct frame *, long *, | |||
| 7087 | int, XImage *, int)); | 7148 | int, XImage *, int)); |
| 7088 | static void x_laplace_read_row P_ ((struct frame *, Colormap, | 7149 | static void x_laplace_read_row P_ ((struct frame *, Colormap, |
| 7089 | XColor *, int, XImage *, int)); | 7150 | XColor *, int, XImage *, int)); |
| 7151 | static XColor *x_to_xcolors P_ ((struct frame *, struct image *, int)); | ||
| 7152 | static void x_from_xcolors P_ ((struct frame *, struct image *, XColor *)); | ||
| 7153 | static void x_detect_edges P_ ((struct frame *, struct image *, int[9], int)); | ||
| 7154 | |||
| 7155 | /* Edge detection matrices for different edge-detection | ||
| 7156 | strategies. */ | ||
| 7157 | |||
| 7158 | static int emboss_matrix[9] = { | ||
| 7159 | /* x - 1 x x + 1 */ | ||
| 7160 | 2, -1, 0, /* y - 1 */ | ||
| 7161 | -1, 0, 1, /* y */ | ||
| 7162 | 0, 1, -2 /* y + 1 */ | ||
| 7163 | }; | ||
| 7090 | 7164 | ||
| 7165 | static int laplace_matrix[9] = { | ||
| 7166 | /* x - 1 x x + 1 */ | ||
| 7167 | 1, 0, 0, /* y - 1 */ | ||
| 7168 | 0, 0, 0, /* y */ | ||
| 7169 | 0, 0, -1 /* y + 1 */ | ||
| 7170 | }; | ||
| 7091 | 7171 | ||
| 7092 | /* Fill COLORS with RGB colors from row Y of image XIMG. F is the | ||
| 7093 | frame we operate on, CMAP is the color-map in effect, and WIDTH is | ||
| 7094 | the width of one row in the image. */ | ||
| 7095 | 7172 | ||
| 7096 | static void | 7173 | /* On frame F, return an array of XColor structures describing image |
| 7097 | x_laplace_read_row (f, cmap, colors, width, ximg, y) | 7174 | IMG->pixmap. Each XColor structure has its pixel color set. RGB_P |
| 7175 | non-zero means also fill the red/green/blue members of the XColor | ||
| 7176 | structures. Value is a pointer to the array of XColors structures, | ||
| 7177 | allocated with xmalloc; it must be freed by the caller. */ | ||
| 7178 | |||
| 7179 | static XColor * | ||
| 7180 | x_to_xcolors (f, img, rgb_p) | ||
| 7098 | struct frame *f; | 7181 | struct frame *f; |
| 7099 | Colormap cmap; | 7182 | struct image *img; |
| 7100 | XColor *colors; | 7183 | int rgb_p; |
| 7101 | int width; | ||
| 7102 | XImage *ximg; | ||
| 7103 | int y; | ||
| 7104 | { | 7184 | { |
| 7105 | int x; | 7185 | int x, y; |
| 7186 | XColor *colors, *p; | ||
| 7187 | XImage *ximg; | ||
| 7106 | 7188 | ||
| 7107 | for (x = 0; x < width; ++x) | 7189 | BLOCK_INPUT; |
| 7108 | colors[x].pixel = XGetPixel (ximg, x, y); | 7190 | |
| 7191 | colors = (XColor *) xmalloc (img->width * img->height * sizeof *colors); | ||
| 7192 | |||
| 7193 | /* Get the X image IMG->pixmap. */ | ||
| 7194 | ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, | ||
| 7195 | 0, 0, img->width, img->height, ~0, ZPixmap); | ||
| 7109 | 7196 | ||
| 7110 | XQueryColors (FRAME_X_DISPLAY (f), cmap, colors, width); | 7197 | /* Fill the `pixel' members of the XColor array. I wished there |
| 7198 | were an easy and portable way to circumvent XGetPixel. */ | ||
| 7199 | p = colors; | ||
| 7200 | for (y = 0; y < img->height; ++y) | ||
| 7201 | { | ||
| 7202 | XColor *row = p; | ||
| 7203 | |||
| 7204 | for (x = 0; x < img->width; ++x, ++p) | ||
| 7205 | p->pixel = XGetPixel (ximg, x, y); | ||
| 7206 | |||
| 7207 | if (rgb_p) | ||
| 7208 | XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), | ||
| 7209 | row, img->width); | ||
| 7210 | } | ||
| 7211 | |||
| 7212 | XDestroyImage (ximg); | ||
| 7213 | |||
| 7214 | UNBLOCK_INPUT; | ||
| 7215 | return colors; | ||
| 7111 | } | 7216 | } |
| 7112 | 7217 | ||
| 7113 | 7218 | ||
| 7114 | /* Write row Y of image XIMG. PIXELS is an array of WIDTH longs | 7219 | /* Create IMG->pixmap from an array COLORS of XColor structures, whose |
| 7115 | containing the pixel colors to write. F is the frame we are | 7220 | RGB members are set. F is the frame on which this all happens. |
| 7116 | working on. */ | 7221 | COLORS will be freed; an existing IMG->pixmap will be freed, too. */ |
| 7117 | 7222 | ||
| 7118 | static void | 7223 | static void |
| 7119 | x_laplace_write_row (f, pixels, width, ximg, y) | 7224 | x_from_xcolors (f, img, colors) |
| 7120 | struct frame *f; | 7225 | struct frame *f; |
| 7121 | long *pixels; | 7226 | struct image *img; |
| 7122 | int width; | 7227 | XColor *colors; |
| 7123 | XImage *ximg; | ||
| 7124 | int y; | ||
| 7125 | { | 7228 | { |
| 7126 | int x; | 7229 | int x, y; |
| 7230 | XImage *oimg; | ||
| 7231 | Pixmap pixmap; | ||
| 7232 | XColor *p; | ||
| 7233 | |||
| 7234 | BLOCK_INPUT; | ||
| 7235 | init_color_table (); | ||
| 7127 | 7236 | ||
| 7128 | for (x = 0; x < width; ++x) | 7237 | x_create_x_image_and_pixmap (f, img->width, img->height, 0, |
| 7129 | XPutPixel (ximg, x, y, pixels[x]); | 7238 | &oimg, &pixmap); |
| 7239 | p = colors; | ||
| 7240 | for (y = 0; y < img->height; ++y) | ||
| 7241 | for (x = 0; x < img->width; ++x, ++p) | ||
| 7242 | { | ||
| 7243 | unsigned long pixel; | ||
| 7244 | pixel = lookup_rgb_color (f, p->red, p->green, p->blue); | ||
| 7245 | XPutPixel (oimg, x, y, pixel); | ||
| 7246 | } | ||
| 7247 | |||
| 7248 | xfree (colors); | ||
| 7249 | x_clear_image (f, img); | ||
| 7250 | |||
| 7251 | x_put_x_image (f, oimg, pixmap, img->width, img->height); | ||
| 7252 | x_destroy_x_image (oimg); | ||
| 7253 | img->pixmap = pixmap; | ||
| 7254 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7255 | free_color_table (); | ||
| 7256 | UNBLOCK_INPUT; | ||
| 7130 | } | 7257 | } |
| 7131 | 7258 | ||
| 7132 | 7259 | ||
| 7133 | /* Transform image IMG which is used on frame F with a Laplace | 7260 | /* On frame F, perform edge-detection on image IMG. |
| 7134 | edge-detection algorithm. The result is an image that can be used | 7261 | |
| 7135 | to draw disabled buttons, for example. */ | 7262 | MATRIX is a nine-element array specifying the transformation |
| 7263 | matrix. See emboss_matrix for an example. | ||
| 7264 | |||
| 7265 | COLOR_ADJUST is a color adjustment added to each pixel of the | ||
| 7266 | outgoing image. */ | ||
| 7136 | 7267 | ||
| 7137 | static void | 7268 | static void |
| 7138 | x_laplace (f, img) | 7269 | x_detect_edges (f, img, matrix, color_adjust) |
| 7139 | struct frame *f; | 7270 | struct frame *f; |
| 7140 | struct image *img; | 7271 | struct image *img; |
| 7272 | int matrix[9], color_adjust; | ||
| 7141 | { | 7273 | { |
| 7142 | Colormap cmap = FRAME_X_COLORMAP (f); | 7274 | XColor *colors = x_to_xcolors (f, img, 1); |
| 7143 | XImage *ximg, *oimg; | 7275 | XColor *new, *p; |
| 7144 | XColor *in[3]; | 7276 | int x, y, i, sum; |
| 7145 | long *out; | ||
| 7146 | Pixmap pixmap; | ||
| 7147 | int x, y, i; | ||
| 7148 | long pixel; | ||
| 7149 | int in_y, out_y, rc; | ||
| 7150 | int mv2 = 45000; | ||
| 7151 | 7277 | ||
| 7152 | BLOCK_INPUT; | 7278 | for (i = sum = 0; i < 9; ++i) |
| 7279 | sum += abs (matrix[i]); | ||
| 7153 | 7280 | ||
| 7154 | /* Get the X image IMG->pixmap. */ | 7281 | #define COLOR(A, X, Y) ((A) + (Y) * img->width + (X)) |
| 7155 | ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, | ||
| 7156 | 0, 0, img->width, img->height, ~0, ZPixmap); | ||
| 7157 | |||
| 7158 | /* Allocate 3 input rows, and one output row of colors. */ | ||
| 7159 | for (i = 0; i < 3; ++i) | ||
| 7160 | in[i] = (XColor *) alloca (img->width * sizeof (XColor)); | ||
| 7161 | out = (long *) alloca (img->width * sizeof (long)); | ||
| 7162 | 7282 | ||
| 7163 | /* Create an X image for output. */ | 7283 | new = (XColor *) xmalloc (img->width * img->height * sizeof *new); |
| 7164 | rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0, | ||
| 7165 | &oimg, &pixmap); | ||
| 7166 | 7284 | ||
| 7167 | /* Fill first two rows. */ | 7285 | for (y = 0; y < img->height; ++y) |
| 7168 | x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0); | 7286 | { |
| 7169 | x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1); | 7287 | p = COLOR (new, 0, y); |
| 7170 | in_y = 2; | 7288 | p->red = p->green = p->blue = 0xffff/2; |
| 7171 | 7289 | p = COLOR (new, img->width - 1, y); | |
| 7172 | /* Write first row, all zeros. */ | 7290 | p->red = p->green = p->blue = 0xffff/2; |
| 7173 | init_color_table (); | 7291 | } |
| 7174 | pixel = lookup_rgb_color (f, 0, 0, 0); | 7292 | |
| 7175 | for (x = 0; x < img->width; ++x) | 7293 | for (x = 1; x < img->width - 1; ++x) |
| 7176 | out[x] = pixel; | 7294 | { |
| 7177 | x_laplace_write_row (f, out, img->width, oimg, 0); | 7295 | p = COLOR (new, x, 0); |
| 7178 | out_y = 1; | 7296 | p->red = p->green = p->blue = 0xffff/2; |
| 7297 | p = COLOR (new, x, img->height - 1); | ||
| 7298 | p->red = p->green = p->blue = 0xffff/2; | ||
| 7299 | } | ||
| 7179 | 7300 | ||
| 7180 | for (y = 2; y < img->height; ++y) | 7301 | for (y = 1; y < img->height - 1; ++y) |
| 7181 | { | 7302 | { |
| 7182 | int rowa = y % 3; | 7303 | p = COLOR (new, 1, y); |
| 7183 | int rowb = (y + 2) % 3; | 7304 | |
| 7305 | for (x = 1; x < img->width - 1; ++x, ++p) | ||
| 7306 | { | ||
| 7307 | int r, g, b, intensity, y1, x1; | ||
| 7308 | |||
| 7309 | r = g = b = i = 0; | ||
| 7310 | for (y1 = y - 1; y1 < y + 2; ++y1) | ||
| 7311 | for (x1 = x - 1; x1 < x + 2; ++x1, ++i) | ||
| 7312 | if (matrix[i]) | ||
| 7313 | { | ||
| 7314 | XColor *t = COLOR (colors, x1, y1); | ||
| 7315 | r += matrix[i] * t->red; | ||
| 7316 | g += matrix[i] * t->green; | ||
| 7317 | b += matrix[i] * t->blue; | ||
| 7318 | } | ||
| 7184 | 7319 | ||
| 7185 | x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++); | 7320 | r = (r / sum + color_adjust) & 0xffff; |
| 7321 | g = (g / sum + color_adjust) & 0xffff; | ||
| 7322 | b = (b / sum + color_adjust) & 0xffff; | ||
| 7186 | 7323 | ||
| 7187 | for (x = 0; x < img->width - 2; ++x) | 7324 | intensity = (2 * r + 3 * g + b) / 6; |
| 7188 | { | 7325 | p->red = p->green = p->blue = intensity; |
| 7189 | int r = 0xffff & (in[rowa][x].red + mv2 - in[rowb][x + 2].red); | ||
| 7190 | int g = 0xffff & (in[rowa][x].green + mv2 - in[rowb][x + 2].green); | ||
| 7191 | int b = 0xffff & (in[rowa][x].blue + mv2 - in[rowb][x + 2].blue); | ||
| 7192 | out[x + 1] = lookup_rgb_color (f, r, g, b); | ||
| 7193 | } | 7326 | } |
| 7194 | |||
| 7195 | x_laplace_write_row (f, out, img->width, oimg, out_y++); | ||
| 7196 | } | 7327 | } |
| 7197 | 7328 | ||
| 7198 | /* Write last line, all zeros. */ | 7329 | xfree (colors); |
| 7199 | for (x = 0; x < img->width; ++x) | 7330 | x_from_xcolors (f, img, new); |
| 7200 | out[x] = pixel; | ||
| 7201 | x_laplace_write_row (f, out, img->width, oimg, out_y); | ||
| 7202 | 7331 | ||
| 7203 | /* Free the input image, and free resources of IMG. */ | 7332 | #undef COLOR |
| 7204 | XDestroyImage (ximg); | 7333 | } |
| 7205 | x_clear_image (f, img); | 7334 | |
| 7335 | |||
| 7336 | /* Perform the pre-defined `emboss' edge-detection on image IMG | ||
| 7337 | on frame F. */ | ||
| 7338 | |||
| 7339 | static void | ||
| 7340 | x_emboss (f, img) | ||
| 7341 | struct frame *f; | ||
| 7342 | struct image *img; | ||
| 7343 | { | ||
| 7344 | x_detect_edges (f, img, emboss_matrix, 0xffff / 2); | ||
| 7345 | } | ||
| 7346 | |||
| 7347 | |||
| 7348 | /* Perform the pre-defined `laplace' edge-detection on image IMG | ||
| 7349 | on frame F. */ | ||
| 7350 | |||
| 7351 | static void | ||
| 7352 | x_laplace (f, img) | ||
| 7353 | struct frame *f; | ||
| 7354 | struct image *img; | ||
| 7355 | { | ||
| 7356 | x_detect_edges (f, img, laplace_matrix, 45000); | ||
| 7357 | } | ||
| 7358 | |||
| 7359 | |||
| 7360 | /* Perform edge-detection on image IMG on frame F, with specified | ||
| 7361 | transformation matrix MATRIX and color-adjustment COLOR_ADJUST. | ||
| 7362 | |||
| 7363 | MATRIX must be either | ||
| 7364 | |||
| 7365 | - a list of at least 9 numbers in row-major form | ||
| 7366 | - a vector of at least 9 numbers | ||
| 7367 | |||
| 7368 | COLOR_ADJUST nil means use a default; otherwise it must be a | ||
| 7369 | number. */ | ||
| 7370 | |||
| 7371 | static void | ||
| 7372 | x_edge_detection (f, img, matrix, color_adjust) | ||
| 7373 | struct frame *f; | ||
| 7374 | struct image *img; | ||
| 7375 | Lisp_Object matrix, color_adjust; | ||
| 7376 | { | ||
| 7377 | int i = 0; | ||
| 7378 | int trans[9]; | ||
| 7206 | 7379 | ||
| 7207 | /* Put the output image into pixmap, and destroy it. */ | 7380 | if (CONSP (matrix)) |
| 7208 | x_put_x_image (f, oimg, pixmap, img->width, img->height); | 7381 | { |
| 7209 | x_destroy_x_image (oimg); | 7382 | for (i = 0; |
| 7383 | i < 9 && CONSP (matrix) && NUMBERP (XCAR (matrix)); | ||
| 7384 | ++i, matrix = XCDR (matrix)) | ||
| 7385 | trans[i] = XFLOATINT (XCAR (matrix)); | ||
| 7386 | } | ||
| 7387 | else if (VECTORP (matrix) && ASIZE (matrix) >= 9) | ||
| 7388 | { | ||
| 7389 | for (i = 0; i < 9 && NUMBERP (AREF (matrix, i)); ++i) | ||
| 7390 | trans[i] = XFLOATINT (AREF (matrix, i)); | ||
| 7391 | } | ||
| 7210 | 7392 | ||
| 7211 | /* Remember new pixmap and colors in IMG. */ | 7393 | if (NILP (color_adjust)) |
| 7212 | img->pixmap = pixmap; | 7394 | color_adjust = make_number (0xffff / 2); |
| 7213 | img->colors = colors_in_color_table (&img->ncolors); | ||
| 7214 | free_color_table (); | ||
| 7215 | 7395 | ||
| 7216 | UNBLOCK_INPUT; | 7396 | if (i == 9 && NUMBERP (color_adjust)) |
| 7397 | x_detect_edges (f, img, trans, (int) XFLOATINT (color_adjust)); | ||
| 7217 | } | 7398 | } |
| 7218 | 7399 | ||
| 7219 | 7400 | ||
| @@ -7236,6 +7417,12 @@ x_build_heuristic_mask (f, img, how) | |||
| 7236 | unsigned long bg = 0; | 7417 | unsigned long bg = 0; |
| 7237 | 7418 | ||
| 7238 | BLOCK_INPUT; | 7419 | BLOCK_INPUT; |
| 7420 | |||
| 7421 | if (img->mask) | ||
| 7422 | { | ||
| 7423 | XFreePixmap (FRAME_X_DISPLAY (f), img->mask); | ||
| 7424 | img->mask = 0; | ||
| 7425 | } | ||
| 7239 | 7426 | ||
| 7240 | /* Create an image and pixmap serving as mask. */ | 7427 | /* Create an image and pixmap serving as mask. */ |
| 7241 | rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, | 7428 | rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, |
| @@ -7350,6 +7537,7 @@ enum pbm_keyword_index | |||
| 7350 | PBM_RELIEF, | 7537 | PBM_RELIEF, |
| 7351 | PBM_ALGORITHM, | 7538 | PBM_ALGORITHM, |
| 7352 | PBM_HEURISTIC_MASK, | 7539 | PBM_HEURISTIC_MASK, |
| 7540 | PBM_MASK, | ||
| 7353 | PBM_LAST | 7541 | PBM_LAST |
| 7354 | }; | 7542 | }; |
| 7355 | 7543 | ||
| @@ -7365,7 +7553,8 @@ static struct image_keyword pbm_format[PBM_LAST] = | |||
| 7365 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 7553 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 7366 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 7554 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 7367 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7555 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7368 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 7556 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7557 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 7369 | }; | 7558 | }; |
| 7370 | 7559 | ||
| 7371 | /* Structure describing the image type `pbm'. */ | 7560 | /* Structure describing the image type `pbm'. */ |
| @@ -7668,6 +7857,7 @@ enum png_keyword_index | |||
| 7668 | PNG_RELIEF, | 7857 | PNG_RELIEF, |
| 7669 | PNG_ALGORITHM, | 7858 | PNG_ALGORITHM, |
| 7670 | PNG_HEURISTIC_MASK, | 7859 | PNG_HEURISTIC_MASK, |
| 7860 | PNG_MASK, | ||
| 7671 | PNG_LAST | 7861 | PNG_LAST |
| 7672 | }; | 7862 | }; |
| 7673 | 7863 | ||
| @@ -7683,7 +7873,8 @@ static struct image_keyword png_format[PNG_LAST] = | |||
| 7683 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 7873 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 7684 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 7874 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 7685 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 7875 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7686 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 7876 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 7877 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 7687 | }; | 7878 | }; |
| 7688 | 7879 | ||
| 7689 | /* Structure describing the image type `png'. */ | 7880 | /* Structure describing the image type `png'. */ |
| @@ -8152,6 +8343,7 @@ enum jpeg_keyword_index | |||
| 8152 | JPEG_RELIEF, | 8343 | JPEG_RELIEF, |
| 8153 | JPEG_ALGORITHM, | 8344 | JPEG_ALGORITHM, |
| 8154 | JPEG_HEURISTIC_MASK, | 8345 | JPEG_HEURISTIC_MASK, |
| 8346 | JPEG_MASK, | ||
| 8155 | JPEG_LAST | 8347 | JPEG_LAST |
| 8156 | }; | 8348 | }; |
| 8157 | 8349 | ||
| @@ -8167,7 +8359,8 @@ static struct image_keyword jpeg_format[JPEG_LAST] = | |||
| 8167 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 8359 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 8168 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 8360 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 8169 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8361 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8170 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 8362 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8363 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 8171 | }; | 8364 | }; |
| 8172 | 8365 | ||
| 8173 | /* Structure describing the image type `jpeg'. */ | 8366 | /* Structure describing the image type `jpeg'. */ |
| @@ -8514,6 +8707,7 @@ enum tiff_keyword_index | |||
| 8514 | TIFF_RELIEF, | 8707 | TIFF_RELIEF, |
| 8515 | TIFF_ALGORITHM, | 8708 | TIFF_ALGORITHM, |
| 8516 | TIFF_HEURISTIC_MASK, | 8709 | TIFF_HEURISTIC_MASK, |
| 8710 | TIFF_MASK, | ||
| 8517 | TIFF_LAST | 8711 | TIFF_LAST |
| 8518 | }; | 8712 | }; |
| 8519 | 8713 | ||
| @@ -8529,7 +8723,8 @@ static struct image_keyword tiff_format[TIFF_LAST] = | |||
| 8529 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 8723 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 8530 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 8724 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 8531 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 8725 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8532 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 8726 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8727 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 8533 | }; | 8728 | }; |
| 8534 | 8729 | ||
| 8535 | /* Structure describing the image type `tiff'. */ | 8730 | /* Structure describing the image type `tiff'. */ |
| @@ -8838,6 +9033,7 @@ enum gif_keyword_index | |||
| 8838 | GIF_RELIEF, | 9033 | GIF_RELIEF, |
| 8839 | GIF_ALGORITHM, | 9034 | GIF_ALGORITHM, |
| 8840 | GIF_HEURISTIC_MASK, | 9035 | GIF_HEURISTIC_MASK, |
| 9036 | GIF_MASK, | ||
| 8841 | GIF_IMAGE, | 9037 | GIF_IMAGE, |
| 8842 | GIF_LAST | 9038 | GIF_LAST |
| 8843 | }; | 9039 | }; |
| @@ -8855,6 +9051,7 @@ static struct image_keyword gif_format[GIF_LAST] = | |||
| 8855 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 9051 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 8856 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 9052 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 8857 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 9053 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 9054 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | ||
| 8858 | {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} | 9055 | {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0} |
| 8859 | }; | 9056 | }; |
| 8860 | 9057 | ||
| @@ -9151,6 +9348,7 @@ enum gs_keyword_index | |||
| 9151 | GS_RELIEF, | 9348 | GS_RELIEF, |
| 9152 | GS_ALGORITHM, | 9349 | GS_ALGORITHM, |
| 9153 | GS_HEURISTIC_MASK, | 9350 | GS_HEURISTIC_MASK, |
| 9351 | GS_MASK, | ||
| 9154 | GS_LAST | 9352 | GS_LAST |
| 9155 | }; | 9353 | }; |
| 9156 | 9354 | ||
| @@ -9169,7 +9367,8 @@ static struct image_keyword gs_format[GS_LAST] = | |||
| 9169 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, | 9367 | {":margin", IMAGE_POSITIVE_INTEGER_VALUE, 0}, |
| 9170 | {":relief", IMAGE_INTEGER_VALUE, 0}, | 9368 | {":relief", IMAGE_INTEGER_VALUE, 0}, |
| 9171 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, | 9369 | {":algorithm", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 9172 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | 9370 | {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, |
| 9371 | {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} | ||
| 9173 | }; | 9372 | }; |
| 9174 | 9373 | ||
| 9175 | /* Structure describing the image type `ghostscript'. */ | 9374 | /* Structure describing the image type `ghostscript'. */ |
| @@ -10421,7 +10620,19 @@ syms_of_xfns () | |||
| 10421 | 10620 | ||
| 10422 | Qlaplace = intern ("laplace"); | 10621 | Qlaplace = intern ("laplace"); |
| 10423 | staticpro (&Qlaplace); | 10622 | staticpro (&Qlaplace); |
| 10424 | 10623 | Qemboss = intern ("emboss"); | |
| 10624 | staticpro (&Qemboss); | ||
| 10625 | Qedge_detection = intern ("edge-detection"); | ||
| 10626 | staticpro (&Qedge_detection); | ||
| 10627 | Qheuristic = intern ("heuristic"); | ||
| 10628 | staticpro (&Qheuristic); | ||
| 10629 | QCmatrix = intern (":matrix"); | ||
| 10630 | staticpro (&QCmatrix); | ||
| 10631 | QCcolor_adjustment = intern (":color-adjustment"); | ||
| 10632 | staticpro (&QCcolor_adjustment); | ||
| 10633 | QCmask = intern (":mask"); | ||
| 10634 | staticpro (&QCmask); | ||
| 10635 | |||
| 10425 | Qface_set_after_frame_default = intern ("face-set-after-frame-default"); | 10636 | Qface_set_after_frame_default = intern ("face-set-after-frame-default"); |
| 10426 | staticpro (&Qface_set_after_frame_default); | 10637 | staticpro (&Qface_set_after_frame_default); |
| 10427 | 10638 | ||