Skip to content

Commit 2e78894

Browse files
authored
dzsave: IIIF: use named region of 'full' when no crop takes place (#4578)
Should improve conformance with IIIF v2 and v3, the specs of which both mandate support for the 'full' region. Also adds a couple of initial, basic IIIF layout tests
1 parent d27660b commit 2e78894

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ master
99
- text: prevent use of rgba subpixel anti-aliasing [lovell]
1010
- tiffsave: always apply resolution unit conversion [kleisauke]
1111
- cache: suppress invalidation errors in release builds [kleisauke]
12+
- dzsave: IIIF: use named region of 'full' when no crop takes place [lovell]
1213

1314
5/6/25 8.17.0
1415

libvips/foreign/dzsave.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,9 @@ tile_name(Level *level, int x, int y)
12121212
save->ready->Xsize - left);
12131213
int height = VIPS_MIN(dz->tile_size * level->sub,
12141214
save->ready->Ysize - top);
1215+
gboolean is_region_full = left == 0 && top == 0 &&
1216+
width == save->ready->Xsize &&
1217+
height == save->ready->Ysize;
12151218

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

1226-
g_snprintf(subdir, VIPS_PATH_MAX,
1227-
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
1228-
left, top, width, height,
1229-
xsize, ysize,
1230-
rotation);
1229+
if (is_region_full)
1230+
g_snprintf(subdir, VIPS_PATH_MAX,
1231+
"full" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
1232+
xsize, ysize,
1233+
rotation);
1234+
else
1235+
g_snprintf(subdir, VIPS_PATH_MAX,
1236+
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d,%d" G_DIR_SEPARATOR_S "%d",
1237+
left, top, width, height,
1238+
xsize, ysize,
1239+
rotation);
12311240
}
12321241
else {
12331242
/* IIIF2 "size" is just real tile width, I think.
12341243
*/
12351244
int size = VIPS_MIN(dz->tile_size,
12361245
level->width - x * dz->tile_size);
12371246

1238-
g_snprintf(subdir, VIPS_PATH_MAX,
1239-
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
1240-
left, top, width, height,
1241-
size,
1242-
rotation);
1247+
if (is_region_full)
1248+
g_snprintf(subdir, VIPS_PATH_MAX,
1249+
"full" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
1250+
size,
1251+
rotation);
1252+
else
1253+
g_snprintf(subdir, VIPS_PATH_MAX,
1254+
"%d,%d,%d,%d" G_DIR_SEPARATOR_S "%d," G_DIR_SEPARATOR_S "%d",
1255+
left, top, width, height,
1256+
size,
1257+
rotation);
12431258
}
12441259

12451260
g_snprintf(name, VIPS_PATH_MAX, "default%s", dz->file_suffix);

test/test-suite/test_foreign.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,27 @@ def test_dzsave(self):
14071407
assert x.width == 256
14081408
assert x.height == 256
14091409

1410+
# IIIF v2
1411+
im = pyvips.Image.black(3509, 2506, bands=3)
1412+
filename = temp_filename(self.tempdir, '')
1413+
im.dzsave(filename, layout="iiif")
1414+
assert os.path.exists(filename + "/info.json")
1415+
assert os.path.exists(filename + "/0,0,512,512/512,/0/default.jpg")
1416+
assert os.path.exists(filename + "/2560,2048,512,458/512,/0/default.jpg")
1417+
x = pyvips.Image.new_from_file(filename + "/full/439,/0/default.jpg")
1418+
assert x.width == 439
1419+
assert x.height == 314
1420+
1421+
# IIIF v3
1422+
filename = temp_filename(self.tempdir, '')
1423+
im.dzsave(filename, layout="iiif3")
1424+
assert os.path.exists(filename + "/info.json")
1425+
assert os.path.exists(filename + "/0,0,512,512/512,512/0/default.jpg")
1426+
assert os.path.exists(filename + "/2560,2048,512,458/512,458/0/default.jpg")
1427+
x = pyvips.Image.new_from_file(filename + "/full/439,314/0/default.jpg")
1428+
assert x.width == 439
1429+
assert x.height == 314
1430+
14101431
# test zip output
14111432
filename = temp_filename(self.tempdir, '.zip')
14121433
self.colour.dzsave(filename)

0 commit comments

Comments
 (0)
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