1

I have a figure that is been generated by stitching many figures together. For captioning and clarity purposes, I want this figure split into its individual pieces. I have done that using subfloat and trim and clip. However, sometimes the sizes are, well, not round in value. For example, I want to split an image into 6 subfloats and thus the trim parameters need to trim between 0 and 0.1666.... the width of the image. I do that as follows:

\documentclass{article}

\usepackage[utf8]{inputenc}

\usepackage{graphicx} \usepackage{subcaption} \usepackage[export]{adjustbox}

\begin{document}

\begin{figure} \centering \captionsetup[subfigure]{labelformat=empty,justification=centering}

\subfloat[]{%
\centering
\begingroup
\sbox0{\includegraphics{example-image-a.png}}%
\includegraphics[trim=0 0 {.833333\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}%
\endgroup
}% 

\hspace{1em} \subfloat[]{% \centering \begingroup \sbox0{\includegraphics{exp_lsqr_diff.png}}% \includegraphics[trim={.1666666\wd0} 0 {.6666666\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}% \endgroup \captionsetup{justification=centering}% }% \hspace{1em} \subfloat[]{% \centering \begingroup \sbox0{\includegraphics{exp_lsqr_diff.png}}% \includegraphics[trim={.3333333\wd0} 0 {.5\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}% \endgroup }% \hspace{1em} \subfloat[]{% \centering \begingroup \sbox0{\includegraphics{exp_lsqr_diff.png}}% \includegraphics[trim={.5\wd0} 0 {.3333333\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}% \endgroup }% \hspace{1em} \subfloat[]{% \centering \begingroup \sbox0{\includegraphics{exp_lsqr_diff.png}}% \includegraphics[trim={.6666666\wd0} 0 {.1666666\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}% \endgroup }% \hspace{1em} \subfloat[]{% \centering \begingroup \sbox0{\includegraphics{exp_lsqr_diff.png}}% \includegraphics[trim={.8333\wd0} 0 {.0\wd0} 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff.png}% \endgroup }% \end{figure}

\end{document}

This works, but causes infinitesimal (yet visible) errors such as (very zoomed in):

enter image description here

I know they look small, but most renderers I tried (Chrome, Adobe Reader, overleaf) do in fact enhance this when looked from a zoomed out image, its quite visible under most zoom conditions. How can I solve this? Obviously I don't have enough space for all the decimals I need to be accurate, they may require (a few) monkeys with typewriters.

PD: note, that with example_image_a.png this is considerably less obvious to see. My images are 64x(64x6) and therefore the effect is more visible. With a much higher resolution image, this effect, albeit visible if you look for it, its less noticeable.

PD2: example png: enter image description here

Ander Biguri
  • 1,837
  • If you can't get the trimming right in LaTeX then maybe it would be an option to split the figure in a drawing program, where you can graphically select a subfigure on the pixel level. – Marijn Nov 18 '22 at 19:42
  • What packages are you using? I assume subfig, maybe adjustbox? What else? Your code does not compile. The reason you should include a working example is so that other users who want to help you don't have to guess at your preamble. It's not noise. Also, replace f.png with example-image-a. – Sandy G Nov 18 '22 at 19:45
  • 1
    I'm not understanding why you're talking about 1 pixel discrepancies when your example has \hspace*{-.9em}. At the least, you should remove that extra spacing (see https://tex.stackexchange.com/q/7453/107497). – Teepeemm Nov 18 '22 at 20:11
  • @Teepeemm it's not 1 pixel discrepancy, it's much smaller than 1 pixel, note that the big blocks in my example are, indeed, single pixels. The horizontal space removing is less than the default gap, doesn't seem to change the behavior – Ander Biguri Nov 18 '22 at 20:26
  • I see that in your image. But in your code, I see arbitrary horizontal spacing. I can get rid of the arbitrary horizontal spacing (which does seem to change the behavior) so that you only have 1 pixel, and then you can consider \hspace*{-1px}. But I don't understand why you haven't done that. – Teepeemm Nov 18 '22 at 21:06
  • @Teepeemm Re "I don't understand why you haven't done that" mostly asking because I don't know how to do what I want to do... – Ander Biguri Nov 21 '22 at 10:22
  • @Teepeemm Re \hspace: yeah, it changes the behaviour of the spacing, but it does not change the effect that I show in the image, at all. MWE added. – Ander Biguri Nov 21 '22 at 10:29
  • 1
    @SandyG Have updated with MWE and deleted my own noise. Apologies, you are correct. – Ander Biguri Nov 21 '22 at 10:29
  • @cabohah care to elaborate in which particular } I should add }% to remove the small pixel chuncks cut? – Ander Biguri Nov 21 '22 at 10:34
  • @cabohah thanks, that is what I thought you mean yes. Also: nothing changes, still get the same effects. I am a bit confused by this line of reasoning, could you explain why you think the spacing between the figures causes individual figures not to be trimmed at pixel level? – Ander Biguri Nov 21 '22 at 10:40
  • 1
    I can't reproduce the issue. Possible things to check, ensure your png is not compressed. Otherwise, there's an obvious workaround of trimming one more pixel. – user202729 Nov 21 '22 at 12:03
  • @user202729 this code, on overleaf, reproduces the issue, if you want an engine where it shows. I suggest not using the default image and inputting a smaller, yet integer divisible image as input. The example image is not really good at showcasing it, but you can definitely see it. Also 1) this is a scientific plot, I can't just trim one more pixel 2) the trim mismatch is about 0.00001% of a pixel, its tiny, yet visible. Its not a 1 pixel error. – Ander Biguri Nov 21 '22 at 12:07
  • Then trim 0.01% of a pixel instead? – user202729 Nov 21 '22 at 12:09
  • @user202729 OK, so read the question again: its not exactly that number, the problem is written in the question and well explained: the amount I need to trim so its exact has infinite decimals, which is the cause of the problem (I think). Please, do let me know if this is not clear in the question, I thought it was. – Ander Biguri Nov 21 '22 at 12:10
  • 1
    Maybe you can post an example image...? I tried generating one such image with PIL and still can't reproduce. – user202729 Nov 21 '22 at 12:14
  • 1
    @user202729 there you go. – Ander Biguri Nov 21 '22 at 12:20
  • I see. I'd say that this is an issue in the PDF renderer instead of that of TeX output. (I believe TeX places the whole image into the PDF, plus instruction to make the viewer crop it, so if the viewer render the image, scale it, then crop, artifact can be visible) Increasing the crop amount from 0.5\wd0 to about 0.5001\wd0 seems to fix the issue without introducing any observable difference (when printed on paper the ink would blur it out anyway, paraphrasing Knuth) – user202729 Nov 21 '22 at 12:32
  • 1
    Maybe try disabling image antialiasing? https://tex.stackexchange.com/a/10978/250119 has a guide for some viewer – user202729 Nov 21 '22 at 12:41
  • In the worst case there's still an option of using some Python/(other language) script to cut the image into parts, then include each one manually. – user202729 Nov 21 '22 at 12:43
  • @user202729 ah, but unfortunately for Knuth's wisdom, the nature of document sharing has changed since, and "printed on paper" is starting to be as similar as "written into a floppy disk", particularly for academic papers, which is what I this is for. Unfortunately your solutions only approximately works, i.e. I'd need to fiddle with numbers one by one until I find the one that doesn't make PDF readers screw this, which indeed defeats the purpose of doing it in latex. I can always just manually take all my figures and cut them, but all this exercise was to avoid doing exactly that (many figs) – Ander Biguri Nov 21 '22 at 12:43
  • @cabohah ugh. If I remove the space, the images touch each other, and thus you can not see it. Problem solved? Nope, the final figure needs to have spaces between the images, otherwise why would I even want to separate them? Its a circular argument we are getting in here. "I do not want space between the images" Wrong, you seem to have not read the question. Please, take a few seconds to do so. The issue is that the images are trimmed wrongly, not that there is an space. – Ander Biguri Nov 21 '22 at 12:50
  • @user202729 the answer then, if numerical issues can't be avoided due to the renderer, may be "you can't do this in latex". If you think that is it, please feel free to post it as an asnwer. – Ander Biguri Nov 21 '22 at 13:00
  • Now I'm confused. You want the spaces to be present? The only complaint you have in your question is about an infinitesimal (1 pixel) gap between two images. Instead, is your aim to correctly cut the picture so that you could put it back together, but you're not planning on doing so? The first thing that occurs to me is how can you notice in your image if a pixel is missing? The next thing that occurs to me is if you know the image is 384 wide, why not trim by multiples of 64 instead of fractions of \wd0? – Teepeemm Nov 21 '22 at 14:37
  • @Teepeemm No you misunderstood the question... the complain is about the line on the border of the images. The space between the images doesn't matter. – user202729 Nov 21 '22 at 15:41
  • But your example code doesn't produce your example image, so I'm not understanding your question. I'm not seeing a line on the border of the images. I'm seeing red/blue noise in front of a white background. – Teepeemm Nov 21 '22 at 16:28
  • @Teepeemm you misunderstand what you see. Check the sample image. My code splits that image in pieces, and the issue is that the split does not happen at pixel level. Forget about the length of the gap, totally irrelevant. There is a gap, that is the only important part. The reason to not use multiples of 64 is because they are not necessarily always 64, I wanted a general result. Otherwise I can just crop teh images by hand. – Ander Biguri Nov 21 '22 at 17:13
  • Future note: PDF has an ImageMask key, but I'm not knowledgeable enough to be able to write pdfspecial commands. // On the other hand, instead of cropping images by hand it's always possible to invoke an external command to crop from inside LaTeX with shell-escape, which would eliminate the amount of manual work (but some additional work is needed to avoid re-cropping the figures every time the document is compiled, which is a bit slow) – user202729 Feb 01 '23 at 01:37

1 Answers1

1

First, you need to change the original bitmap's resolution to 72 pixels per inch. This can be done by means of ImageMagick's convert command line tool.

convert -density 72 -units PixelsPerInch exp_lsqr_diff.png exp_lsqr_diff_72dpi.png

Once this has been accomplished, you can use graphicx' numerical argument for trim and related keys without unit. The unit defaults to 1bp which is exactly 1/72 inch. With the image resolution properly set, 1bp corresponds to 1 pixel and the bitmap can be precisely trimmed.

Converted bitmap exp_lsqr_diff_72dpi.png:

enter image description here

Example input with trimmed bitmap:

\documentclass{article}

\usepackage{graphicx}

\begin{document}

\noindent\frame{\includegraphics[ trim=0 0 320 0, %clip width=\linewidth]{exp_lsqr_diff_72dpi.png}}

\end{document}

Output:

enter image description here

AlexG
  • 54,894
  • Interesting. So, trying to understand this: you just changed the metadata on how big each pixel is? The imagemagic line does not interpolate, correct? Also, while this indeed seems to solve my problem, the implicit question of "how can I do this in LaTeX" seems to be: you can't, right? – Ander Biguri Nov 21 '22 at 14:11
  • 1
    It should be like this. The total amount of pixels, 384 x 64, does not change. To be verified with magick identify exp_lsqr_diff_72dpi.png. – AlexG Nov 21 '22 at 14:13
  • I am on windows: It seems that the ImageMagic line does not do anything to my images, or at least I can't see any property change (e.g. Resolution information not appearing). The original images also don't have this info, perhaps that is the cause? – Ander Biguri Nov 21 '22 at 14:27
  • On Windows, the command line may read: magick convert ... since convert alone is some existing system command. Likewise magick identify ... – AlexG Nov 21 '22 at 14:34
  • No that is not the issue, convert is indeed ImageMagics convert, I just don't see the change in the metadata of the new image. – Ander Biguri Nov 21 '22 at 14:37
  • Try identify -verbose .... Also, you will then see that the (un-used) Alpha channel was optimised away during conversion. – AlexG Nov 21 '22 at 14:40
  • Ah, you are absolutely right, the info is there, and indeed the command did change the resolution. Unfortunately the bad news is then that it did not change the bad trim effect in my question.... It does if I add the frame, but the I am just literally hiding it, not removing it. – Ander Biguri Nov 21 '22 at 14:46
  • Hm, seems to work for me. If I remove \frame{, } and enable clip in my example, I can see all 64x64 pixels of the leftmost 6th part of the included image, properly trimmed. – AlexG Nov 21 '22 at 14:52
  • Using this on overleaf, with the 6th image being \hspace{1em} \subfloat[]{% \centering \begingroup \includegraphics[trim=320 0 0 0,width=0.16\columnwidth,valign=c,clip]{exp_lsqr_diff_72dpi.png}% \endgroup }% , I can still see the left part of the 5th image there. Opening it up with other pdf viewers does not change this effect. – Ander Biguri Nov 21 '22 at 15:08