Every so often I get offered a job where a small company has its help docs in Word, full of admin-panel screenshots, and wants me to turn them into a static help page. People who write those docs often crop the customer details off a screenshot before pasting it in. Before I'd quote a job like that, I wanted to know whether the crop survives the trip to HTML, because if it doesn't, somebody's customer data ends up on a host I pay for. I don't have Word on this Mac, so I wrote a test .docx by hand following the OOXML structure, with seven picture cases. The screenshot in it comes from an order admin page I built myself, and every recipient, phone number, address and payment ID on it is a placeholder. One case crops 35.484% off the bottom of that screenshot to hide the shipping card.
A .docx is a zip, and the crop never touches the picture. The file in word/media/ is the whole original, and the crop is one a:srcRect line in document.xml, with each edge in thousandths of a percent. Listing the crops takes one pipe.
unzip -p seven-cases.docx word/document.xml | grep -o '<a:srcRect [^/]*/>' | sort | uniq -c
# 2 <a:srcRect l="0" t="0" r="0" b="35484"/>
# 1 <a:srcRect l="15000" t="15000" r="15000" b="15000"/>
# 1 <a:srcRect l="30000" t="20000" r="20000" b="25000"/>
To be fair to Word, I put the full images in that file myself, so my sample proves nothing about what Word saves. Microsoft's support page on shrinking picture sizes does offer a "Delete cropped areas of pictures" option on macOS, and that option only makes sense if the cropped part stays until you tick it. I couldn't check what Word does by default on save.
The left side is what a reader of the document sees. The right side is what the .docx actually carries, and the red box is the part someone meant to remove.
mammoth.js 1.13.0 was the easy one to judge. It ignores the crop, so the shipping card shows up right there on the converted page.
For a browser-side converter I used ImgIng (https://imging.ai/) and its DOCX to HTML workbench, on the same seven-case sample in a Chromium 149 open-source build. It read the crop content and the display size correctly, and the conversion made 0 non-GET requests. It also showed no warning about crops, and the bottom-cropped screenshot moved up 70.4 px over the heading line above it. The bigger issue for me was inside the exported file. It came to 9,665,338 bytes, and all seven inline images were the untouched originals, byte for byte the same as the media in the .docx. Pulling the screenshot back out of the single-case export took one more line.
grep -o 'data:image/png;base64,[^")]*' screenshot-case.html | head -1 | cut -d, -f2 | base64 -d > inline.png && sips -g pixelWidth -g pixelHeight inline.png
# pixelWidth: 1800
# pixelHeight: 1240
That is the full 1800×1240 screenshot, shipping card and placeholder phone number included, and it's what "Save image as" would hand anyone visiting the page. This is the part I think people in my line of work underestimate. A client reviews a converted page by looking at it, and the page can look right while the bytes still carry everything. Any CSS fix only hides the cut-off area, and the bytes go out with the page anyway.
So the fix has to happen before conversion. Baking the crop in, meaning cutting each media file to its srcRect and then clearing the setting, took the sample from 7,234,550 to 5,714,763 bytes, 21.0% smaller. The screenshot's media became 1800×800, the 70.4 px shift dropped to 0.4 px, and none of the three converters left a shipping card to find. As a side bonus for someone paying for bandwidth, the full ImgIng export went from 9.22 MB to 7.28 MB. Honestly, for a handful of screenshots I'd skip the script and ask the client for fresh screenshots without the customer data. That costs me one email and no script.
I haven't tested Word itself, WPS, LibreOffice or pandoc, I only checked ImgIng's export in Chromium 149, and floating images weren't in the sample. Whether Word removes cropped areas on its own in some versions, I still don't know. For now, if a job like this comes in, I'd run that first pipe on the client's files before quoting. Any line it prints goes into the quote as either baking or a fresh screenshot.

Top comments (0)