Skip to content

Commit

Permalink
add support for relative urls in IIIF images
Browse files Browse the repository at this point in the history
fixes #215
  • Loading branch information
lovasoa committed Sep 20, 2023
1 parent 3ca94c7 commit 988dc90
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 66 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dezoomify-rs"
version = "2.11.1"
version = "2.11.2"
authors = ["lovasoa"]
edition = "2021"
license-file = "LICENSE"
Expand Down
75 changes: 49 additions & 26 deletions src/iiif/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ fn zoom_levels(url: &str, raw_info: &[u8]) -> Result<ZoomLevels, IIIFError> {
.filter(|info| {
let keep = info.has_distinctive_iiif_properties();
if keep {
debug!("keeping image info {:?} because it has distinctive IIIF properties", info)
debug!(
"keeping image info {:?} because it has distinctive IIIF properties",
info
)
} else {
info!("dropping level {:?}", info)
}
Expand All @@ -62,9 +65,12 @@ fn zoom_levels(url: &str, raw_info: &[u8]) -> Result<ZoomLevels, IIIFError> {
if levels.is_empty() {
Err(e.into())
} else {
info!("No normal info.json parsing failed ({}), \
info!(
"No normal info.json parsing failed ({}), \
but {} inline json5 zoom level(s) were found.",
e, levels.len());
e,
levels.len()
);
Ok(levels)
}
}
Expand All @@ -73,6 +79,7 @@ fn zoom_levels(url: &str, raw_info: &[u8]) -> Result<ZoomLevels, IIIFError> {

fn zoom_levels_from_info(url: &str, mut image_info: ImageInfo) -> ZoomLevels {
image_info.remove_test_id();
image_info.resolve_relative_urls(url);
let img = Arc::new(image_info);
let tiles = img.tiles();
let base_url = &Arc::from(url.replace("/info.json", ""));
Expand All @@ -83,21 +90,24 @@ fn zoom_levels_from_info(url: &str, mut image_info: ImageInfo) -> ZoomLevels {
let quality = Arc::from(img.best_quality());
let format = Arc::from(img.best_format());
let size_format = img.preferred_size_format();
info!("Chose the following image parameters: tile_size=({}) quality={} format={}",
tile_size, quality, format);
info!(
"Chose the following image parameters: tile_size=({}) quality={} format={}",
tile_size, quality, format
);
let page_info = &img; // Required to allow the move
tile_info
.scale_factors
.iter()
.map(move |&scale_factor| IIIFZoomLevel {
tile_info.scale_factors.iter().map(move |&scale_factor| {
let zoom_level = IIIFZoomLevel {
scale_factor,
tile_size,
page_info: Arc::clone(page_info),
base_url: Arc::clone(base_url),
quality: Arc::clone(&quality),
format: Arc::clone(&format),
size_format,
})
};
debug!("Found zoom level {zoom_level:?}: page_info: {page_info:?}, tile_size: {tile_size:?}, scale_factor: {scale_factor}, base_url: {base_url}, quality: {quality}, format: {format}, size_format: {size_format:?}");
zoom_level
})
})
.into_zoom_levels();
levels
Expand Down Expand Up @@ -129,20 +139,32 @@ impl TilesRect for IIIFZoomLevel {
let tile_size = scaled_tile_size / self.scale_factor;
format!(
"{base}/{x},{y},{img_w},{img_h}/{tile_size}/{rotation}/{quality}.{format}",
base = self.page_info.id.as_deref().unwrap_or_else(|| self.base_url.as_ref()),
base = self
.page_info
.id
.as_deref()
.unwrap_or_else(|| self.base_url.as_ref()),
x = xy_pos.x,
y = xy_pos.y,
img_w = scaled_tile_size.x,
img_h = scaled_tile_size.y,
tile_size = TileSizeFormatter { w: tile_size.x, h: tile_size.y, format: self.size_format },
tile_size = TileSizeFormatter {
w: tile_size.x,
h: tile_size.y,
format: self.size_format
},
rotation = 0,
quality = self.quality,
format = self.format,
)
}
}

struct TileSizeFormatter { w: u32, h: u32, format: TileSizeFormat }
struct TileSizeFormatter {
w: u32,
h: u32,
format: TileSizeFormat,
}

impl std::fmt::Display for TileSizeFormatter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down Expand Up @@ -202,7 +224,6 @@ fn test_tiles() {
])
}


#[test]
fn test_tiles_max_area_filter() {
// Predefined tile size (1024x1024) is over maxArea (262144 = 512x512).
Expand All @@ -219,12 +240,15 @@ fn test_tiles_max_area_filter() {
.into_iter()
.map(|t| t.url)
.collect();
assert_eq!(tiles, vec![
"http://ophir.dev/0,0,512,512/512,512/0/default.jpg",
"http://ophir.dev/512,0,512,512/512,512/0/default.jpg",
"http://ophir.dev/0,512,512,512/512,512/0/default.jpg",
"http://ophir.dev/512,512,512,512/512,512/0/default.jpg",
])
assert_eq!(
tiles,
vec![
"http://ophir.dev/0,0,512,512/512,512/0/default.jpg",
"http://ophir.dev/512,0,512,512/512,512/0/default.jpg",
"http://ophir.dev/0,512,512,512/512,512/0/default.jpg",
"http://ophir.dev/512,512,512,512/512,512/0/default.jpg",
]
)
}

#[test]
Expand Down Expand Up @@ -259,7 +283,10 @@ fn test_false_positive() {
};
"#;
let res = zoom_levels("https://orion2020v5b.spaceforeverybody.com/", data);
assert!(res.is_err(), "openseadragon zoomify image should not be misdetected");
assert!(
res.is_err(),
"openseadragon zoomify image should not be misdetected"
);
}

#[test]
Expand All @@ -279,11 +306,7 @@ fn test_qualities() {
let mut levels = zoom_levels("test.com", data).unwrap();
let level = &mut levels[0];
assert_eq!(level.size_hint(), Some(Vec2d { x: 515, y: 381 }));
let tiles: Vec<String> = level
.next_tiles(None)
.into_iter()
.map(|t| t.url)
.collect();
let tiles: Vec<String> = level.next_tiles(None).into_iter().map(|t| t.url).collect();
assert_eq!(tiles, vec![
"https://images.britishart.yale.edu/iiif/fd470c3e-ead0-4878-ac97-d63295753f82/0,0,5156,3816/515,381/0/native.png",
])
Expand Down
7 changes: 7 additions & 0 deletions src/iiif/tile_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use regex::Regex;
use serde::{Deserialize, Serialize};

use crate::Vec2d;
use crate::network::resolve_relative;

#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ImageInfo {
Expand Down Expand Up @@ -153,6 +154,12 @@ impl ImageInfo {
}
}
}

pub fn resolve_relative_urls(&mut self, base: &str) {
if let Some(id) = &self.id {
self.id = Some(resolve_relative(base, id))
}
}
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
Expand Down
Loading

0 comments on commit 988dc90

Please sign in to comment.