Skip to content

Commit

Permalink
Use piexif to dynamically generate density-corrected size images
Browse files Browse the repository at this point in the history
  • Loading branch information
noamr committed Jun 1, 2020
1 parent 2aceef0 commit e1092ad
Show file tree
Hide file tree
Showing 9 changed files with 2,595 additions and 55 deletions.
44 changes: 27 additions & 17 deletions density-size-correction/density-corrected-natural-size.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,36 @@
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./resources/piexif.js"></script>
<script src="./resources/exify.js"></script>
<link rel="author" title="Noam Rosenthal" href="[email protected]">
<img src="resources/exif-resolution-invalid-cm.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-invalid-no-match.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-invalid-partial.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-no-change.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="100" class="test-img" />
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
<img src="resources/exif-resolution-with-orientation.jpg" data-width="100" data-height="200" class="test-img" />
<script>
let run_test = () => {
test(() => {
[...document.querySelectorAll('.test-img')].forEach(img => {
assert_equals(img.naturalWidth, +img.dataset.width, `Density size correction for ${img.src}`);
assert_equals(img.naturalHeight, +img.dataset.height, `Density size correction for ${img.src}`);
})
}, "Test the image dimensions of different EXIF scenarios");
async function test_valid(input) {
const image = await createImageWithMetadata(input)
assert_equals(image.naturalWidth, input.preferredWidth)
assert_equals(image.naturalHeight, input.preferredHeight)
}
window.addEventListener("load", run_test);
async function test_invalid(input) {
const image = await createImageWithMetadata(input)
assert_equals(image.naturalWidth, input.width)
assert_equals(image.naturalHeight, input.height)
}

async function test() {
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 2, preferredHeight: 4, resolutionX: 360, resolutionY: 360, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 10, resolutionX: 36, resolutionY: 144, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 10, preferredHeight: 40, resolutionX: 72, resolutionY: 36, resolutionUnit: 2})
await test_valid({width: 30, height: 30, preferredWidth: 90, preferredHeight: 30, resolutionX: 24, resolutionY: 72, resolutionUnit: 2})

await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
await test_valid({width: 10, height: 20, preferredWidth: 20, preferredHeight: 40, resolutionX: 36, resolutionY: 36, resolutionUnit: 2})
}

promise_test(test)

</script>

</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@
.box { width: 200px; height: 200px; display: inline-block; }
.tiled {background-repeat: repeat; }
.stretch {background-repeat: no-repeat; background-size: contain; }
.non-uniform-bg.stretch { background-size: 200px 200px; clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%, 0 0) }
.non-uniform-bg.stretch { background-size: 100px 200px; background-size: scale-down; }
</style>
<br/>
<div class="default-bg tiled box"></div>
<div class="lores-bg tiled box"></div>
<div class="hires-bg tiled box"></div>
<div class="non-uniform-bg tiled box"></div>
<br/>
<div class="lores-bg stretch box"></div>
<div class="default-bg stretch box"></div>
<div class="non-uniform-bg stretch box"></div>
<div class="lores-after box">
<img src="resources/exif-resolution-none.jpg" width="200" />
</div>
<br/>
<div class="default-after box"></div>
</body>
</html>
77 changes: 42 additions & 35 deletions density-size-correction/density-corrected-size-rendering.html
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
<!DOCTYPE html>
<head>
<title>Density corrected size: rendering</title>
<link rel="author" title="Noam Rosenthal" href="[email protected]">
<link rel="match" href="density-corrected-size-rendering-ref.html" />
<meta name="assert" content="Assert that images with EXIF density-corrected-size are rendered correctly">
<script src="./resources/piexif.js"></script>
<script src="./resources/exify.js"></script>
</head>
<body>
<link rel="author" title="Noam Rosenthal" href="[email protected]">
<link rel="match" href="density-corrected-size-rendering-ref.html" />
<meta name="assert" content="Assert that images with EXIF density-corrected-size are rendered correctly">
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="10" class="test-img" />
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
<style>
body {
--lores: url(resources/exif-resolution-valid-lores.jpg);
--hires: url(resources/exif-resolution-valid-hires.jpg);
--default: url(resources/exif-resolution-none.jpg);
--non-uniform: url(resources/exif-resolution-valid-non-uniform.jpg);
}
.default-bg {background-image: var(--default); }
.lores-bg {background-image: var(--lores); }
.lores-after::after {content: var(--lores); }
.default-after::after {content: var(--default); }
.hires-bg {background-image: var(--hires); }
.invalid-bg {background-image: var(--invalid); }
.non-uniform-bg {background-image: var(--non-uniform); }
.box { width: 200px; height: 200px; display: inline-block; }
.tiled {background-repeat: repeat; }
.stretch {background-repeat: no-repeat; background-size: contain; }
</style>
<br/>
<div class="default-bg tiled box"></div>
<div class="lores-bg tiled box"></div>
<div class="hires-bg tiled box"></div>
<div class="non-uniform-bg tiled box"></div>
<div class="lores-bg stretch box"></div>
<div class="default-bg stretch box"></div>
<div class="non-uniform-bg stretch box"></div>
<div class="lores-after box"></div>
<div class="default-after box"></div>
<style>
body {
--lores: url(resources/exif-resolution-valid-lores.jpg);
--hires: url(resources/exif-resolution-valid-hires.jpg);
--default: url(resources/exif-resolution-none.jpg);
--non-uniform: url(resources/exif-resolution-valid-non-uniform.jpg);
}
.default-bg {background-image: var(--default); }
.lores-bg {background-image: var(--lores); }
.lores-after::after {content: var(--lores); }
.default-after::after {content: var(--default); }
.hires-bg {background-image: var(--hires); }
.invalid-bg {background-image: var(--invalid); }
.non-uniform-bg {background-image: var(--non-uniform); }
.box { width: 200px; height: 200px; display: inline-block; }
.tiled {background-repeat: repeat; }
.stretch {background-repeat: no-repeat; background-size: contain; }
</style>
<img src="resources/exif-resolution-none.jpg" data-width="100" data-height="50" class="test-img" />
<img src="resources/exif-resolution-valid-hires.jpg" data-width="50" data-height="25" class="test-img" />
<img src="resources/exif-resolution-valid-lores.jpg" data-width="200" data-height="10" class="test-img" />
<img src="resources/exif-resolution-valid-non-uniform.jpg" data-width="50" data-height="100" class="test-img" />
<br/>
<div class="default-bg tiled box"></div>
<div class="lores-bg tiled box"></div>
<div class="hires-bg tiled box"></div>
<div class="non-uniform-bg tiled box"></div>
<br/>
<div class="lores-bg stretch box"></div>
<div class="default-bg stretch box"></div>
<div class="non-uniform-bg stretch box"></div>
<div class="lores-after box"></div>
<br />
<div class="default-after box"></div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<html>
<head>
<title>Content-DPR: various elements</title>
<title>Density corrected size: various elements</title>
<link rel="author" title="Noam Rosenthal" href="[email protected]">
<link rel="match" href="density-corrected-various-elements-ref.html" />
<meta name="assert" content="Assert that content-dpr is taken into account for images in all relevant elements (input/canvas/svg/video-poster)">
<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)">
<style>
.row {
display: flex;
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
39 changes: 39 additions & 0 deletions density-size-correction/resources/exify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
function createImageWithMetadata({
width,
height,
preferredWidth,
preferredHeight,
resolutionX,
resolutionY,
resolutionUnit,
orientation
}) {
const canvas = document.createElement('canvas')
canvas.width = width || 100
canvas.height = height || 100
const ctx = canvas.getContext('2d')
ctx.fillColor = 'green'
ctx.fillRect(0, 0, canvas.width, canvas.height)
const original = canvas.toDataURL('image/jpeg')
const root = {}
const exif = {}
if (orientation !== undefined)
root[piexif.ExifIFD.Orientation] = orientation
if (resolutionX !== undefined)
root[piexif.ImageIFD.XResolution] = [resolutionX, 1]
if (resolutionY !== undefined)
root[piexif.ImageIFD.YResolution] = [resolutionY, 1]
if (resolutionUnit !== undefined)
root[piexif.ImageIFD.ResolutionUnit] = resolutionUnit
if (preferredWidth !== undefined)
exif[piexif.ExifIFD.PixelXDimension] = preferredWidth
if (preferredHeight !== undefined)
exif[piexif.ExifIFD.PixelYDimension] = preferredHeight
const exifString = piexif.dump({'0th': root, 'Exif': exif})
const newDataUrl = piexif.insert(exifString, original)
const image = new Image()
image.src = newDataUrl
return new Promise(resolve => {
image.onload = () => resolve(image);
})
}
Loading

0 comments on commit e1092ad

Please sign in to comment.