Menu

#493 Preserve aspect ratio of included images

None
closed-accepted
nobody
None
5
2020-12-25
2019-09-05
No

Hello,

when including a jpg or png into a plot, it is quite difficult to keep the original aspect ratio of the image, especially, if the x and y axis have different ranges and the output size is non-square. I did find a way to re-establish the correct aspect ratio, but the workaround is quite cumbersome:

set term pdfcairo color size 8.5cm,5.95cm
set xr [3210:3680]
set yr [0:6000]
# first dummy call to plot in order to establish GPVAL-variables
set out "rubbish.pdf"
plot "some.data"
set out "correct.pdf"

XRANGE = GPVAL_X_MAX-GPVAL_X_MIN
YRANGE = GPVAL_Y_MAX-GPVAL_Y_MIN
scale = 1.0e6 #or whatever size is wanted

plot "some.data", "image.png" binary filetype=png center=(3400,3000) dx=scale/(GPVAL_TERM_XSIZE*YRANGE) dy=scale/(GPVAL_TERM_YSIZE*XRANGE) w rgbalpha
!rm rubbish.pdf

Honestly, I don't understand why dx has to be divided by X-size but Y-range, and dy by X-range and Y-size, but somehow this gives correct results. (Is this a bug?)
It would be nice to have a new option like preserve_aspect_ratio that does this job and eliminates the need of dual-plotting.

Discussion

  • Ethan Merritt

    Ethan Merritt - 2019-09-05

    Is there a reason you cannot use the command set view equal xy?

     
    • Eldrad Ulthran

      Eldrad Ulthran - 2019-09-06

      Unfortunately, I fail to see any difference when using set view equal xy – I still have to set up dx and dy in the same manner as above. To be honest, I don't see how the unit length of the axis can be equal in the example given above: x covers a range of 470 on a length of 8.5cm, while y covers 6000 on a length of 5.95cm. This is determined by the data I am plotting.
      And isn't the command set view only applied to splot?

      I guess the situation will get even worse when working with logarithmic axis…

       
  • Ethan Merritt

    Ethan Merritt - 2019-09-06

    My apologies. The 2D equivalent command is set size ratio -1. This is documented somewhere but it's hard to find. Here is an example. First I create a junk png plot of known dimensions.

    set term pngcairo background "cyan" size 400,800
    set output 'tall.png'
    set border lw 4
    plot sin(x)
    exit
    

    Then I start a new session and use your example layout to read in the image.

    set term pngcairo color size 850,595
    set output 'foo.png'
    unset key
    set xr [3210:3680]
    set yr [0:6000]
    set size ratio -1
    plot (12*(x-3210)) with lines lw 6, \
        'tall.png' binary filetype=png center=(3400,3000) with rgbimage
    

    Of course this reveals that the chosen ranges on x and y may not be appropriate, but it does show that the aspect ratio of the image is preserved.

     
    • Eldrad Ulthran

      Eldrad Ulthran - 2019-09-08

      Your example shows that preserving the png aspect ratio via set size ratio -1 "destroys" the rest of the plot – your result foo.png is obviously not useful.
      The x- and y-range are determined by the dataset I am plotting, they are representing physical quantities, which is why I can't set them to be equally scaled.

      Another workaround for including non-distorted images would be via cairolatex terminal and set label '\includegraphics[scale=0.1]{image.png}' at 3400,3600, but then positioning will need lots of iterative tests.

       
      • Ethan Merritt

        Ethan Merritt - 2019-09-08

        The example I gave does show how to preserve the aspect ratio of the included png image. If that is not what you wanted, please go back and try to explain more clearly what you do want. Is it that you want to rescale the included image as well as preserving the aspect ratio? That could be done by adding qualifiers dx=scale dy=scale for whatever scaling factor you choose.

        Edit: Or is it that you don't actually care about the size of the included image, i.e. you want it shown independent of the axis scaling? Sorry if I didn't understand that from your original query. Will it be the case that you always know the exact size in pixels of the included image in advance?

         

        Last edit: Ethan Merritt 2019-09-08
        • Eldrad Ulthran

          Eldrad Ulthran - 2019-09-08

          you want it shown independent of the axis scaling?

          Exactly that is what I am asking for, I would like to "detach" the image pixels from x and y (and x2/y2), and simply place it somewhere on the graph. A scaling option like "width = 0.1 graph width" (or screen) would be nice as well.
          Here is an example of a very similar picture: https://doi.org/10.1039/c9sc01555h (Open Access)
          In Fig. 1 and 2 there are some data plotted against the axis and a small image of a molecule is included.

          Will it be the case that you always know the exact size in pixels of the included image in advance?

          Unfortunately not, in my specific case I wanted to include four images which all have slightly different sizes. I could of course just look up the sizes.

           
  • Ethan Merritt

    Ethan Merritt - 2019-09-08
     
    • Eldrad Ulthran

      Eldrad Ulthran - 2019-09-08

      Oh, apologies that I didn't find this old thread. Yeah, a completely empty multiplot with just the image on top of the "real" plot would probably be a possible workaround as well… but probably not less fiddly than my one :-)

       
  • Ethan Merritt

    Ethan Merritt - 2019-09-15

    Now in the development version as an experimental feature. Compile with -DPIXMAPS.

    gnuplot> help pixmap
    
    EXPERIMENTAL (compile with -DPIXMAPS, requires libgd)
     Syntax:
           set pixmap <index> "filename" at <position> {width <w>|size <w> <h>}
                      {front|behind} {center}
           show pixmaps
           unset pixmaps
    
     The `set pixmap` command is similar to `set object` in that it defines an
     object that will appear on subsequent plots. The rectangular array of
     red/green/blue/alpha values making up the pixmap are read from a png, jpeg, 
     or gif file.  The position and extent occupied by the pixmap in the gnuplot
     output may be specified in any coordinate system (see `coordinates`).
     The coordinates given by `at <position>` refer to the lower left
     corner of the pixmap unless keyword `center` is present.
    
     If the x-extent of the rendered pixmap is set using `width <x-extent>` the
     aspect ratio of the original image is retained and neither the aspect ratio
     nor the orientation of the pixmap changes with axis scaling or rotation.
     If both the x-extent and y-extent are given using `size <x-extent> <y-extent>`
     this overrides the original aspect ratio.
     Pixmaps are not clipped to the border of the plot.
     Examples:
            # Use a gradient as the background for all plotting
           # Both x and y will be resized to fill the entire canvas
           set pixmap 1 "gradient.png"
           set pixmap 1 at screen 0, 0 size screen 1, 1 behind
    
           # Place a logo at the lower right of each page plotted
           set pixmap 2 "logo.jpg"
           set pixmap 2 at screen 0.95, 0 width screen 0.05 behind
    
           # Place a small image at some 3D coordinate
           # It will move as if attached to the surface being plotted
           # but will always face forward and remain upright
           set pixmap 3 "image.png" at my_x, my_y, f(my_x,my_y) width screen .05
           splot f(x,y)
    
     
    • Eldrad Ulthran

      Eldrad Ulthran - 2019-09-16

      Unfortunately I can't compile it – configure tells that it doesn't know the option "-DPIXMAPS" (the only file containing this word is gnuplot.doc)… am I doing something wrong?

       
      • Ethan Merritt

        Ethan Merritt - 2019-09-16

        Ah, sorry for the confusion. I didn't make a configuration option for it. You can either add -DPIXMAPS to the standard compiler options:

        export CFLAGS="$CFLAGS -DPIXMAPS"
        ./configure
        

        Or run your normal configuration procedure and then add a line
        #define PIXMAPS
        at the end of ./config.h

        It should be considered "experimental" at this stage. After testing and feedback I'll either remove the conditional flags or make it a configuration option.

         
  • Ethan Merritt

    Ethan Merritt - 2019-09-15
    • status: open --> pending-accepted
    • Group: -->
     
  • Eldrad Ulthran

    Eldrad Ulthran - 2019-09-18

    Thank you very much, I used this new feature to create some images for a conference poster that I'm going to present soon. While testing two small possible improvements came to my mind:

    • width <w> autoscales the height, and it would be nice to have the opposite option height <h> that autoscales the width. Maybe it would be possible to merge the three options size, width and height to a single size option, where an asterisk or some other special character marks autoscaling: scale <w>,* would be the same as width <w> is now, and scale *,<h> would be the height.
    • a nice gimmick would be rotation of the image, if implementation is feasible. Of course one could resort to latex output and \includegraphics instead.
     
  • Ethan Merritt

    Ethan Merritt - 2020-12-25
    • status: pending-accepted --> closed-accepted
     

Log in to post a comment.