Skip to content

dzsave: IIIF: use named region of 'full' when no crop takes place #4578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ master
- text: prevent use of rgba subpixel anti-aliasing [lovell]
- tiffsave: always apply resolution unit conversion [kleisauke]
- cache: suppress invalidation errors in release builds [kleisauke]
- dzsave: IIIF: use named region of 'full' when no crop takes place [lovell]

5/6/25 8.17.0

Expand Down
35 changes: 25 additions & 10 deletions libvips/foreign/dzsave.c
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,9 @@ tile_name(Level *level, int x, int y)
save->ready->Xsize - left);
int height = VIPS_MIN(dz->tile_size * level->sub,
save->ready->Ysize - top);
gboolean is_region_full = left == 0 && top == 0 &&
width == save->ready->Xsize &&
height == save->ready->Ysize;

/* Rotation is always 0.
*/
Expand All @@ -1223,23 +1226,35 @@ tile_name(Level *level, int x, int y)
int ysize = VIPS_MIN(dz->tile_size,
level->height - y * dz->tile_size);

g_snprintf(subdir, VIPS_PATH_MAX,
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
left, top, width, height,
xsize, ysize,
rotation);
if (is_region_full)
g_snprintf(subdir, VIPS_PATH_MAX,
"full" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
xsize, ysize,
rotation);
else
g_snprintf(subdir, VIPS_PATH_MAX,
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
left, top, width, height,
xsize, ysize,
rotation);
}
else {
/* IIIF2 "size" is just real tile width, I think.
*/
int size = VIPS_MIN(dz->tile_size,
level->width - x * dz->tile_size);

g_snprintf(subdir, VIPS_PATH_MAX,
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
left, top, width, height,
size,
rotation);
if (is_region_full)
g_snprintf(subdir, VIPS_PATH_MAX,
"full" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
size,
rotation);
else
g_snprintf(subdir, VIPS_PATH_MAX,
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
left, top, width, height,
size,
rotation);
}

g_snprintf(name, VIPS_PATH_MAX, "default%s", dz->file_suffix);
Expand Down
21 changes: 21 additions & 0 deletions test/test-suite/test_foreign.py
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,27 @@ def test_dzsave(self):
assert x.width == 256
assert x.height == 256

# IIIF v2
im = pyvips.Image.black(3509, 2506, bands=3)
filename = temp_filename(self.tempdir, '')
im.dzsave(filename, layout="iiif")
assert os.path.exists(filename + "/info.json")
assert os.path.exists(filename + "/0,0,512,512/512,/0/default.jpg")
assert os.path.exists(filename + "/2560,2048,512,458/512,/0/default.jpg")
x = pyvips.Image.new_from_file(filename + "/full/439,/0/default.jpg")
assert x.width == 439
assert x.height == 314

# IIIF v3
filename = temp_filename(self.tempdir, '')
im.dzsave(filename, layout="iiif3")
assert os.path.exists(filename + "/info.json")
assert os.path.exists(filename + "/0,0,512,512/512,512/0/default.jpg")
assert os.path.exists(filename + "/2560,2048,512,458/512,458/0/default.jpg")
x = pyvips.Image.new_from_file(filename + "/full/439,314/0/default.jpg")
assert x.width == 439
assert x.height == 314

# test zip output
filename = temp_filename(self.tempdir, '.zip')
self.colour.dzsave(filename)
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy