3
$\begingroup$

I want to add an image into a plot. Lets leave the plot empty for simplicity. It is important that in the end the pixels of the image are identical to the original.

First we define an example image:

imagedata = Table[If[25 < i + j < 75, 1, 0], {i, 1, 200}, {j, 1, 200}];

Then we add it into the plot

 plot=ListPlot[{}, Axes -> None, AspectRatio -> 1, ImageSize -> 400, 
  Epilog -> {Inset[Image[imagedata, ImageSize -> 400], {0, 0}]}]

Export["plot.pdf",plot]

The inset works fine, but if the image is now exported it becomes blurred: blurred image

Normally I would assume this happens because the number of pixels has changed or something, but it even happens in a pdf export, where such things should not matter.

The crazy part is that images up to a size of 143x143 are perfectly fine and get exported correctly, but 144x144 and higher are blurred. This makes me think this is some internal performance option, but I could not find it.

Maybe some of you have an idea? See below the comparison between 143x143 and 144x144 143x143 image144x144 image

$\endgroup$

1 Answer 1

2
$\begingroup$

With Mathematica 12.3.1 on Windows 10 x64 I do not reproduce your issue with the image dimensions 200 x 200:

imagedata = Table[If[25 < i + j < 75, 1, 0], {i, 1, 200}, {j, 1, 200}];
plot = ListPlot[{{0, 0}, {1, 1}}, Axes -> None, AspectRatio -> 1, ImageSize -> 400, 
  Epilog -> {Inset[Image[imagedata, ImageSize -> 400], Center, Center]}]
Export["plot.pdf", plot] // SystemOpen

out

screenshot

Inspecting the contents of the produced PDF file reveals that it doesn't contain rasters at all, and the image is represented completely in vectors as FilledCurves:

pdfContents = Import["plot.pdf", "PageGraphics"][[1]];
Count[pdfContents, _FilledCurve, -1]
Count[pdfContents, _Raster, -1]
40002
0

But increasing the pixel size of the image results in rasters in the exported PDF file:

imagedata2 = Table[If[25 < i + j < 75, 1, 0], {i, 1, 400}, {j, 1, 400}];
plot2 = ListPlot[{{0, 0}, {1, 1}}, Axes -> None, AspectRatio -> 1, ImageSize -> 400, 
   Epilog -> {Inset[Image[imagedata2, ImageSize -> 400], Center, Center]}];
Export["plot2.pdf", plot2] // SystemOpen

screenshot

pdfContents2 = Import["plot2.pdf", "PageGraphics"][[1]];
Count[pdfContents2, _FilledCurve, -1]
Count[pdfContents2, _Raster, -1]
2
1

The screenshot looks blurry and for some reason the PDF file contains a grayscale image with only two pixel color values:

imgPDF = FirstCase[Import["plot2.pdf", "PageGraphics"], 
   r_Raster :> Image[r], Automatic, -1];
Union[Flatten[ImageData[imgPDF, "Byte"]]]
{0, 254}

I don't think that the fact that the white color is translated to grayscale 254 should necessarily lead to blurry rendering of the image. Probably it is a horrible feature of the Adobe Acrobat rendering method. But the fact that a black&write image is exported as a grayscale image with 254 as a representation of white instead of 255, should be considered as a bug in Mathematica's exporter. Please report it to the support.

$\endgroup$
4
  • $\begingroup$ You are right! In my case the difference between both pdfs is indeed that the blurry one is rasterized, while the other is a FilledCurve! But there are still some remaining questions and problems. Even in Mathematica the rasterized pdf is blurred in my version 12.1 and looking for the color values yields {0, 32, 64, 96, 127, 158, 191, 223, 254} instead of {0,254} so it is indeed blurred. This actually also happens in a png export. So for me there are only two solutions, either force mathematica not to rasterize or improve the way mathematica rasterizes. Any ideas? $\endgroup$ Aug 27, 2022 at 8:46
  • $\begingroup$ I think one of the problems is that mathematica rasters a 144x144 image as a 400x400 raster as default in the pdf. This could be the reason why you do not encounter this problem with you 400x400 image. An option would be nice so that the raster resolution has to be the original image resolution. $\endgroup$ Aug 27, 2022 at 8:50
  • 1
    $\begingroup$ @mathematica_guy Currently I have only one idea: instead of Image, directly export FilledCurve. Then we avoid the rasterization completely. You can create a separate question on how to convert an Image to a FilledCurve. $\endgroup$ Aug 27, 2022 at 9:01
  • $\begingroup$ One can use ResourceFunction["ImageSquareDivide"] for converting a raster image into vectors. $\endgroup$ Aug 30, 2022 at 3:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.