Skip to content

bbox images do not get placed properly when figure is saved to png or pdf #3918

Closed

Description

@breedlun

When I create a figure using bbox images, everything looks fine, but when I save the figure, the images move. Here is an example

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.image import BboxImage
from matplotlib.transforms import Bbox, TransformedBbox

#Generate the image
im = np.random.rand(10, 10) * 255.0

#Set up figure
fig = plt.figure()
ax = fig.add_axes([0.1,0.1,0.8,0.8])
ax.set_xlim(-2,24)
ax.set_ylim(0,10)

#Create image that transforms automatically
bbox1 = Bbox.from_extents([0,0,10,10])
trans_bbox1 = TransformedBbox(bbox1, ax.transData)
bbox_image1 = BboxImage(trans_bbox1)
bbox_image1.set_data(im)
ax.add_image(bbox_image1)

#Create image that does not transform
bbox2 = Bbox.from_extents([12,0,22,10])
trans_bbox2 = bbox2.transformed(ax.transData)
bbox_image2 = BboxImage(trans_bbox2)
bbox_image2.set_data(im)
ax.add_image(bbox_image2)

#Save the result
fig.savefig('png_test.png')
fig.savefig('pdf_test.pdf')

If I take a screenshot of the figure window, it looks like this
screenshot
which is what I expect. However, when I look at the 'png_test.png', the second image that did not use the TransformedBbox moves, as shown below
png_test
In the pdf, both images move, as shown below
pdf_test

In case it matters, I am using the Qt4Agg interactive backend with the Spyder IDE. My matplotlib version is 1.4.0.

Activity

  1. tacaswell commented on Dec 13, 2014

    @tacaswell
    Member

    See the discussion in #2831.

    I think the issue is that you are specifying the bounding box locations in display units. The transformation from data -> display takes into account things like the final dpi (which is one of the main reasons that the transform system exists).

    In particular #2831 (comment) has a work-around that should solve your problem short of a complete overhaul of how the rendering backends work.

  2. added this to the milestone on Dec 13, 2014
  3. breedlun commented on Dec 14, 2014

    @breedlun
    ContributorAuthor

    @tacaswell Thanks for the suggestion. The figure dpi and the savefig dpi were different and that fixed the png issue. (I have never understood why the figure dpi and savefig dpi do not default to the same values.) I tried to incorporate leejjoon's #2831 (comment) to fix the pdf problem, but I am not sure how to do it without an annotation. Doesn't the TransformedBbox that I used above do the same thing anyways?

    The problem I am seeing might be the same as #2831, but I believe there is something different here. Check out the following example,

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.image import BboxImage
    from matplotlib.transforms import Bbox, TransformedBbox
    import matplotlib as mpl
    mpl.rcParams['savefig.dpi'] = mpl.rcParams['figure.dpi']
    
    im = np.random.rand(10, 10) * 255.0
    
    #Set up figure
    fig = plt.figure()
    ax = fig.add_axes([0.1,0.1,0.8,0.8])
    ax.set_xlim(-2,24)
    ax.set_ylim(0,10)
    
    #Create an image that transforms automatically
    bbox1 = Bbox.from_extents([0,0,10,10])
    trans_bbox1 = TransformedBbox(bbox1, ax.transData)
    bbox_image1 = BboxImage(trans_bbox1, data = im)
    ax.add_image(bbox_image1)
    #Save the result
    fig.savefig('pdf_test_with_1_image.pdf')
    
    #Add another image that transforms automatically
    bbox2 = Bbox.from_extents([12,0,22,10])
    trans_bbox2 = TransformedBbox(bbox2, ax.transData)
    bbox_image2 = BboxImage(trans_bbox2, data = im)
    ax.add_image(bbox_image2)
    #Save the result
    fig.savefig('pdf_test_with_2_images.pdf')
    

    The pdf with only one image looks correct:
    pdf_test_with_1_image
    When I add a second image, the figure window looks like this
    screenshot_with_2_images,
    but when I save it to a pdf, it looks all wrong:
    pdf_test_with_2_images
    The first image gets moved, and the second image is gone. Something happens in the pdf backend when I have two Bbox images that does not occur when I have one Bbox image.

  4. breedlun commented on Dec 16, 2014

    @breedlun
    ContributorAuthor

    @tacaswell can I ask you to take a look at my post above? I think my issue is not quite a duplicate of issue #2831. When I use TransformedBbox with one image, the PDF looks fine. When I use TransformedBbox with two images, the PDF gets messed up.

  5. WeatherGod commented on Jan 20, 2015

    @WeatherGod
    Member

    I modified your example a little bit. I flipped the second image: bbox_image2 = BboxImage(trans_bbox2, data = im[::-1]). When running this example, we see that the second image is getting placed on top of the first. So, the second image is using the first image's transform (in the file, that is). I can also verify that this problem occurs when saving the results as 'eps' files.

  6. modified the milestones: v1.4.x, on Jan 20, 2015
  7. breedlun commented on Jan 21, 2015

    @breedlun
    ContributorAuthor

    @WeatherGod, thanks for confirming the bug. It appears that, no matter where I place the two images, they both get moved to the lower left corner of the axes when the figure is saved as a pdf.

    For example, here is the matplotlib figure window:
    fig_window
    and here is an image of the pdf file:
    pdf_test_with_2_images

  8. WeatherGod commented on Jan 21, 2015

    @WeatherGod
    Member

    Oh, now that's interesting! It is as if none of the transform data is being
    utilized!
    On Jan 20, 2015 8:50 PM, "Benjamin Reedlunn" notifications@github.com
    wrote:

    @WeatherGod https://github.com/WeatherGod, thanks for confirming the
    bug. It appears that, no matter where I place the two images, they both get
    moved to the lower left corner of the axes when the figure is saved as a
    pdf.

    For example, here is the matplotlib figure window:
    [image: fig_window]
    https://cloud.githubusercontent.com/assets/4099759/5829823/f495047a-a0d4-11e4-929a-b5878ca7a7f4.png
    and here is an image of the pdf file:
    [image: pdf_test_with_2_images]
    https://cloud.githubusercontent.com/assets/4099759/5829829/0a685f18-a0d5-11e4-9f78-efae0a45c7f5.png

    —
    Reply to this email directly or view it on GitHub
    #3918 (comment)
    .

  9. tacaswell commented on Jan 21, 2015

    @tacaswell
    Member
  10. 12 remaining items

  11. modified the milestones: , on Jul 17, 2015
  12. modified the milestones: , on Oct 3, 2017
  13. github-actions commented on Mar 9, 2023

    @github-actions

    This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!

  14. tacaswell commented on Mar 9, 2023

    @tacaswell
    Member

    This now works, however I have not bisected back to when it was fixed.

  15. breedlun commented on Mar 9, 2023

    @breedlun
    ContributorAuthor

    @tacaswell how do you know this issue is resolved? When I try to run the code in my Dec 13, 2014 post, I get the following error: TypeError: 'image' must be an instance of matplotlib.image.AxesImage, not a matplotlib.image.BboxImage. I tried swapping out BboxImage for AxesImage, but that gave a different error.

  16. tacaswell commented on Mar 9, 2023

    @tacaswell
    Member

    I ran this with 3.6 when that was just a warning. Change ax.add_image -> ax.add_artist.

  17. breedlun commented on Mar 11, 2023

    @breedlun
    ContributorAuthor

    Thanks, tacaswell. Running the code in my Dec 13, 2014 post, except with ax.add_image -> ax.add_artist, allows me to confirm the issue is fixed with matplotlib 3.7. Yay! The first image moves ever so slightly when I save two images in the same set of axes, but I think it is negligible for most purposes.

  18. removed this from the future releases milestone on Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions