# Interactively cropping a TIFF stack?

**URL:** <https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020>\
**Category:** New to Julia\
**Tags:** images, interactivity\
**Created:** [August 8, 2021, 1:07pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020 "2021-08-08T13:07:11Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![DTL](https://avatars.discourse-cdn.com/v4/letter/d/90ced4/32.png) [@DTL](https://discourse.julialang.org/u/DTL)\
**Post date:** [August 8, 2021, 1:07pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/1 "2021-08-08T13:07:12Z")

</div>

I’ve got some 8-bit TIFF stacks, on the order of 300x300x150 (x \* y \* slices) in size. I can load these into Julia fine and display them, what I’d really like to be able to do now is interactively crop out a region define by the mouse (rectangular is fine, no need for spline fits to many points) and save that crop to a new image.

The basic code I’ve got so far is:

```julia
using Images, ImageView;
using Gtk;

using QuartzImageIO; 
#On a mac, it seems I need this else I get errors about no being able to load image

filename = open_dialog("My Open dialog")
image = load(filename);

imshow(image);

mouse_pos = map(d->println("x = $(float(d.position.x)), y = $(float(d.position.y))"),s["gui"]["canvas"].mouse.buttonpress)
@show mouse_pos;

```

I’ll admit the mouse\_pos bit is complete cargo cult programming, it came from a google search and I’m not sure how it is supposed to work. It just doesn’t seem to for me. I think I could probably do this using GTKReactive, but I don’t really want t create a whole GUI program for this simple-ish task.

Any pointers to info or help with the code is greatly appreciated.

---

<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:** [August 8, 2021, 3:04pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/2 "2021-08-08T15:04:09Z")

</div>

Here’s a solution with GLMakie, although somehow it seems the zoom rectangle was broken in the last version so it’s not actually visible. Would have been cooler if the selection was actually visible.

I didn’t write the cropping and saving part but you can see where you’d put it in the code.

```julia
using GLMakie

images = randn(300, 300, 150)

fig = Figure()

i_slice = Node(1)

ax = Axis(fig[1, 1], aspect = DataAspect(), yreversed = true,
    title = @lift("Slice $($i_slice)"))
hidedecorations!(ax)

chosen_slice = @lift(images[:, :, $i_slice]')

i = image!(ax, chosen_slice)
translate!(i, 0, 0, -5)

buttongrid = fig[1, 2] = GridLayout(tellheight = false)
b = Button(buttongrid[1, 1], label = "Save crop")
b2 = Button(buttongrid[2, 1], label = "Next image")
b3 = Button(buttongrid[3, 1], label = "Previous image")

on(b.clicks) do c
    lims = ax.finallimits[]
    println("save image cropped to $lims")
end

on(b2.clicks) do c
    i_slice[] = mod1(i_slice[] + 1, 150)
    autolimits!(ax)
end

on(b3.clicks) do c
    i_slice[] = mod1(i_slice[] - 1, 150)
    autolimits!(ax)
end

fig

```

[https://i.imgur.com/Z62rpmR.mp4](https://i.imgur.com/Z62rpmR.mp4)

---

<div class="post-metadata">

**Author:** ![DTL](https://avatars.discourse-cdn.com/v4/letter/d/90ced4/32.png) [@DTL](https://discourse.julialang.org/u/DTL)\
**Post date:** [August 8, 2021, 5:54pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/3 "2021-08-08T17:54:04Z")

</div>

Thank you!

It is a shame the crop boundary isn;t drawn, but that’s something minor for now.

---

<div class="post-metadata">

**Author:** ![sardinecan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sardinecan/32/29141_2.png) [@sardinecan](https://discourse.julialang.org/u/sardinecan)\
**Post date:** [February 6, 2024, 9:41am UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/4 "2024-02-06T09:41:37Z")

</div>

Hi everyone,  
I’m digging up this topic just to know if someone could help me to save the cropped images with Jules’s solution?  
I modified the code as above, but i must be missing something as it always returns an error when I try to save the cropped version of my image.

Thank you for your help,  
Josselin

```julia
using GLMakie
using FileIO
using ImageIO

input = load("/path/to/input.png")
images = input
images
fig = Figure()

i_slice = Observable(1)

ax = Axis(fig[1, 1], aspect = DataAspect(), yreversed = true,
    title = @lift("Slice $($i_slice)"))
hidedecorations!(ax)

chosen_slice = @lift(images[:, :, $i_slice]')

i = image!(ax, chosen_slice)
translate!(i, 0, 0, -5)

buttongrid = fig[1, 2] = GridLayout(tellheight = false)
b = Button(buttongrid[1, 1], label = "Save crop")
b2 = Button(buttongrid[2, 1], label = "Next image")
b3 = Button(buttongrid[3, 1], label = "Previous image")

on(b.clicks) do c
    lims = ax.finallimits[]
    println("save image cropped to $lims")
    # I tried to save $lims, $i, $ax... 
    save("ouput.png", lims)
end

on(b2.clicks) do c
    i_slice[] = mod1(i_slice[] + 1, 150)
    autolimits!(ax)
end

on(b3.clicks) do c
    i_slice[] = mod1(i_slice[] - 1, 150)
    autolimits!(ax)
end

fig

```

---

<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:** [February 6, 2024, 10:02am UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/5 "2024-02-06T10:02:21Z")

</div>

what’s the error?

---

<div class="post-metadata">

**Author:** ![sardinecan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sardinecan/32/29141_2.png) [@sardinecan](https://discourse.julialang.org/u/sardinecan)\
**Post date:** [February 6, 2024, 3:20pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/6 "2024-02-06T15:20:21Z")

</div>

Hi Jules,  
With `save("ouput.png", lims)` I have the following error message :

```julia
Errors encountered while save File{DataFormat{:PNG}, String}("ouput.png").
All errors:
=============
MethodError: no method matching save(::File{DataFormat{:PNG}, String}, ::GeometryBasics.HyperRectangle{2, Float32})

```

I think that I’m not saving the good object ?!

Best,  
Josselin

---

<div class="post-metadata">

**Author:** ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)\
**Post date:** [February 7, 2024, 8:55pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/7 "2024-02-07T20:55:24Z")

</div>

You would ideally use the limits as guidelines to figure out how to actually crop + save the image, so for example:

```julia
on(b.clicks) do c
    lims = ax.finallimits[]
    println("save image cropped to $lims")
    # I tried to save $lims, $i, $ax... 
    mini, maxi = extrema(lims) # get the bottom left and top right corners of `lims`
    mini = round.(Int, mini) # to index into an image, which is an array, we need ints
    maxi = round.(Int, maxi) # and the axis bounding box is always represented in floats
    cropped_slice = chosen_slice[][mini[1]:maxi[1], mini[2]:maxi[2]]
    save("output_$(i_slice[]).png", cropped_slice)
end

```

or something like this. Basically, you’re saving a cropped version of `chosen_slice[]` because that is what is actually displayed on the screen, and you know the number of the image from `i_slice[]`. I hope it makes sense!

---

<div class="post-metadata">

**Author:** ![sardinecan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sardinecan/32/29141_2.png) [@sardinecan](https://discourse.julialang.org/u/sardinecan)\
**Post date:** [February 9, 2024, 2:42pm UTC](https://discourse.julialang.org/t/interactively-cropping-a-tiff-stack/66020/8 "2024-02-09T14:42:46Z")

</div>

@asinghvi17 Thank you very much! It make sens with your explanation!  
Josselin
