Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sizing Images #94

Closed
Alecat opened this issue Sep 19, 2014 · 10 comments
Closed

Sizing Images #94

Alecat opened this issue Sep 19, 2014 · 10 comments

Comments

@Alecat
Copy link

Alecat commented Sep 19, 2014

Hi,
I am working on a document generator for files that will eventually be imported into Adobe Indesign.
Picture scaling works correctly for images when viewed in Word/OpenOffice. However when imported into InDesign the images appear at their native resolution instead.

After doing some digging I found that the issue was with the sizing of the pic:spPr element. InDesign uses these to render the image, rather than the dimensions of the Inline object's extents.

I am not sure if this is an error with python-docx or Adobe's parsing.

I was able to fix my issue by passing width and height through all add_picture/new_picture methods and then relocating the picture scaling logic (from Run's add_picture method) into InlineShape's new_picture method. Both the picture and the inlineshape can then be updated with the correct size information and the file now imports correctly into InDesign.

Does this sound like an appropriate fix? Alternatively, is it possible to access the Picture object inside the InlineShape? That would then make it be possible to modify its dimensions in add_picture.

I have not tested this extensively, nor do I pretend to really understand the docx spec. I don't know if I may have just broken other things but I can submit a pull request with changes if you want to see more clearly in code what problem I was attempting to solve.

@scanny
Copy link
Contributor

scanny commented Sep 19, 2014

Hi @Alecat,

I think the XML below illustrates what you're describing. The size in <wp:extent> is smaller than the one in
pic:spPr/a:xfrm/a:ext. The two are different because they are distinct sizes. The one in wp:extent is the displayed size (scaled down to about 20% of original) whereas the one in a:ext is the "Original Size". You can see the two displayed in inches on the "Format Picture" dialog on the "Size" panel.

I suppose I would consider this improper interpretation of the file format by InDesign. The original size is a legitimate measure and in fact represents the actual size recorded in the embedded image file (300-dpi.jpg in this case). In order to adjust the values in a:ext properly, the source image file would need to be resampled to match.

If you import a large picture into Word and then use the handles to scale it down to half-size or so, as one commonly does, does InDesign get its size right?

--Steve

<w:p>
  <w:r>
    <w:rPr>
      <w:noProof/>
    </w:rPr>
    <w:drawing>
      <wp:inline distT="0" distB="0" distL="0" distR="0" wp14:anchorId="0745B591" wp14:editId="18533FCA">
        <wp:extent cx="914400" cy="1177047"/>
        <wp:effectExtent l="0" t="0" r="0" b="0"/>
        <wp:docPr id="3" name="Picture 3"/>
        <wp:cNvGraphicFramePr>
          <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
        </wp:cNvGraphicFramePr>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
              <pic:nvPicPr>
                <pic:cNvPr id="0" name="300-dpi.jpg"/>
                <pic:cNvPicPr/>
              </pic:nvPicPr>
              <pic:blipFill>
                <a:blip r:embed="rId9"/>
                <a:stretch>
                  <a:fillRect/>
                </a:stretch>
              </pic:blipFill>
              <pic:spPr>
                <a:xfrm>
                  <a:off x="0" y="0"/>
                  <a:ext cx="4584192" cy="5900928"/>
                </a:xfrm>
                <a:prstGeom prst="rect">
                  <a:avLst/>
                </a:prstGeom>
              </pic:spPr>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:inline>
    </w:drawing>
  </w:r>
</w:p>

@Alecat
Copy link
Author

Alecat commented Sep 19, 2014

Hi Steve, thanks for your reply. Here is the XML generated by unmodified python-docx. In this example I am attempting to render a smallish 300dpi image (135px x 130px) with a much larger 4-inch width.

<w:p>
  <w:r>
    <w:drawing>
      <wp:inline xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
                 xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
        <wp:extent cx="3657600" cy="3522133"/>
        <wp:docPr id="1" name="Picture 1"/>
        <wp:cNvGraphicFramePr>
          <a:graphicFrameLocks noChangeAspect="1"/>
        </wp:cNvGraphicFramePr>
        <a:graphic>
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic>
              <pic:nvPicPr>
                <pic:cNvPr id="0" name="badges2.PNG"/>
                <pic:cNvPicPr/>
              </pic:nvPicPr>
              <pic:blipFill>
                <a:blip r:embed="rId9"/>
                <a:stretch>
                  <a:fillRect/>
                </a:stretch>
              </pic:blipFill>
              <pic:spPr>
                <a:xfrm>
                  <a:off x="0" y="0"/>
                  <a:ext cx="411480" cy="396240"/>
                </a:xfrm>
                <a:prstGeom prst="rect"/>
              </pic:spPr>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:inline>
    </w:drawing>
  </w:r>
</w:p>

Scaling the image in Word results in it being correctly scaled when imported into InDesign. Similarly taking a python-docx generated file and re-saving it in OpenOffice fixes the scaling for import into InDesign.

I experienced the problems when attempting to both upscale and downscale images. Manually created files worked correctly in both upscaling and downscaling cases.

@scanny
Copy link
Contributor

scanny commented Sep 19, 2014

Hmm, interesting. Looks like we didn't completely correctly reverse-engineer Word's behavior when it comes to scaling images. I just tried a manually scaled image and the wp:extent and a:ext numbers do match. It still shows the original size in the format picture dialog, so I'm betting it's getting those directly from the embedded image file.

So I'm thinking the fix to update both the wp:extent and a:ext sizes on assignment to InlineShape.width and InlineShape.height.

It's going to need to be a little more sophisticated than that unfortunately, because wp:inline can contain other things besides a Picture and those would have different ways to change their size, or perhaps not keep a size of their own at all, as is the case with a Chart I believe. I suppose it would be enough for now to just make sure the enclosed object was a picture before trying to change its a:ext attributes. I think the uri in a:graphicData (ending in '.../2006/picture') is the decisive evidence of the shape type.

@Alecat
Copy link
Author

Alecat commented Sep 22, 2014

Hi Steve, are the charts etc. also added as pictures? Otherwise I think the changes I made to add_picture/new_picture to do the size calculations at the point of adding the InlineShape will work. I can submit a pull request with those changes if you like.

@scanny
Copy link
Contributor

scanny commented Sep 22, 2014

No, charts are native. They should work fine as is, once we add support for them that is :)

A pull request would be handy, thanks :)

@toplayer
Copy link

I believe I have a similar problem. I have wrote a program for work that creates a report in MS Word using python-docx. I am adding pictures, which I size to my liking. ypically the picture I add are of higher resolution. Everything looks great...until I print. The pictures I added using python-docx have "un-sized" themselves. My document looks great on the screen and even in the print preview. This problem can also be seen if printing to PDF. Using the demo from python-docx, which exhibits the problem as well...

from docx import Document
from docx.shared import Inches

document = Document()
document.add_picture('picture.jpg', width=Inches(4.9))
document.save('demo.docx')

@scanny scanny added the image label Feb 13, 2015
scanny pushed a commit that referenced this issue Feb 14, 2015
Change the dimensions in both `wp:inline/wp:extent` and
`pic:pic/pic:spPr/a:xfrm` when setting width or height of a picture.
@scanny
Copy link
Contributor

scanny commented Feb 14, 2015

Hi @Alecat, @toplayer, finally found some time to address this.

I just pushed a temporary branch fix/94 up to the repo here:
https://github.com/python-openxml/python-docx/commits/fix/94

Could you give it a try and confirm it fixes the problems you were having with scaled images during print etc.?

If you look at the commit you'll see the scope of the change is much more modest than your PR @Alecat, but I believe it gets the job done and has the advantage that it also works if one changes the size of the inline picture after it's created, for example to scale a picture in an existing document. e7bdc57

I'm inclined to do some refactoring along the lines of your PR @Alecat but wanted to get this problem confirmed fixed before digging into that.

Let me know after you've had a chance to test and I'll prepare a point release to get it into the main distribution.

scanny pushed a commit that referenced this issue Feb 14, 2015
Change the dimensions in both `wp:inline/wp:extent` and
`pic:pic/pic:spPr/a:xfrm` when setting width or height of a picture.
@Alecat
Copy link
Author

Alecat commented Feb 14, 2015

Hi Steve, thanks for making that change. Sorry for not addressing the PR
sooner, I've been out of reliable internet access lately.

I'll see if I can grab the branch and test it soon.

On Sat, Feb 14, 2015 at 7:01 PM, Steve Canny notifications@github.com
wrote:

Hi @Alecat https://github.com/Alecat, @toplayer
https://github.com/toplayer, finally found some time to address this.

I just pushed a temporary branch fix/94 up to the repo here:
https://github.com/python-openxml/python-docx/commits/fix/94

Could you give it a try and confirm it fixes the problems you were having
with scaled images during print etc.?

If you look at the commit you'll see the scope of the change is much more
modest than your PR @Alecat https://github.com/Alecat, but I believe it
gets the job done and has the advantage that it also works if one changes
the size of the inline picture after it's created, for example to scale a
picture in an existing document. e0d928d
e0d928d

I'm inclined to do some refactoring along the lines of your PR @Alecat
https://github.com/Alecat but wanted to get this problem confirmed
fixed before digging into that.

Let me know after you've had a chance to test and I'll prepare a point
release to get it into the main distribution.


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

@Alecat
Copy link
Author

Alecat commented Feb 15, 2015

Hi Steve, I've had a play and I think the issues are resolved by your
changes. Thanks for checking it out.

On Saturday, February 14, 2015, Alethea Lim alecat@gmail.com wrote:

Hi Steve, thanks for making that change. Sorry for not addressing the PR
sooner, I've been out of reliable internet access lately.

I'll see if I can grab the branch and test it soon.

On Sat, Feb 14, 2015 at 7:01 PM, Steve Canny <notifications@github.com
javascript:_e(%7B%7D,'cvml','notifications@github.com');> wrote:

Hi @Alecat https://github.com/Alecat, @toplayer
https://github.com/toplayer, finally found some time to address this.

I just pushed a temporary branch fix/94 up to the repo here:
https://github.com/python-openxml/python-docx/commits/fix/94

Could you give it a try and confirm it fixes the problems you were having
with scaled images during print etc.?

If you look at the commit you'll see the scope of the change is much more
modest than your PR @Alecat https://github.com/Alecat, but I believe
it gets the job done and has the advantage that it also works if one
changes the size of the inline picture after it's created, for example to
scale a picture in an existing document. e0d928d
e0d928d

I'm inclined to do some refactoring along the lines of your PR @Alecat
https://github.com/Alecat but wanted to get this problem confirmed
fixed before digging into that.

Let me know after you've had a chance to test and I'll prepare a point
release to get it into the main distribution.


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

@scanny scanny closed this as completed in 395b48f Feb 16, 2015
@scanny
Copy link
Contributor

scanny commented Feb 16, 2015

This is fixed in version 0.8.2 released Feb 16, 2015.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants