GNU bug report logs -
#69602
29.1; Image :map should adjust with :scale and :rotation
Previous Next
Full log
Message #23 received at 69602 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Eli Zaretskii <eliz <at> gnu.org> writes:
>> From: Joseph Turner <joseph <at> breatheoutbreathe.in>
>> Cc: 69602 <at> debbugs.gnu.org, stephen.berman <at> gmx.net, juri <at> linkov.net
>> Date: Thu, 07 Mar 2024 00:08:57 -0800
>>
>> Eli Zaretskii <eliz <at> gnu.org> writes:
> I hoped :map allows its value to be a form that is evaluated when the
> image is being processed, in which case that form could call
> image-compute-scaling-factor when it produces the coordinates.
Thanks! Would this require a change in C?
> If that doesn't work, then...
>
>> When creating an image, we set its :map property according to the return
>> value of `image-compute-scaling-factor'. Once the image is inserted into
>> the buffer, the user may run `image-increase-size' or `image-rotate',
>> which changes how the image is displayed but not its :map.
>>
>> Now, we need to rerun `image-compute-scaling-factor' and recompute :map.
What I said here is wrong. `image-compute-scaling-factor' is not
useful for recomputing :map, but `image--current-scaling' is.
>> However, there is no hook which runs after the user runs those commands,
>> so AFAICT there's no way for our code to know when to recompute :map.
>
> ...AFAIU, when an image is rescaled, we call
> image-transform-properties to produce the updated image properties.
There are two ways to rescale an image, `image-transform-properties'
(defined in image-mode.el; works only on file-backed images in
image-mode) and `image--change-size' (defined in image.el; works
on any image object in any mode).
For now, I'd like to focus on improving `image.el'.
> So I guess you'd like that function to recompute the coordinates in
> :map according to the transform?
>
> IOW, I don't understand why you think the problem can only be solved
> in C: AFAIK almost all of the machinery that performs image transforms
> is implemented in Lisp, and each time an image is rescaled, we
> basically re-process the image descriptor anew.
The attached patch adds two hooks in `image.el' which allow packages to
recompute an image's map after it's rescaled or rotated.
The following demonstrates `image-after-change-size-hooks':
(progn
(defun image--scale-map (map factor)
"Scale MAP by FACTOR, destructively modifying it."
(when (and factor (/= 1 factor))
(pcase-dolist (`(,`(,type . ,coords) ,_id ,_plist) map)
(pcase-exhaustive type
('rect
(setf (caar coords) (round (* (caar coords) factor)))
(setf (cdar coords) (round (* (cdar coords) factor)))
(setf (cadr coords) (round (* (cadr coords) factor)))
(setf (cddr coords) (round (* (cddr coords) factor))))
('circle
(setf (caar coords) (round (* (caar coords) factor)))
(setf (cdar coords) (round (* (cdar coords) factor)))
(setf (cdr coords) (round (* (cdr coords) factor))))
('poly
(dotimes (i (length coords))
(aset coords i
(round (* (aref coords i) factor))))))))
map)
(defun image-rescale-image-map ()
"Recalculate and set :map property of image at point.
Assumes that image has an :unscaled-map property."
(when-let* ((image (image--get-imagemagick-and-warn))
(unscaled-image (image--image-without-parameters image))
(unscaled-map (image-property image :unscaled-map))
(scale (image--current-scaling image unscaled-image)))
(setf (image-property image :map)
(image--scale-map (copy-tree unscaled-map t) scale))))
(with-current-buffer (get-buffer-create "*image-properties-test*")
(let* ((svg-string "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<!-- Generated by graphviz version 2.43.0 (0)\n -->\n<!-- Title: orggraphview Pages: 1 -->\n<svg width=\"128pt\" height=\"128pt\"\n viewBox=\"0.00 0.00 127.59 127.59\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 123.59)\">\n<title>orggraphview</title>\n<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-123.59 123.59,-123.59 123.59,4 -4,4\"/>\n<!-- a -->\n<g id=\"node1\" class=\"node\">\n<title>a</title>\n<g id=\"a_node1\"><a xlink:href=\"1\" xlink:title=\"Hover me!\">\n<ellipse fill=\"none\" stroke=\"black\" cx=\"59.79\" cy=\"-59.79\" rx=\"59.59\" ry=\"59.59\"/>\n<text text-anchor=\"middle\" x=\"59.79\" y=\"-56.09\" font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Hover me!</text>\n</a>\n</g>\n</g>\n</g>\n</svg>\n")
(scale 0.75) ; Adjust initial image scale
(unscaled-map '(((circle (85 . 85) . 80) "1" (help-echo "Surprise!"))))
(map (image--scale-map (copy-tree unscaled-map t) scale))
(image
(create-image svg-string 'svg t
:scale scale :map map :unscaled-map unscaled-map)))
(add-hook 'image-after-change-size-hooks #'image-rescale-image-map nil t)
(erase-buffer)
(insert-image image)
(goto-char (point-min))
(pop-to-buffer (current-buffer)))))
After applying the attached patch, evaluate the above form, press "i +"
and "i -" repeatedly to see the image and its map scale together.
Thanks!
Joseph
[0001-Add-image-after-change-size-hooks-image-after-rotate.patch (text/x-diff, attachment)]
This bug report was last modified 1 year and 116 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.