web analytics
Skip to main content

The PreTeXt Guide

Section 5.14 Images

Subsection 5.14.1 Raster Images

A raster image is an image described pixel-by-pixel, with different colors and intensities. Photographs are good examples. Common formats are Portable Network Graphics (PNG) and Joint Photographic Experts Group (JPEG, JPG), which will both work with pdflatex and modern web browsers. JPEG is a good choice for photographs since they are compressed on the assumption they will be viewed by a human, while PNG is a lossless format and good for line art, diagrams and similar images (if you do not have vector graphics versions, see below).
To use these images, you simply provide the complete filename, with a relative path. A subdirectory such as images is a good choice for a place to put them. It is your responsibility to place these images where the output will find them or where the HTML output will find them. Your PreTeXt source would look like:
<image source="images/crocodiles.png" width="50%" />
Typically you would wrap this in a <figure> that might have an @xml:id attribute for cross-references, with or without a caption. There is no @height attribute, so the aspect ratio of your image is your responsibility outside of PreTeXt. The @width attribute is a percentage of the available width of the text (outside of a <sidebyside> panel).
You may also provide a <description> which will aid accessibility for electronic formats. Keep such readers in mind and provide as much description as possible. Keep the markup simple, since this will typically migrate to an HTML attribute that cannot contain any structure. Be careful to avoid double-quotes. For example:
<image source="images/crocodiles.jpeg" width="50%">
    <description>Five crocodiles partially submerged.</description>
</image>

Subsection 5.14.2 Vector Graphics

An image is a vector graphic if the file describes the geometric shapes that constitute the image. So a simple diagram would be a good candidate, but a photograph would not. Popular formats are Portable Document Format (PDF) and Scalable Vector Graphics (SVG). You will get the best results with PDF images in output and SVG images for HTML. The principal advantage of these formats is that they scale (big or small) smoothly, along with fonts. This is critical when you cannot predict the screen size for a reader of an electronic version.
Unless you describe these images with a language (see Subsection 5.14.3), you are responsible for providing the PDF and SVG versions. The pdf2svg utility is very useful if you have PDF images only. To have these different images used for different output formats, you simply follow the instructions above, but do not include a file extension. This alerts the conversion to use the best possible choice for any given output, and to embed it correctly. So presuming you made available the files images/toad-life-cycle.pdf and images/toad-life-cycle.svg, the following example would incorporate the PDF version with output and the SVG version for HTML output.
<image source="images/toad-life-cycle" width="85%">
    <description>The four stages of a toad's life.</description>
</image>
Vector graphics images can be created with source code in different languages (Subsection 5.14.3) or with applications, such as Inkscape (Section 6.7). If you are creating non-technical graphics that have lots of geometric shapes and simple text (a look like a movie poster), then using a tool like Inkscape is a great choice since its native file format is an enhanced version of SVG and a faithful PDF is easy to create.

Subsection 5.14.3 Images Described by Source Code

There are various languages which may be used to describe diagrams, geometric objects, or data plots. A key strategy enabled by PreTeXt is to put these specifications of such images directly in your document's source rather than losing track of them over time.
So we have various elements which are children of <image> that hold these source code descriptions. Then PreTeXt provides techniques for realizing these in the best formats for various devices and print. So if you are accustomed to the idea of a @source attribute pointing to a file, think of these elements as alternative specifications.

Subsubsection 5.14.3.1 Asymptote

Asymptote 1  is a vector graphics language that produces high-quality output in WebGL, SVG, PNG, and PDF formats. You can describe 2-D or 3-D objects, and the 3-D objects are interactive in online output as HTML WebGL files. may be used, and your macros are automatically available for use.
Authoring is straight-forward. Inside an <image> include a child <asymptote> to hold the code. For example:
<image xml:id="gaussian-histogram">
    <description>A histogram of Gaussian data.</description>
    <asymptote>
    import graph;
    import stats;

    size(400,200,IgnoreAspect);

    int n=10000;
    real[] a=new real[n];
    for(int i=0; i < n; ++i) a[i]=Gaussrand();

    draw(graph(Gaussian,min(a),max(a)),blue);

    // Optionally calculate "optimal" number
    // of bins a la Shimazaki and Shinomoto.
    int N=bins(a);

    histogram(a,min(a),max(a),N,normalize=true,low=0,lightred,black,bars=false);

    xaxis("$x$",BottomTop,LeftTicks);
    yaxis("$dP/dx$",LeftRight,RightTicks(trailingzero));
    </asymptote>
</image>
Here is the result. Look elsewhere for examples of 3-D output from Asymptote.
Notes:
  • Notice the necessity of escaping the less-than in the for-loop. See Subsubsection 5.1.4.2.
  • Setting a @xml:id is necessary to have a stable name for graphics files that will be generated.
  • The <description> is an important part of making your output accessible.
  • Notice the use of for the label on the vertical axis. All of your macros defined in docinfo are available for use, so you can keep notation consistent.
  • You need to produce PDF versions of your diagrams for use in a conversion to .
  • You need to produce HTML versions of your diagrams for use in a conversion to an electronic format based on HTML. For a 2-D diagram these are a thin wrapper around an SVG image. For a 3-D diagram these are interactive WebGL objects.
    It is very important to note that these HTML versions contain the height and width of the diagram and these are queried by a conversion of your document to HTML format in order to compute the aspect ratio. Therefore they need to be available with your other source files (typically in an images directory). So in a very real sense these files become part of your source.
  • You may want to produce SVG versions of your diagrams for conversion to EPUB, and PNG versions for conversion to the EPUB precursor for Kindle format.
  • PDF versions produced by the pretext script will not include the RPC extensions. So “rotatable” 3D images rendered by the proprietary viewer, Adobe Acrobat, are not created, consistent with our open source philosophy.
  • Colors in Asymptote can be hard-coded using rgb syntax. Colors can also be defined at the top of an Asymptote file, to be referred to later. You may wish to produce PDF in both color (electronic) and black and white (print on demand) formats, and you probably do not want to maintain parallel source for both versions. Rather than writing (for example) pen p=rgb(0,0,.7); in your Asymptote code, you can write pen p=curvepen1;. Then, in the <docinfo> section of your document, you can add an <asymptote-preamble> and include the line pen curvepen1=rgb(0,0,.7);. Once you are ready to produce your black and white version, you need only change the definition of curvepen1 in your <asymptote-preamble>.
    One note of caution: if your preamble includes Asymptote code that only works once certain libraries are loaded, you must include lines to import those libraries in your preamble. For example, to define a material you must first have the line import three;.
Asymptote may be run as a program installed locally, but the project also has an on-demand online server written by Supakorn Jamie Rassameemasmuang. By default, the pretext/pretext script (Chapter 48) will interface automatically with this server to create your diagrams. Furthermore, Asymptote provides a very useful web application 2  written by Pedram Emami. This is a great place to learn, experiment, and iterate as you become more skilled at building high-quality graphics to illustrate the concepts in your document.
Best Practice 5.14.1. Build 3-D Asymptote Figures.
If your project uses geometric or mathematical objects that are three-dimensional, invest some time in learning the Asymptote vector graphics language. The interactive diagrams for your HTML output produced by Asymptote, in WebGL format, are outstanding and will greatly enhance your project. (And the other static formats are similarly excellent.) The pretext/pretext script will create these diagrams, in the necessary formats, with no extra software by using an online server.

Subsubsection 5.14.3.2 Images in Syntax

There are a variety of packages for authoring a diagram, plot, or graph. Examples include: TikZ, PGF, Xy-pic, and PSTricks. Generally, the <latex-image> tag allows you to incorporate this code into your source and PreTeXt realizes these descriptions as images in your output.
For output the procedure is transparent—PreTeXt simply incorporates the preamble information and the image's code in the correct places in the output, scaled to fit whatever space is described on the <image> element. Then traditional processing will do the right thing. For output to other non- formats, such as HTML or EPUB, we need some help from the CLI to generate other formats. This tool will isolate the image's code and bundle it up with the necessary preamble to make a complete single-purpose file. Once converted by to a PDF version, other tools can convert the image into other formats, such as SVG. In this way, you can use packages for describing images, use mathematically-correct labels in syntax, and use your own macros for consistency in notation, yet also employ the resulting images in more modern output formats. Note that as of 2020-07-24, limited testing indicates that PSTricks needs to be processed with the xelatex engine, and the pstricks-add package might also be necessary. Any updates, especially using pdflatex would be appreciated. Finally, processing with xelatex might be necessary if your labels use Unicode characters.
Much like the <asymptote> tag, the <latex-image> tag is used as a child of <image> and can be thought of as an alternative to the @source attribute of <image>. The contents need to be a complete specification of the image. For example, a TikZ image will typically begin with \begin{tikzpicture}. Inside of your document's <docinfo> you will likely need to employ a <latex-image-preamble> element to hold necessary \usepackage commands and any global settings, such as the style for tick-marks and labels on axes of graphs. The source code in this next example is greatly abbreviated and mildly edited, see the source for the complete example.
<docinfo>
    <latex-image-preamble>
    \usepackage{tikz}
    </latex-image-preamble>
</docinfo>
<figure>
    <caption>RNA Codons Table, by Florian Hollandt</caption>
    <image xml:id="rna-codons-table" width="100%">
        <description>A table of the RNA codons.</description>
        <latex-image>
        \begin{tikzpicture}
        \footnotesize
        \tikzstyle{every node}=[inner sep=1.7pt,anchor=center]
        % to_x and from_x styles denote bonds terminating
        % or starting in labeled nodes. x denotes the
        % number of letters in the node label.
        \tikzstyle{to_1}=[shorten >=5pt]
        \tikzstyle{to_1i}=[shorten >=6pt]
        \tikzstyle{to_2}=[shorten >=7pt]
        \tikzstyle{to_3}=[shorten >=8pt]
        ...
        \begin{scope}[scale=0.5]    % Asparagine
        \draw[ultra thick,shorten >=2pt,shorten &lt;=2pt] (90-2*5.625:8.2)
                        arc(90-2*5.625:90-4*5.625:8.2);
        \path (90-3.5*3.625-3:13.3) node (zero) {};
        \draw[to_2]  (zero.center)  -- ++(30:1) node (CO) {}
                        -- +(330:1) node [anchor=base] {O$^{\mbox{-}}$};
        \draw[to_1]  (CO.center)    -- +(90:1) node (Od) {O};
        \draw[to_1i] (CO.30)        -- +(90:1);
        \draw[to_3]  (zero.center)  -- ++(150:1) node {NH$_{\mbox{3}}^{\mbox{+}}$};
        \draw[to_2]  (zero.center)  -- ++(270:1) node(Cb){}
                        -- ++(330:1) node (Cc) {}
                        -- +(30:1) node (Cd) {NH$_{\mbox{2}}$};
        \draw[to_1i] (Cc.center)    -- +(270:1) node (O) {};
        \draw[to_1]  (Cc.210)       -- (O.150);
        \path (O.center) node {O};
        \end{scope}
        ...
        \node at (90-55*5.625:4.5) {C};
        \node at (90-58*5.625:4.5) {S};
        \node at (90-61*5.625:4.5) {L};
        \node at (90-63*5.625:4.5) {F};
        \end{tikzpicture}
        </latex-image>
    </image>
</figure>
This will result in:
A table of the RNA codons, together with the amino acids they encode.
Figure 5.14.2. RNA Codons Table, by Florian Hollandt, from ample.net 3 

Subsubsection 5.14.3.3 Scaling TikZ Images

Images authored in TikZ 4  are the most popular. Text (nodes) in a TikZ picture are at whatever the current font size is. The other parts of the picture (lines, circles, rays, etc.; the “line art”) can be scaled as part of an overall scale factor. The point being, the scale factor will not scale the text simultaneously. It is not unlike a map application on your mobile device. The name of a road is too small to read, so you zoom in on the map, making the street bigger, but the name stays in the same font size and is still unreadable. This means some manual labor is involved when you place a TikZ picture into a PreTeXt document.
For many authors, the goal is to have the text in their TikZ picture have the same size as the surrounding text, both in a PDF and in HTML. We now explain how to accomplish this consistently.
Preparation.
Well before designing many TikZ images, answer the following questions.
  1. For your output, what will the overall font size be?
  2. For your output, what will the width of the text block be? Note that this will normally be computed by PreTeXt, dependent on your chosen font size. A larger font will mean a greater width. You can generate the source file and look early in the preamble to see what width is being used. It is also possible that you may be setting this with yourself (Section 31.6). The ratio of line width to font size is always \(34:1\text{.}\)
TikZ in .
Every image in PreTeXt may be constrained by width and/or margins, or may be restricted to a panel of a <sidebyside> with a certain width. So the TikZ code you author will create an image that is then scaled by PreTeXt to fit the constraints (much as any other image is scaled). Except this is done in a way that scales both the font and the line art. Your main goal is to have this scaling use a scale factor of \(1.0\text{.}\) Which, of course, sounds like a waste of effort, but it is critical for how the image behaves in HTML (next).
To accomplish this unit scaling, follow this procedure for each TikZ picture.
  1. Determine the width of the TikZ picture itself, in physical units of length. Typically, the lengths used for larger portions are described in centimeters. But note that an overall scale factor is sometimes applied for convenience (or as a result of poor planning!). Also, the default unit length (centimeters) can be changed. Note also, that text may “push out” to the right and left, defining the boundaries on the sides, and these lengths can be hard to compute or predict.
  2. Recall the width of your text (above). Recognize that list items will be indented (reducing width), and perhaps there are multiple indents if a list has multiple levels.
  3. Now you want the width of your picture as a percentage of the overall available width. By default, your overall width will be points, and your picture width will be in centimeters. You may be familiar with a “big point” (or “desktop publishing point”) which is \(72\) points to the inch. however uses \(72.27\) points to the inch, which makes a point equal to \(0.03514598\) centimeters. Convert to whatever common unit makes sense to you, since it is the dimension-less ratio you are after.
  4. Use this percentage as the @width attribute on the <image> (with a percent sign).
Now produce a PDF and you will find that the font in the surrounding text, and the font in image, will match identically. I like to check this carefully by zomming in on the PDF and using an on-screen pixel ruler to check the heights of identical letters. KRuler 5  is one such example for Linux, suggestions for other operating systems are welcome.
Note that in practice you will envision your picture as large or small, and you will begin with some overall physical width in mind, relative to the line width.
TikZ in HTML.
For HTML output, the goal is to not edit your source. In other words to not change the @width attributes that have been so carefully computed and to not edit the TikZ code. But you will want to maintain fidelity with the surrounding font.
HTML output is designed to behave very similarly (not identically) to how output behaves. In other words, the ratio of line width to font size is \(34:1\text{.}\) In this way, line length and font size are such that a long paragraph will usually have an identical number of lines in (at any font size) and in HTML.
Our tools produce Scalable Vector Graphics (SVG) versions of TikZ pictures for use in HTML output. Being scalable means a reader can zoom in without any pixelation of the images. This is helpful for those with low vision, or if some fine point of a picture needs to be examined closely. It also means an SVG can be scaled by any factor when placed in PreTeXt HTML. However, the work done for a unit scaling for output will continue to provide the correct scaling for HTML! (Provided the text width used for the PDF production is the one automatically computed from the font size via the \(34:1\) ratio.)
The PreTeXt source below describes a simple TikZ picture, nd is followed by the picture itself. The rectangle is 8 centimeters wide. The Guide is produced as a PDF with 10 point text and a text width of \(6.5\) inches. (This is too wide for comfortable reading, and contrary to our recommendations. See Best Practice 31.6.1.) Normally, a choice of 10 point text would result in a width of \(340\) point, or about \(4.7\) inches.
So we compute the fraction of the available width required, as a percentage:
\begin{equation*} \frac{8\text{ cm}}{6.5\text{ in}} = \frac{8\text{ cm}\left(\frac{1\text{ in}}{2.54\text{ cm}}\right)}{6.5\text{ in}} = 0.4846 = 48.46\% \end{equation*}
and we use that as the width of the image.
<image xml:id="scaling-tikz" width="48.46%">
    <latex-image>
    \begin{tikzpicture}
    % 1 cm is default unit of length
    % a rectangle: 8 cm wide, 6 cm tall
    \draw[draw=black, thick] (4,2) rectangle (-4,-2);

    \node at (-2,  1) {Foo};
    \node at ( 2,  1) {Bar};
    \node at (-2, -1) {Baz};
    \node at ( 2, -1) {Qux};
    \end{tikzpicture}
    </latex-image>
</image>
Some characters for comparison: Foo  Bar  Baz  Qux
In the PDF version, the text matches between the image and the surrounding text almost identically. We could slide the image right and left by adjusting the margins (the default is to be centered). But if we want the image bigger and smaller, we need to adjust the TikZ code and recompute the @width attribute.
Now for HTML we need to produce an SVG version that is a close match. The HTML version is a close match for built with a computed text width (for any font size). We do not want to change the percentage of the width devoted to the TikZ picture, and we do not want to change the TikZ code itself. If we had not chosen a different text width (the \(6.5\) inches, versus a computed \(340\) point), then we could generate the SVG by supplying the same publication file, so as to use the same font size. However, our text width is 38% larger in the version,
\begin{equation*} \frac{6.5\text{ in}}{340\text{ pt}} = \frac{6.5\text{ in}\left(\frac{72.27\text{ pt}}{1\text{ in}}\right)}{340\text{ pt}} = 1.3816 \end{equation*}
The font size needs to increase by a similar percentage,
\begin{equation*} 10\text{ pt}\times 1.3816 = 13.816\text{ pt}\approx 14\text{ pt} \end{equation*}
So we generate the SVG image with a different publication file, giving a font size of 14 point. The HTML font in the text may be very different from the font used in the TikZ picture, but their sizes are nearly identical. Note that our use of only supports 8 different font sizes, so it was fortuitous in this example that the 38% increase was so close to the supported 14 point font size. Note also, that since we used a different text width for the PDF, the resulting 40% increase in the font size for the SVG could play havoc with text that has been placed carefully not to overlap other components of the picture.
There are myriad ways to scale and transform a TikZ picture. You might choose to intentionally use a smaller font size than the surrounding text, as in Figure 5.14.2. Or, fidelity with the surrounding text might not be important to you. Or you might prefer that images perform better in HTML. But hopefully the above discussion and example provide enough insight into how the various constructions behave. The important points are:
  • TikZ uses physical units for the overall width of a picture, and nodes have text using the ambient font size of the PreTeXt file (unless prescribed otherwise).
  • PreTeXt scales a TikZ picture uniformly (text and line art) to fit into constraints given in the source.
  • The SVG version of a TikZ picture is also uniformly scalable and at the same width as the original will have text of the correct font size. However, when used in HTML output, it is scaled on the assumption that the ratio of the line width to the font size is 34:1. This is the default width computed by PreTeXt for all supported font sizes. Changes in this ratio for PDF production requires an equivalent change in font size during SVG construction, via the publication file.

Subsubsection 5.14.3.4 Images in Sage Syntax

Sometimes the necessary computations for an image are not part of the capabilities of whatever system is actually realizing the image. We have good support for Sage in other parts of your document, and Sage has an extremely wide variety of computational capabilities, in addition to letting you program your own computations in Python syntax with the full support of the Sage library. Rather than translating Sage output as input to some other graphics program, we simply capture the graphics output from Sage. So if your graphics are derived from non-standard, or intensive, computation this might be your best avenue.
Use the <sageplot> element, in a manner entirely similar to the <asymptote> element and the <latex-image> element, as a child of <image>, and containing the necessary Sage code to construct the image. There is one very important twist. The last line of your Sage code must return a Sage Graphics object. The pretext/pretext script (Chapter 48) and PreTeXt-CLI (Section 6.2) will isolate this last line, use it as the right-hand side of an assignment statement, and the Sage .save() method will automatically be called to generate the image in a file. Note that there are four different file types, depending on if the graphic is 2D or 3D, and the output format of the conversion.
The @variant attribute of the <sageplot> element may be 2d or 3d, since PreTeXt is not capable of analyzing your Sage code. The default value is 3d so can be skipped for 2D plots. For technical reasons, it is also necessary to specify the aspect ratio of a graphic for the 3D case using the @aspect attribute. The value can be a positive real number (decimal) or a ratio of two positive integers separated by a colon. The default is a square (1.0 or 1:1).
Table 5.14.4. File formats for sageplot images
2D 3D
PDF PNG
HTML SVG HTML (for iframe)
Note that the PNG images in the 3D case are not very good. This needs help on the Sage side. And since 3D images in HTML output are inserted via an HTML iframe they can misbehave if you do not get the aspect ratio close to right. On the plus side, the 3D HTML images may be manipulated interactively with keyboard arrow keys, a mouse scroll wheel, and by dragging with a mouse using both a left and a right mouse press.
Pay very careful attention to the requirement that the last line of your code evaluates to be a graphics object. In particular, while show() might appear to do the right thing during testing, it evaluates to Python's None object and that is just what you will get for your image. The example below illustrates creating two graphics objects and combining them into an expression on the last line that evaluates to the graphics object that will be created in the desired graphics files.
<figure>
    <caption>Negative multiple of a curve</caption>
    <image xml:id="negative-curve" width="65%">
        <description>Plot of x^4 - 1 and its negative.</description>
        <sageplot>
        f(x) = x^4 - 1
        g(x) = -x^4 + 1
        up = plot(f, (x, -1.5, 1.5), color='blue', thickness=2)
        down = plot(g, (x, -1.5, 1.5), color='red', thickness=2)
        up + down
        </sageplot>
    </image>
</figure>
This will result in:
Plot of x^4 - 1 and its negative.
Figure 5.14.5. Negative multiple of a curve
Note the necessity of using the pretext script (Chapter 48) to independently invoke Sage, no matter what sort of output is being created for your document.

Subsection 5.14.4 Image Formats

Best Practice 5.14.6. Preferred Image Formats.

The best formats for images, in order, are:
SVG
Vector graphics format ideal for HTML output formats. Scalable and compact. Converts to other formats, such as PDF.
PDF
Vector graphics format ideal for print and PDF output formats. Good tools exist to convert back-and-forth between SVG and PDF.
PNG
Lossless and compressible format for raster images. May be used for both HTML and PDF outputs.
JPEG
Compressed lossy format which works well for photographs. May be used for both HTML and PDF outputs. PNG should be preferred when there is a choice, except in the case of a photograph. Converting between these formats is unlikely to be an improvement.

Subsection 5.14.5 Image Archives

As an instructor, you might want to recycle images from a text for a classroom presentation, a project handout, or an examination question. As an author, you can elect to make images files available through links in the HTML version, and it is easy and flexible to produce those links automatically.
First, it is your responsibility to manufacture the files. For making different formats, the pretext script can sometimes help (Chapter 48). The Image Magick convert command is a quick way to make raster images in different formats, while the pdf2svg executable is good for converting vector graphics PDFs into SVGs. Also, to make this easy to specify, different versions of the same image must have identical paths and names, other than the suffixes. Finally, the case and spelling of the suffix in your PreTeXt source must match the filename (e.g. jpg versus JPEG). OK, those are the ground rules.
For links for a single image, add the @archive attribute to the <image> element, such as
<image  ...  archive="pdf svg">
to get two links for a single image.
To have every single image receive an identical collection of links, in docinfo/images place an <archive> element whose content is the space-separated list of suffixes/formats.
<archive>png JPEG tex ods</archive>
will provide four links on every image, including a link to an OpenDocument spreadsheet.
For a collection of images that is contained within some portion of your document, you can place an @xml:id on the enclosing element and then in docinfo/images place
<archive from="the-xml-id-on-the-portion">svg png</archive>
to get two links on every image only in that portion (chapter, subsection, side-by-side, etc.). The @from attribute is meant to suggest the root of a subtree of your hierarchical document. If you use this, then do not use the global form that does not have @from.
You may accumulate several of the above semi-global semi-local forms in succession. An image will receive links according to the last <archive> whose @from subtree contains the image. So the strategy is to place general, large subtree, specifications early, and use refined, smaller subtree specifications later. For example,
<archive from="the-xml:id-on-a-chapter">svg png</archive>
<archive from="the-xml:id-on-the-introduction">jpeg</archive>
<archive from="the-xml:id-on-a-section-within" />
will put two links on every image of a chapter, but just one link on images in the introduction, and no links at all on every image image within one specific section. Again, do not mix with the global form. You can use the root document node (e.g. <book>) for @from to obtain a global treatment, but it is unnecessary (and inefficient) to provide empty content for the root node as first in the list—the same effect is the default behavior.
Notice that this facility does not restrict you to providing files of the same image, or even images at all. You could choose to make data files available for each data plot you provide, as spreadsheets, or text files, or whatever you have, or whatever you think your readers need.
Finally, “archive” may be a bit of a misnomer, since there is no historical aspect to any of this. Maybe “repository” would be more accurate. Though for a history textbook, it might be a perfect name.

Subsection 5.14.6 Copies of Images

Sometimes you want to use the same image more than once. Putting it in a <figure> and then making a cross-reference (<xref>) can work well in HTML output since it will be available as a knowl. However in a static format (PDF, print) the reader will need to chase the cross-reference.
For a raster image, you can just point to the file again with the @source attribute. You are free to wrap it in a figure and thus change the caption. It will get a new number as a new figure, and you will need to assign a new unique @xml:id attribute. Maybe appending -copy-2, or similar, to the @xml:id will be helpful.
If you have a figure generated from source code (such as in TikZ) you really do not want to edit and maintain two copies that may not stay in sync. Instead, you can place the code into a file and xinclude it twice. Study Section 5.35 carefully, and note that this is an excellent place to take advantage of setting the @parse attribute to text (no need to escape problematic XML characters). Notice that when you generate images, you will have two image files with identical contents, but different names. This is no place for false optimization. Bits are cheap and your time is valuable. It is far more important to only maintain a single copy of the source, than to be caught up with the “waste” of having two copies of the same file (and which are managed for you). We demonstrate this with the sample book, since it is all set up with the xinclude mechanism. See the two plots of the 8-th roots of unity in the complex numbers section of the chapter on cyclic groups.
asymptote.sourceforge.io/
asymptote.ualberta.ca/
texample.net/tikz/examples/rna-codons-table/
github.com/pgf-tikz/pgf
apps.kde.org/kruler/