# Viewer for PDF images

**URL:** <https://discourse.julialang.org/t/viewer-for-pdf-images/95668>\
**Category:** General Usage\
**Tags:** question, images, cairomakie-plotting\
**Created:** [March 7, 2023, 1:47pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668 "2023-03-07T13:47:43Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 7, 2023, 1:47pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/1 "2023-03-07T13:47:43Z")

</div>

How can I display two PDF images side-by-side for a visual comparison?

Background:  
I run different versions of a model and wish to compare their outputs (Makie plots saved in PDF format). Effectively, I have two directories with several PDF image files. I want to scroll through them, viewing each pair of images side-by-side.

I am open to using an app for this purpose, but have not been able to find one that works well (I am on MacOS).

I am aware of ImageView.jl; it can display to images side-by-side, but those would have to be loaded somehow from the PDF files.

One option is to convert the PDF files to SVG on the fly as suggested at

> [@Show PDF in Julia Notebook & general advises for for jupyterlab extensions](https://discourse.julialang.org/t/show-pdf-in-julia-notebook-general-advises-for-for-jupyterlab-extensions/39466):
>
> Hey there, I prepared a JupyterHub Server for a class and I converted old exercise material from matlab into beautiful julia notebooks. Unfortunately, I haven’t found any possibility to view PDF images in the notebook. Is there something similar for the Julia kernel like this: [python - View pdf image in an iPython Notebook - Stack Overflow](https://stackoverflow.com/questions/19470099/view-pdf-image-in-an-ipython-notebook) ? I need this in order to get rid of the separately prepared latex documents. Final goal is to just export the notebooks as PDFs. Besides that, do you have …

I am hoping to avoid creating a folder full of temporary files, though.

---

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [March 7, 2023, 8:44pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/2 "2023-03-07T20:44:27Z")

</div>

When I look at a git diff of a modified image in vscode, I see a side by side comparison. Possibly that will also happen for pdfs although I am not completely sure.  
Would this work for you?  
Perhaps it is neccessary to also install git lens.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 7, 2023, 10:57pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/3 "2023-03-07T22:57:01Z")

</div>

Thank you for the suggestion. I have to investigate whether this solution would allow me to scroll through a directory full of files.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 8, 2023, 1:30pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/4 "2023-03-08T13:30:17Z")

</div>

I don’t think I can make this suggestion work. I need to be able to scroll through a directory of files. When I pick “a.pdf” in dir1, I want to compare with “a.pdf” in dir2 without having to manually open it.  
In VSCode, it seems I would have to manually pick both files.

One workaround that may be quite acceptable:

- write a markdown file with a bunch of `<img ...>` statements (two per line)
- preview that file in `Marked`

But there really should be an app for such a common task…

I could also cook up something using `ImageView.jl` (e.g., by converting pdf → jpg using ghostscript). But it turns out that `ImageView` takes several seconds to open a file, so that’s not practical (unless I am doing something wrong).

Thanks again for the suggestion.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 8, 2023, 3:14pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/5 "2023-03-08T15:14:11Z")

</div>

Are the files always pretty much the same except for plots? You might grab a pdf editing package (Poppler\_jll) and create a new file with A3 pages out of your two old files, where each page has v1 on the left side and v2 on the right. Then you can scroll through it side by side. Kind of crude but if there’s no app that does it?

---

<div class="post-metadata">

**Author:** ![cormullion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cormullion/32/49131_2.png) [@cormullion](https://discourse.julialang.org/u/cormullion)\
**Post date:** [March 8, 2023, 3:49pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/6 "2023-03-08T15:49:23Z")

</div>

I think this is a commonly required task in the business world - lawyers, real estate agents, politicians, journalists, etc. all need this frequently - so there are many applications for doing this. Probably more for Windows than Mac, some text-only rather than visual, some online, and many paid or subscription options… Adobe Acrobat Pro would like $20 per month from you for their PDF tool kit… 🙂

But, since you’re on a Mac, you could investigate creating an Automator action. I managed to create a Automator workflow that ‘zips’ two PDF files together page by page, using the Compare PDF (shuffle) function:

 ![Screenshot 2023-03-08 at 15.39.19](https://global.discourse-cdn.com/julialang/original/3X/c/a/cacdcb85452526f08068f568c655403fc2641503.png)

The workflow is available from the Services menu:

 ![Screenshot 2023-03-08](https://global.discourse-cdn.com/julialang/original/3X/1/1/11723cb09146c2998da8c9a40300c337e4994b71.png)

Then you can see both Page 1s of the two PDFs at the same time, altbeit vertically ordered…

 ![Screenshot 2023-03-08 at 15.40.22](https://global.discourse-cdn.com/julialang/original/3X/d/d/dd2cec7b64faa6f592eb61f5d71465cae58a65eb.png)

If you’re new to scripting MacOS, using Automator (or, if absolutely necessary, AppleScript), it may take you a while to get the hang of it. Sometimes it’s worth paying someone else to save you time. 🙂

---

<div class="post-metadata">

**Author:** ![scheidan1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheidan1/32/24771_2.png) [@scheidan1](https://discourse.julialang.org/u/scheidan1)\
**Post date:** [March 8, 2023, 3:55pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/7 "2023-03-08T15:55:46Z")

</div>

And if you do not have a mac, you can use Julia 🙂

> **[GitHub - scheidan/PDFmerger.jl: A simple Julia library to merge PDF files](https://github.com/scheidan/PDFmerger.jl)**
>
> A simple Julia library to merge PDF files. Contribute to scheidan/PDFmerger.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![Salmon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/salmon/32/22968_2.png) [@Salmon](https://discourse.julialang.org/u/Salmon)\
**Post date:** [March 8, 2023, 4:12pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/8 "2023-03-08T16:12:51Z")

</div>

There is also a pretty easy Julia workaround, at least with CairoMakie:

> **Generate test plots**
>
> ```julia
> let 
> mkpath("OldFigs")
> mkpath("NewFigs")
> x = LinRange(0,2pi,100)
> funcs = (sin, cos, exp)
> for f in funcs
> fig = Figure(resolution = 350 .*(2.,1.3),fontsize = 20)
> ax = Axis(fig[1,1])
> lines!(ax,x,f.(x),)
> save("OldFigs/$(string(f)).pdf",current_figure())
> end
> 
> for f in funcs
> fig = Figure(resolution = 350 .*(2.,1.3),fontsize = 20)
> ax = Axis(fig[1,1])
> lines!(ax,x,f.(x/2),)
> save("NewFigs/$(string(f)).pdf",current_figure())
> end
> end
> 
> ```

```julia
# This is the actual function that makes the comparison plot
using CairoMakie, FileIO, ImageMagick #ImageMagick seems to be neccessary for pdfs

function PicturesComparison(OldPath,NewPath)
    files1 = readdir(OldPath)
    files2 = readdir(NewPath)
    
    names = files1 ∩ files2

    fig = Figure(resolution = 800 .*(1,0.4*length(names)))

    axkwargs = (;
    xticklabelsvisible = false,
    xticksvisible = false,
    yticklabelsvisible = false,
    yticksvisible = false,
    spinewidth = 0.,
    xgridvisible = false,
    ygridvisible = false,
    aspect = DataAspect(),
    )
    OldAx = [Axis(fig[i,1],title = n;axkwargs...) for (i,n) in enumerate(names)]
    NewAx = [Axis(fig[i,2];axkwargs...) for (i,n) in enumerate(names)]

    for (i,n) in enumerate(names)
        for (j,p) in enumerate((OldPath,NewPath))
            img = rotr90(load(joinpath(p,n)))
            ax = [OldAx,NewAx][j][i]
            image!(ax,img)
        end
    end

    fig
end
PicturesComparison("OldFigs","NewFigs")

```

This produces the plot

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/2/2/2275b1ff8ec881c636c73016795a3a8506e1eef0.png)

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 8, 2023, 7:07pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/9 "2023-03-08T19:07:37Z")

</div>

Yes, one could make a pdf file and page through it. I have done something similar before with pdflatex. I was hoping to avoid pdf. I have a hard time articulating exactly why I find paging through the pdf file inconvenient, but it’s doable. Thanks.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 8, 2023, 7:08pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/10 "2023-03-08T19:08:48Z")

</div>

Thanks for that suggestion. I am notoriously bad at Automator / Apple Script. But it’s certainly an option.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 8, 2023, 7:10pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/11 "2023-03-08T19:10:42Z")

</div>

Thanks for that suggestion. I have not looked in detail (in a hurry right now) but it seems like this would put each graph on a separate page (not side by side). I will look into it more.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 8, 2023, 7:12pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/12 "2023-03-08T19:12:51Z")

</div>

Thanks for this suggestion. I think this is closest to what I was hoping for (barring an actual app that can do this). ImageMagick is the piece that I was missing.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [March 9, 2023, 1:51pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/13 "2023-03-09T13:51:08Z")

</div>

It is also possible to create a basic HTML file with a 2 x N table and a corresponding `<IMG>` in each cell. First convert PDFs to SVG or PNG of course.

Then use your favorite browser

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 9, 2023, 5:21pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/14 "2023-03-09T17:21:42Z")

</div>

Thank you - yes. I have been coming around to that solution as well.

I’m thinking ghostscript for the conversion, but perhaps there is a Julia package that would be more reliable than running a shell script.

---

<div class="post-metadata">

**Author:** ![Eben60](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eben60/32/13475_2.png) [@Eben60](https://discourse.julialang.org/u/Eben60)\
**Post date:** [March 9, 2023, 5:44pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/15 "2023-03-09T17:44:15Z")

</div>

Surely there are many ways to batch-convert image files. One of them on Mac is GraphicConverter by Lemke Soft. It is not free, but IMO is worth every cent of it’s price tag.

Still one more non-julian way is ImageJ/Fiji, which is scriptable in many languages (Java, Python…) and should be able to read PDFs

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [March 9, 2023, 6:52pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/16 "2023-03-09T18:52:39Z")

</div>

A GDAL linked against Poppler would let you read pdf directly as bit maps.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 9, 2023, 7:09pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/17 "2023-03-09T19:09:27Z")

</div>

I had trouble installing that (M1 mac), apparently because of a mismatch between the binaries and the apple silicon (via macports).

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 10, 2023, 9:18am UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/18 "2023-03-10T09:18:05Z")

</div>

You could make that app with GLMakie and flip through the image pairs using a button or so. I actually like image comparison better if the same canvas is flipped back and forth between two images, because then you can pick up on the smallest differences.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [March 10, 2023, 1:30pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/19 "2023-03-10T13:30:27Z")

</div>

Could you explain more how this would work with PDF files? Or are you thinking of a solution where I first convert to a bitmap format?

I have not been able to figure out how to load a PDF into an image format.  
`ImageMagick` does not work for me (Apple Silicon) because of

> <https://github.com/JuliaIO/ImageMagick.jl/issues/209>
>
> I'm getting this undefvarerror on using ImageMagick, and it is only happening on… Julia 1.7 ARM version, not the Julia 1.6.3 Intel version also running on the same computer.
> 
>  
> \> InitError: UndefVarError: libwand not defined
> \>Stacktrace:
> \> \[1\] magickgenesis
> \>  @ ~/.julia/packages/ImageMagick/Fh2BX/src/libmagickwand.jl:21 \[inlined\]
> \> \[2\] \_\_init\_\_()
> \>  @ ImageMagick ~/.julia/packages/ImageMagick/Fh2BX/src/libmagickwand.jl:27
> \>\[3\] \_include\_from\_serialized(path::String, depmods::Vector{Any})
> \> @ Base ./loading.jl:768  
> \>\[4\] \_require\_search\_from\_serialized(pkg::Base.PkgId, sourcepath::String)
> \> @ Base ./loading.jl:854
> \>\[5\] \_require(pkg::Base.PkgId)
> \> @ Base ./loading.jl:1097
> \>\[6\] require(uuidkey::Base.PkgId)
> \> @ Base ./loading.jl:1013
> \>\[7\] require(into::Module, mod::Symbol)
> \>  @ Base ./loading.jl:997
> \>during initialization of module ImageMagic 

Thank you.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [March 10, 2023, 1:39pm UTC](https://discourse.julialang.org/t/viewer-for-pdf-images/95668/20 "2023-03-10T13:39:50Z")

</div>

Ah I assumed that loading PDFs as bitmaps worked because you marked the CairoMakie version as the solution.

[Next page](https://discourse.julialang.org/t/viewer-for-pdf-images/95668.md?page=2)
