aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Third2021-03-09 18:05:10 +0000
committerAlan Third2021-03-10 21:40:42 +0000
commitc93447eac6f801d7ff97ed6dad368dc49d55cc46 (patch)
tree4643e59abe2e6ca836250f65b9dd5dcc75058f8e
parentd07ed6dfee9338b0d715f8181703252c99e5133a (diff)
downloademacs-c93447eac6f801d7ff97ed6dad368dc49d55cc46.tar.gz
emacs-c93447eac6f801d7ff97ed6dad368dc49d55cc46.zip
Enable selectable image smoothing (bug#38394)
* lisp/doc-view.el (doc-view-insert-image): Always use smoothing in docview. * lisp/image-mode.el (image-transform-smoothing): New variable. (image-mode-map): Add smoothing binding. (image-transform-properties): Apply smoothing when requested. (image-transform-set-smoothing): New function. (image-transform-reset): Reset smoothing. * src/image.c (image_set_transform): Use new :transform-smoothing attribute. (syms_of_image): Add :transform-smoothing attribute. * doc/lispref/display.texi (Image Descriptors): Document new :transform-smoothing property.
-rw-r--r--doc/lispref/display.texi11
-rw-r--r--etc/NEWS10
-rw-r--r--lisp/doc-view.el2
-rw-r--r--lisp/image-mode.el20
-rw-r--r--src/image.c16
5 files changed, 52 insertions, 7 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 131ad2d9c87..3d91ed27642 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -5392,6 +5392,17 @@ are supported, unless the image type is @code{imagemagick}. Positive
5392values rotate clockwise, negative values counter-clockwise. Rotation 5392values rotate clockwise, negative values counter-clockwise. Rotation
5393is performed after scaling and cropping. 5393is performed after scaling and cropping.
5394 5394
5395@item :transform-smoothing @var{smooth}
5396When @code{t} any image transform will have smoothing applied, and if
5397@code{nil} no smoothing will be applied. The exact algorithm used
5398will be platform dependent, but should be equivalent to bilinear
5399filtering. Disabling smoothing will use a nearest neighbour
5400algorithm.
5401
5402The default, if this property is not specified, will be for
5403down-scaling to apply smoothing, and up-scaling to not apply
5404smoothing.
5405
5395@item :index @var{frame} 5406@item :index @var{frame}
5396@xref{Multi-Frame Images}. 5407@xref{Multi-Frame Images}.
5397 5408
diff --git a/etc/NEWS b/etc/NEWS
index b48f7c36167..ac092675b4d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1473,6 +1473,16 @@ To load images with the default frame colors use the ':foreground' and
1473This change only affects image types that support foreground and 1473This change only affects image types that support foreground and
1474background colors or transparency, such as xbm, pbm, svg, png and gif. 1474background colors or transparency, such as xbm, pbm, svg, png and gif.
1475 1475
1476+++
1477*** Image smoothing can now be explicitly enabled or disabled.
1478Smoothing applies a bilinear filter while scaling or rotating an image
1479to prevent aliasing and other unwanted effects. The new image
1480property ':transform-smoothing' can be set to t to enable smoothing
1481and nil to disable smoothing.
1482
1483The default behaviour of smoothing on down-scaling and not smoothing
1484on up-scaling remains unchanged.
1485
1476** EWW 1486** EWW
1477 1487
1478+++ 1488+++
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index f6fcfae453e..cef09009d95 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1439,6 +1439,8 @@ ARGS is a list of image descriptors."
1439 (apply #'create-image file doc-view--image-type nil args) 1439 (apply #'create-image file doc-view--image-type nil args)
1440 (unless (member :width args) 1440 (unless (member :width args)
1441 (setq args `(,@args :width ,doc-view-image-width))) 1441 (setq args `(,@args :width ,doc-view-image-width)))
1442 (unless (member :transform-smoothing args)
1443 (setq args `(,@args :transform-smoothing t)))
1442 (apply #'create-image file doc-view--image-type nil args)))) 1444 (apply #'create-image file doc-view--image-type nil args))))
1443 (slice (doc-view-current-slice)) 1445 (slice (doc-view-current-slice))
1444 (img-width (and image (car (image-size image)))) 1446 (img-width (and image (car (image-size image))))
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 7384abf3b23..8b61aa7e73f 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -95,6 +95,9 @@ Its value should be one of the following:
95(defvar-local image-transform-rotation 0.0 95(defvar-local image-transform-rotation 0.0
96 "Rotation angle for the image in the current Image mode buffer.") 96 "Rotation angle for the image in the current Image mode buffer.")
97 97
98(defvar-local image-transform-smoothing nil
99 "Whether to use transform smoothing.")
100
98(defvar image-transform-right-angle-fudge 0.0001 101(defvar image-transform-right-angle-fudge 0.0001
99 "Snap distance to a multiple of a right angle. 102 "Snap distance to a multiple of a right angle.
100There's no deep theory behind the default value, it should just 103There's no deep theory behind the default value, it should just
@@ -457,6 +460,7 @@ call."
457 (define-key map "sb" 'image-transform-fit-both) 460 (define-key map "sb" 'image-transform-fit-both)
458 (define-key map "ss" 'image-transform-set-scale) 461 (define-key map "ss" 'image-transform-set-scale)
459 (define-key map "sr" 'image-transform-set-rotation) 462 (define-key map "sr" 'image-transform-set-rotation)
463 (define-key map "sm" 'image-transform-set-smoothing)
460 (define-key map "so" 'image-transform-original) 464 (define-key map "so" 'image-transform-original)
461 (define-key map "s0" 'image-transform-reset) 465 (define-key map "s0" 'image-transform-reset)
462 466
@@ -523,6 +527,8 @@ call."
523 :help "Rotate the image"] 527 :help "Rotate the image"]
524 ["Set Rotation..." image-transform-set-rotation 528 ["Set Rotation..." image-transform-set-rotation
525 :help "Set rotation angle of the image"] 529 :help "Set rotation angle of the image"]
530 ["Set Smoothing..." image-transform-set-smoothing
531 :help "Toggle smoothing"]
526 ["Original Size" image-transform-original 532 ["Original Size" image-transform-original
527 :help "Reset image to actual size"] 533 :help "Reset image to actual size"]
528 ["Reset to Default Size" image-transform-reset 534 ["Reset to Default Size" image-transform-reset
@@ -1474,7 +1480,10 @@ return value is suitable for appending to an image spec."
1474 ,@(when (cdr resized) 1480 ,@(when (cdr resized)
1475 (list :height (cdr resized))) 1481 (list :height (cdr resized)))
1476 ,@(unless (= 0.0 image-transform-rotation) 1482 ,@(unless (= 0.0 image-transform-rotation)
1477 (list :rotation image-transform-rotation)))))) 1483 (list :rotation image-transform-rotation))
1484 ,@(when image-transform-smoothing
1485 (list :transform-smoothing
1486 (string= image-transform-smoothing "smooth")))))))
1478 1487
1479(defun image-transform-set-scale (scale) 1488(defun image-transform-set-scale (scale)
1480 "Prompt for a number, and resize the current image by that amount." 1489 "Prompt for a number, and resize the current image by that amount."
@@ -1507,6 +1516,12 @@ ROTATION should be in degrees."
1507 (setq image-transform-rotation (float (mod rotation 360))) 1516 (setq image-transform-rotation (float (mod rotation 360)))
1508 (image-toggle-display-image)) 1517 (image-toggle-display-image))
1509 1518
1519(defun image-transform-set-smoothing (smoothing)
1520 (interactive (list (completing-read "Smoothing: "
1521 '("none" "smooth") nil t)))
1522 (setq image-transform-smoothing smoothing)
1523 (image-toggle-display-image))
1524
1510(defun image-transform-original () 1525(defun image-transform-original ()
1511 "Display the current image with the original (actual) size and rotation." 1526 "Display the current image with the original (actual) size and rotation."
1512 (interactive) 1527 (interactive)
@@ -1519,7 +1534,8 @@ ROTATION should be in degrees."
1519 (interactive) 1534 (interactive)
1520 (setq image-transform-resize image-auto-resize 1535 (setq image-transform-resize image-auto-resize
1521 image-transform-rotation 0.0 1536 image-transform-rotation 0.0
1522 image-transform-scale 1) 1537 image-transform-scale 1
1538 image-transform-smoothing nil)
1523 (image-toggle-display-image)) 1539 (image-toggle-display-image))
1524 1540
1525(provide 'image-mode) 1541(provide 'image-mode)
diff --git a/src/image.c b/src/image.c
index 8137dbea8d7..95ae573354d 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2230,7 +2230,12 @@ image_set_transform (struct frame *f, struct image *img)
2230 operations to use a blended filter, to avoid aliasing and the like. 2230 operations to use a blended filter, to avoid aliasing and the like.
2231 2231
2232 TODO: implement for Windows. */ 2232 TODO: implement for Windows. */
2233 bool scale_down = (width < img->width) || (height < img->height); 2233 bool smoothing;
2234 Lisp_Object s = image_spec_value (img->spec, QCtransform_smoothing, NULL);
2235 if (!s)
2236 smoothing = (width < img->width) || (height < img->height);
2237 else
2238 smoothing = !NILP (s);
2234# endif 2239# endif
2235 2240
2236 /* Perform scale transformation. */ 2241 /* Perform scale transformation. */
@@ -2344,13 +2349,13 @@ image_set_transform (struct frame *f, struct image *img)
2344 /* Under NS the transform is applied to the drawing surface at 2349 /* Under NS the transform is applied to the drawing surface at
2345 drawing time, so store it for later. */ 2350 drawing time, so store it for later. */
2346 ns_image_set_transform (img->pixmap, matrix); 2351 ns_image_set_transform (img->pixmap, matrix);
2347 ns_image_set_smoothing (img->pixmap, scale_down); 2352 ns_image_set_smoothing (img->pixmap, smoothing);
2348# elif defined USE_CAIRO 2353# elif defined USE_CAIRO
2349 cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0], 2354 cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0],
2350 matrix[1][1], matrix[2][0], matrix[2][1]}; 2355 matrix[1][1], matrix[2][0], matrix[2][1]};
2351 cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0); 2356 cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0);
2352 cairo_pattern_set_matrix (pattern, &cr_matrix); 2357 cairo_pattern_set_matrix (pattern, &cr_matrix);
2353 cairo_pattern_set_filter (pattern, scale_down 2358 cairo_pattern_set_filter (pattern, smoothing
2354 ? CAIRO_FILTER_BEST : CAIRO_FILTER_NEAREST); 2359 ? CAIRO_FILTER_BEST : CAIRO_FILTER_NEAREST);
2355 /* Dummy solid color pattern just to record pattern matrix. */ 2360 /* Dummy solid color pattern just to record pattern matrix. */
2356 img->cr_data = pattern; 2361 img->cr_data = pattern;
@@ -2369,13 +2374,13 @@ image_set_transform (struct frame *f, struct image *img)
2369 XDoubleToFixed (matrix[2][2])}}}; 2374 XDoubleToFixed (matrix[2][2])}}};
2370 2375
2371 XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, 2376 XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture,
2372 scale_down ? FilterBest : FilterNearest, 0, 0); 2377 smoothing ? FilterBest : FilterNearest, 0, 0);
2373 XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat); 2378 XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
2374 2379
2375 if (img->mask_picture) 2380 if (img->mask_picture)
2376 { 2381 {
2377 XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture, 2382 XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture,
2378 scale_down ? FilterBest : FilterNearest, 0, 0); 2383 smoothing ? FilterBest : FilterNearest, 0, 0);
2379 XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture, 2384 XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture,
2380 &tmat); 2385 &tmat);
2381 } 2386 }
@@ -10693,6 +10698,7 @@ non-numeric, there is no explicit limit on the size of images. */);
10693 DEFSYM (QCrotation, ":rotation"); 10698 DEFSYM (QCrotation, ":rotation");
10694 DEFSYM (QCmatrix, ":matrix"); 10699 DEFSYM (QCmatrix, ":matrix");
10695 DEFSYM (QCscale, ":scale"); 10700 DEFSYM (QCscale, ":scale");
10701 DEFSYM (QCtransform_smoothing, ":transform-smoothing");
10696 DEFSYM (QCcolor_adjustment, ":color-adjustment"); 10702 DEFSYM (QCcolor_adjustment, ":color-adjustment");
10697 DEFSYM (QCmask, ":mask"); 10703 DEFSYM (QCmask, ":mask");
10698 10704