# A faster way of getting image size from jpg files?

**URL:** <https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760>\
**Category:** New to Julia\
**Tags:** images, performance\
**Created:** [August 3, 2021, 8:31pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760 "2021-08-03T20:31:16Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![rafelafrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafelafrance/32/26549_2.png) [@rafelafrance](https://discourse.julialang.org/u/rafelafrance)\
**Post date:** [August 3, 2021, 8:31pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/1 "2021-08-03T20:31:16Z")

</div>

I was trying to figure out why my Python script was well over 1000 times faster than my translation to Julia and the profiler narrowed it down to a single line, the loading of the images to get image dimensions for clipping bounding boxes.

The slowness is probably due to the way that I’m using the Images.load() function, or not cleaning up after.

The question is, What am I doing wrong here?

* * *

Slow version

```julia
function init_subjects(by_subject, image_dir)::Vector{Subject}
    # <<snip>>

    for old_sub in ProgressBar(by_subject)
        image_file = old_sub.subject_Filename

        image = try
            load("$image_dir/$image_file")
        catch
            @warn "Could not load: $image_file"
            continue
        end

        image_size = size(image)
        # <<snip>>

```

* * *

Fast version

```julia
function init_subjects(by_subject, image_dir)::Vector{Subject}
    PILImage = pyimport("PIL.Image")

   # <<snip>>

    for old_sub in ProgressBar(by_subject)
        image_file = old_sub.subject_Filename

        image = try
            PILImage.open("$image_dir/$image_file")
        catch
            @warn "Could not load: $image_file"
            continue
        end

        image_size = reverse(image.size)
        image.close()
        # <<snip>>

```

I suppose that I can keep the pycall version, but I’d prefer to not have to juggle virtual environments in Julia.

---

<div class="post-metadata">

**Author:** ![sampope](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@sampope](https://discourse.julialang.org/u/sampope)\
**Post date:** [August 3, 2021, 8:42pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/2 "2021-08-03T20:42:09Z")

</div>

While still learning myself, I’ve found try/catch/finally/end are slow. It looks like you’re using try/catch because you’re not sure if the image file is there or PILImage.open will fail. You could use [isfile()](https://docs.julialang.org/en/v1/base/file/#Base.Filesystem.isfile) as a quick test to confirm the file is there. And use [filesize()](https://docs.julialang.org/en/v1/base/file/#Base.filesize) to get the files as an Int.

---

<div class="post-metadata">

**Author:** ![sampope](https://avatars.discourse-cdn.com/v4/letter/s/e9c0ed/32.png) [@sampope](https://discourse.julialang.org/u/sampope)\
**Post date:** [August 3, 2021, 8:44pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/3 "2021-08-03T20:44:37Z")

</div>

Sorry, you wanted image size, not filesize. Sounds like [images.jl](https://juliahub.com/ui/Packages/Images/H8Vxc/0.24.1) does what you want.

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [August 3, 2021, 9:05pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/4 "2021-08-03T21:05:49Z")

</div>

I think PIL is loading the images lazily ([ref](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.open)):

> This is a lazy operation; this function identifies the file, but the file remains open and the actual image data is not read from the file until you try to process the data (or call the [`load()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.load) method).

PIL is probably identifying the image size from the jpeg header, avoiding the need to load the entire image. You could probably do the same thing via LibJpeg along the lines of this post: [Get DCT coefficients of jpeg image - #5 by stevengj](https://discourse.julialang.org/t/get-dct-coefficients-of-jpeg-image/64640/5)

---

<div class="post-metadata">

**Author:** ![rafelafrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafelafrance/32/26549_2.png) [@rafelafrance](https://discourse.julialang.org/u/rafelafrance)\
**Post date:** [August 3, 2021, 9:13pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/5 "2021-08-03T21:13:57Z")

</div>

I think your analysis about why the speed difference is occurring is right.

But Images must be reading the header info too to properly render the image. I guess that I should look into short-circuiting the full load either with the library you mention or in the Images package itself.

thanks.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [August 3, 2021, 9:32pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/6 "2021-08-03T21:32:40Z")

</div>

If you are willing to use ImageMagick.jl, this seems substantially faster on my machine:

```julia
using ImageMagick

function imagesize(filename)
       wand = ImageMagick.MagickWand()
       ccall((:MagickPingImage, ImageMagick.libwand), Bool, (Ptr{Cvoid}, Ptr{UInt8}), wand, filename)
       size(wand)
end

```

---

<div class="post-metadata">

**Author:** ![rafelafrance](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafelafrance/32/26549_2.png) [@rafelafrance](https://discourse.julialang.org/u/rafelafrance)\
**Post date:** [August 3, 2021, 10:00pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/7 "2021-08-03T22:00:06Z")

</div>

I’m already using ImageMagick.jl so that’s easy. The code works as fast as the PIL.Image solution. I just needed to `reverse(size(wand))` for my particular case.

Thank you very much.

Edit: This points to a very useful strategy of calling into libraries directly. TIL.

---

<div class="post-metadata">

**Author:** ![contradict](https://avatars.discourse-cdn.com/v4/letter/c/ac91a4/32.png) [@contradict](https://discourse.julialang.org/u/contradict)\
**Post date:** [August 3, 2021, 10:07pm UTC](https://discourse.julialang.org/t/a-faster-way-of-getting-image-size-from-jpg-files/65760/8 "2021-08-03T22:07:08Z")

</div>

That’s great, glad it helped. It is probably worth checking the return value of the `:MagickPingImage` if you use this in real code, it is just a boolean indicating success or failure.

Good catch about reversing the order of size I didn’t notice that.
