Skip to content

Commit e1092ad

Browse files
committed
Use piexif to dynamically generate density-corrected size images
1 parent 2aceef0 commit e1092ad

9 files changed

+2595
-55
lines changed

density-size-correction/density-corrected-natural-size.html

+27-17
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,36 @@
22
<body>
33
<script src="/resources/testharness.js"></script>
44
<script src="/resources/testharnessreport.js"></script>
5+
<script src="./resources/piexif.js"></script>
6+
<script src="./resources/exify.js"></script>
57
<link rel="author" title="Noam Rosenthal" href="[email protected]">
6-
<img src="resources/exif-resolution-invalid-cm.jpg" data-width="100" data-height="50" class="test-img" />
7-
<img src="resources/exif-resolution-invalid-no-match.jpg" data-width="100" data-height="50" class="test-img" />
8-
<img src="resources/exif-resolution-invalid-partial.jpg" data-width="100" data-height="50" class="test-img" />
9-
<img src="resources/exif-resolution-no-change.jpg" data-width="100" data-height="50" class="test-img" />
10-
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
11-
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
12-
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="100" class="test-img" />
13-
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
14-
<img src="resources/exif-resolution-with-orientation.jpg" data-width="100" data-height="200" class="test-img" />
158
<script>
16-
let run_test = () => {
17-
test(() => {
18-
[...document.querySelectorAll('.test-img')].forEach(img => {
19-
assert_equals(img.naturalWidth, +img.dataset.width, `Density size correction for ${img.src}`);
20-
assert_equals(img.naturalHeight, +img.dataset.height, `Density size correction for ${img.src}`);
21-
})
22-
}, "Test the image dimensions of different EXIF scenarios");
9+
async function test_valid(input) {
10+
const image = await createImageWithMetadata(input)
11+
assert_equals(image.naturalWidth, input.preferredWidth)
12+
assert_equals(image.naturalHeight, input.preferredHeight)
2313
}
24-
window.addEventListener("load", run_test);
14+
async function test_invalid(input) {
15+
const image = await createImageWithMetadata(input)
16+
assert_equals(image.naturalWidth, input.width)
17+
assert_equals(image.naturalHeight, input.height)
18+
}
19+
20+
async function test() {
21+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
22+
await test_valid({width: 10, height: 20, preferredWidth: 2, preferredHeight: 4, resolutionX: 360, resolutionY: 360, resolutionUnit: 2})
23+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 10, resolutionX: 36, resolutionY: 144, resolutionUnit: 2})
24+
await test_valid({width: 10, height: 20, preferredWidth: 10, preferredHeight: 40, resolutionX: 72, resolutionY: 36, resolutionUnit: 2})
25+
await test_valid({width: 30, height: 30, preferredWidth: 90, preferredHeight: 30, resolutionX: 24, resolutionY: 72, resolutionUnit: 2})
26+
27+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
28+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
29+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
30+
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
31+
}
32+
33+
promise_test(test)
34+
2535
</script>
2636

2737
</body>

density-size-correction/density-corrected-size-rendering-ref.html

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@
1818
.box { width: 200px; height: 200px; display: inline-block; }
1919
.tiled {background-repeat: repeat; }
2020
.stretch {background-repeat: no-repeat; background-size: contain; }
21-
.non-uniform-bg.stretch { background-size: 200px 200px; clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%, 0 0) }
21+
.non-uniform-bg.stretch { background-size: 100px 200px; background-size: scale-down; }
2222
</style>
2323
<br/>
2424
<div class="default-bg tiled box"></div>
2525
<div class="lores-bg tiled box"></div>
2626
<div class="hires-bg tiled box"></div>
2727
<div class="non-uniform-bg tiled box"></div>
28+
<br/>
2829
<div class="lores-bg stretch box"></div>
2930
<div class="default-bg stretch box"></div>
3031
<div class="non-uniform-bg stretch box"></div>
3132
<div class="lores-after box">
3233
<img src="resources/exif-resolution-none.jpg" width="200" />
3334
</div>
35+
<br/>
3436
<div class="default-after box"></div>
3537
</body>
3638
</html>
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,46 @@
11
<!DOCTYPE html>
2+
<head>
3+
<title>Density corrected size: rendering</title>
4+
<link rel="author" title="Noam Rosenthal" href="[email protected]">
5+
<link rel="match" href="density-corrected-size-rendering-ref.html" />
6+
<meta name="assert" content="Assert that images with EXIF density-corrected-size are rendered correctly">
7+
<script src="./resources/piexif.js"></script>
8+
<script src="./resources/exify.js"></script>
9+
</head>
210
<body>
3-
<link rel="author" title="Noam Rosenthal" href="[email protected]">
4-
<link rel="match" href="density-corrected-size-rendering-ref.html" />
5-
<meta name="assert" content="Assert that images with EXIF density-corrected-size are rendered correctly">
6-
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
7-
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
8-
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="10" class="test-img" />
9-
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
10-
<style>
11-
body {
12-
--lores: url(resources/exif-resolution-valid-lores.jpg);
13-
--hires: url(resources/exif-resolution-valid-hires.jpg);
14-
--default: url(resources/exif-resolution-none.jpg);
15-
--non-uniform: url(resources/exif-resolution-valid-non-uniform.jpg);
16-
}
17-
.default-bg {background-image: var(--default); }
18-
.lores-bg {background-image: var(--lores); }
19-
.lores-after::after {content: var(--lores); }
20-
.default-after::after {content: var(--default); }
21-
.hires-bg {background-image: var(--hires); }
22-
.invalid-bg {background-image: var(--invalid); }
23-
.non-uniform-bg {background-image: var(--non-uniform); }
24-
.box { width: 200px; height: 200px; display: inline-block; }
25-
.tiled {background-repeat: repeat; }
26-
.stretch {background-repeat: no-repeat; background-size: contain; }
27-
</style>
28-
<br/>
29-
<div class="default-bg tiled box"></div>
30-
<div class="lores-bg tiled box"></div>
31-
<div class="hires-bg tiled box"></div>
32-
<div class="non-uniform-bg tiled box"></div>
33-
<div class="lores-bg stretch box"></div>
34-
<div class="default-bg stretch box"></div>
35-
<div class="non-uniform-bg stretch box"></div>
36-
<div class="lores-after box"></div>
37-
<div class="default-after box"></div>
11+
<style>
12+
body {
13+
--lores: url(resources/exif-resolution-valid-lores.jpg);
14+
--hires: url(resources/exif-resolution-valid-hires.jpg);
15+
--default: url(resources/exif-resolution-none.jpg);
16+
--non-uniform: url(resources/exif-resolution-valid-non-uniform.jpg);
17+
}
18+
.default-bg {background-image: var(--default); }
19+
.lores-bg {background-image: var(--lores); }
20+
.lores-after::after {content: var(--lores); }
21+
.default-after::after {content: var(--default); }
22+
.hires-bg {background-image: var(--hires); }
23+
.invalid-bg {background-image: var(--invalid); }
24+
.non-uniform-bg {background-image: var(--non-uniform); }
25+
.box { width: 200px; height: 200px; display: inline-block; }
26+
.tiled {background-repeat: repeat; }
27+
.stretch {background-repeat: no-repeat; background-size: contain; }
28+
</style>
29+
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
30+
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
31+
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="10" class="test-img" />
32+
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
33+
<br/>
34+
<div class="default-bg tiled box"></div>
35+
<div class="lores-bg tiled box"></div>
36+
<div class="hires-bg tiled box"></div>
37+
<div class="non-uniform-bg tiled box"></div>
38+
<br/>
39+
<div class="lores-bg stretch box"></div>
40+
<div class="default-bg stretch box"></div>
41+
<div class="non-uniform-bg stretch box"></div>
42+
<div class="lores-after box"></div>
43+
<br />
44+
<div class="default-after box"></div>
3845
</body>
3946
</html>

density-size-correction/density-corrected-various-elements.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<html>
22
<head>
3-
<title>Content-DPR: various elements</title>
3+
<title>Density corrected size: various elements</title>
44
<link rel="author" title="Noam Rosenthal" href="[email protected]">
55
<link rel="match" href="density-corrected-various-elements-ref.html" />
6-
<meta name="assert" content="Assert that content-dpr is taken into account for images in all relevant elements (input/canvas/svg/video-poster)">
6+
<meta name="assert" content="Assert that density-corrected size in EXIF is taken into account for images in all relevant elements (input/canvas/svg/video-poster)">
77
<style>
88
.row {
99
display: flex;
Binary file not shown.
Binary file not shown.
Binary file not shown.
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
function createImageWithMetadata({
2+
width,
3+
height,
4+
preferredWidth,
5+
preferredHeight,
6+
resolutionX,
7+
resolutionY,
8+
resolutionUnit,
9+
orientation
10+
}) {
11+
const canvas = document.createElement('canvas')
12+
canvas.width = width || 100
13+
canvas.height = height || 100
14+
const ctx = canvas.getContext('2d')
15+
ctx.fillColor = 'green'
16+
ctx.fillRect(0, 0, canvas.width, canvas.height)
17+
const original = canvas.toDataURL('image/jpeg')
18+
const root = {}
19+
const exif = {}
20+
if (orientation !== undefined)
21+
root[piexif.ExifIFD.Orientation] = orientation
22+
if (resolutionX !== undefined)
23+
root[piexif.ImageIFD.XResolution] = [resolutionX, 1]
24+
if (resolutionY !== undefined)
25+
root[piexif.ImageIFD.YResolution] = [resolutionY, 1]
26+
if (resolutionUnit !== undefined)
27+
root[piexif.ImageIFD.ResolutionUnit] = resolutionUnit
28+
if (preferredWidth !== undefined)
29+
exif[piexif.ExifIFD.PixelXDimension] = preferredWidth
30+
if (preferredHeight !== undefined)
31+
exif[piexif.ExifIFD.PixelYDimension] = preferredHeight
32+
const exifString = piexif.dump({'0th': root, 'Exif': exif})
33+
const newDataUrl = piexif.insert(exifString, original)
34+
const image = new Image()
35+
image.src = newDataUrl
36+
return new Promise(resolve => {
37+
image.onload = () => resolve(image);
38+
})
39+
}

0 commit comments

Comments
 (0)