5

Bug introduced in 11.2 or earlier and persisting through 13.0.0 [CASE:4895073]


The following code produces a 10x10 grid of numbers, each in a 20x6 mm cell.

mm = 72/25.4;
{bx, by} = {20 mm, 6 mm};

label[num_] := Graphics[ Text[IntegerString[num, 10, 5], {10 mm, 3 mm}], ImageSize -> {bx, by}, PlotRange -> {{0, bx}, {0, by}}, PlotRangePadding -> None]

labels = label /@ Range[100]; GraphicsGrid[Partition[labels, 10], Spacings -> 0]

Export["number.pdf", %]

When exporting to PDF, irrespective of the number of cells (even for a single cell without GraphicsGrid), the PDF dimensions are not exact.

The exact dimensions should be 10x20 mm wide and 10x6 mm long, i.e. 200 x 60 mm.

However, the actual output has dimensions of 204.3 x 64.6 mm.

How to resolve this ? Mathematica version is 11.2 running on Win 10 x64.

Of course, I could just add an approximate factor of ~0.979 in the mm definition, but that way it won't be really exact and will look ugly when merged with other graphics (in another program).

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
tobalt
  • 357
  • 1
  • 6
  • 1
    You have luck setting SetOptions[$FrontEndSession, PrintingStyleEnvironment -> "Working"]. – chuy Jan 12 '22 at 21:29
  • 1
    That should be might have luck. In any case see: https://mathematica.stackexchange.com/questions/18393/what-are-the-most-common-pitfalls-awaiting-new-users/137746#137746 – chuy Jan 12 '22 at 21:35
  • @chuy Thank you for mentioning this! Despite the fact that I myself am the author of that answer, this important point completely slipped my mind... – Alexey Popkov Jan 13 '22 at 08:06

2 Answers2

4

First of all, as chuy correctly points out in the comments, you should set PrintingStyleEnvironment to "Working" in order to avoid magnification problems discussed here:

SetOptions[$FrontEndSession, PrintingStyleEnvironment -> "Working"]

Then, I suggest to use Grid instead of GraphicsGrid (the value -.11 is found by trial and error):

Grid[Partition[labels, 10], Spacings -> {0, -.11}]
Export["number.pdf", %] // SystemOpen

screenshot

The above screenshot is of the PDF file exported with Mathematica 13.0.0 on Windows 10 x64.

But with Mathematica 12.3.1 and 8.0.4 I get a PDF image of size 201 x 60 mm. This is version-dependent since even the actual meaning of ImageSize changed significantly in the latest versions, apart from updated PDF exporter.

If you need exact control over the size of the final image, the best what you can do is to make a Graphics object with your contents by using low-level functions like Inset and Text, and not relying on any high-level functionality.

An example:

mm = 72/25.4;

coords = Flatten[Table[{x, y}, {y, 1, 10}, {x, 1, 10}], 1];

labels = IntegerString[Range[100], 10, 5];

imageSize = {200 mm, 60 mm}; gr = Graphics[MapThread[Text, {labels, coords}], PlotRange -> {{.5, 10.5}, {.5, 10.5}}, PlotRangePadding -> 0, ImageSize -> imageSize, AspectRatio -> 1/Divide @@ imageSize];

Export["number.pdf", gr] // SystemOpen

This should give the exact size of the exported PDF, but even with version 13.0.0 it does not:

screenshot

... but version 8.0.4 exports a PDF with exact image size:

screenshot

Hence we have a regression in the PDF exporter in the latest Mathematica versions. Reported to the support as [CASE:4895073].

Update. I just received a response from the support. Here is an excerpt:

Thank you for taking the time to send your report.

It does appear that Export[] is not preserving the specified image size with the PDF files it generates. <...>

This issue appears to have started in Mathematica 12.1, so any earlier versions should not exhibit this behavior.

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
  • My output using Grid is 144.6 x 58.6 mm only. Any thoughts ? – tobalt Jan 12 '22 at 08:16
  • @tobalt Added some thoughts. – Alexey Popkov Jan 12 '22 at 08:35
  • 1
    So you suggest making a single Graphics with multiple Text directives, each placed at the corresponding position. Actually I doubt this would work. As I mentioned in my question, even for a single Text without GraphicsGrid, it didn't work. Thanks for your help, but I think I am gonna piece it together with Python, where at least the PDF export is exact. – tobalt Jan 12 '22 at 08:53
  • @tobalt Yes, producing pixel-perfect graphics with Mathematica is always a challenge, and everything can break in an unexpected way. If you will make your Python solution work through Mathematica, please share it. – Alexey Popkov Jan 12 '22 at 09:05
  • It doesn't use Mathematica, but I have added it below anyway, in case anyone would be interested. – tobalt Jan 12 '22 at 09:13
  • 1
    @tobalt Updated the answer with a response from the support confirming the bug. – Alexey Popkov Jan 12 '22 at 19:12
  • Thanks. But as I wrote above, v 11.2 also doesn't get it right with neither Grid nor GraphicsGrid. So there seems to be more buggy than only the PDF exporter. ‍♂️ – tobalt Jan 13 '22 at 04:01
  • @tobalt I'm sorry, but I completely forgot that in my Mathematica 13.0.0 PrintingStyleEnvironment was set to "Working" permanently, but in versions 12.3.1 and 8.0.4 it wasn't. This made my answer inconsistent. Now I've rewritten it to make all the results consistent with recommended setting PrintingStyleEnvironment -> "Working". – Alexey Popkov Jan 13 '22 at 08:03
  • 1
    I've inserted the SetOptions, but still no luck. Yes, Grid export is now closer to the intended size, but not exact. (201.1 x 80.8) instead of (200 x 60). Also you mention that you found the spacing of -.11 by trial and error. Such finetuned and unexplained value is not really conducive to building trust in an accurately scaled PDF export method. So I still see no resolution here (but thank you very much for your effort and for escalating this). Btw the Inset+Text method is also not exact, it exports the same size here as in your version 13 test. – tobalt Jan 13 '22 at 08:16
0

For those interested, here is a workaround using matplotlib of Python.

import numpy as np
import matplotlib.pyplot as plt

mm = 1 / 25.4

#Array size nx = 10 ny = 40 #Cell size cx = 20mm cy = 6mm

#relative position (left-center justified) of text in cell npx = 0.25 npy = 0.7

plt.figure(figsize=(cxnx, cyny))

for x in (np.arange(nx)+1): for y in (np.arange(ny)+1): plt.figtext( (npx+x-1)/nx, (npy+y-1)/ny, f'{x+nx(y-1):06.0f}', horizontalalignment='left', verticalalignment='center', size=723*mm, fontfamily='consolas', weight='bold')

plt.savefig("numbers-py.pdf")

enter image description here

tobalt
  • 357
  • 1
  • 6