From 5dff53f5da4f17d74a0ad2cd7ec0a736aa5111f7 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 12 Mar 2021 02:37:10 +0100 Subject: [PATCH] Add a new `image-transform-smoothing' user option * doc/lispref/display.texi (Image Descriptors): Document it. * lisp/image.el (image-transform-smoothing): New user option. (create-image): Use it. (image--default-smoothing): New function. --- doc/lispref/display.texi | 9 +++++-- etc/NEWS | 6 +++++ lisp/image.el | 51 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 9723376de91..f003d524272 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5399,8 +5399,13 @@ is platform dependent, but should be equivalent to bilinear filtering. Disabling smoothing will use the nearest neighbor algorithm. -The default, if this property is not specified, is for down-scaling to -apply smoothing, and for up-scaling to not apply smoothing. +If this property is not specified, @code{create-image} will use the +@code{image-transform-smoothing} user option to say whether scaling +should be done or not. This option can be @code{nil} (no smoothing), +@code{t} (use smoothing) or a predicate function that's called with +the image object as the only parameter, and should return either +@code{nil} or @code{t}. The default is for down-scaling to apply +smoothing, and for large up-scaling to not apply smoothing. @item :index @var{frame} @xref{Multi-Frame Images}. diff --git a/etc/NEWS b/etc/NEWS index 4b8700a01cc..fa8784db59c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1483,6 +1483,12 @@ and nil to disable smoothing. The default behaviour of smoothing on down-scaling and not smoothing on up-scaling remains unchanged. ++++ +*** New user option 'image-transform-smoothing'. +This controls whether to use smoothing or not for an image. Values +include nil (no smoothing), t (do smoothing) or a predicate function +that's called with the image object and should return nil/t. + ** EWW +++ diff --git a/lisp/image.el b/lisp/image.el index 6955a90de77..4ede1fbf375 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -141,6 +141,18 @@ based on the font pixel size." (const :tag "Automatically compute" auto)) :version "26.1") +(defcustom image-transform-smoothing #'image--default-smoothing + "Whether to do smoothing when applying transforms to images. +Common transforms are rescaling and rotation. + +Valid values are nil (no smoothing), t (smoothing) or a predicate +function that is called with the image specification and should return +either nil or non-nil." + :type '(choice (const :tag "Do smoothing" t) + (const :tag "No smoothing" nil) + function) + :version "28.1") + (defcustom image-use-external-converter nil "If non-nil, `create-image' will use external converters for exotic formats. Emacs handles most of the common image formats (SVG, JPEG, PNG, GIF @@ -485,11 +497,40 @@ Image file names that are not absolute are searched for in the type 'png data-p t))) (when (image-type-available-p type) - (append (list 'image :type type (if data-p :data :file) file-or-data) - (and (not (plist-get props :scale)) - (list :scale - (image-compute-scaling-factor image-scaling-factor))) - props))) + (let ((image + (append (list 'image :type type (if data-p :data :file) + file-or-data) + (and (not (plist-get props :scale)) + ;; Add default scaling. + (list :scale + (image-compute-scaling-factor + image-scaling-factor))) + props))) + ;; Add default smoothing. + (unless (plist-member props :transform-smoothing) + (setq image (nconc image + (list :transform-smoothing + (pcase image-transform-smoothing + ('t t) + ('nil nil) + (func (funcall func image))))))) + image))) + +(defun image--default-smoothing (image) + "Say whether IMAGE should be smoothed when transformed." + (let* ((props (nthcdr 5 image)) + (scaling (plist-get props :scale)) + (rotation (plist-get props :rotation))) + (cond + ;; We always smooth when scaling down and small upwards scaling. + ((and scaling (< scaling 2)) + t) + ;; Smooth when doing non-90-degree rotation + ((and rotation + (or (not (zerop (mod rotation 1))) + (not (zerop (% (truncate rotation) 90))))) + t) + (t nil)))) (defun image--set-property (image property value) "Set PROPERTY in IMAGE to VALUE. -- 2.39.2