-
Notifications
You must be signed in to change notification settings - Fork 70
/
depth-map-extraction.js
102 lines (93 loc) · 2.99 KB
/
depth-map-extraction.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import exifr from '../dist/lite.esm.js'
const isBrowser = typeof navigator === 'object'
// settings used to extract the depth map
const options = {
// We don't need TIFF, nor thumbnail, so skip this segment (enabled by default).
tiff: false,
// Depth map is stored in an XMP Extended segment (not the main one).
xmp: true,
// We need to tell exifr not to stop at the first XMP segment, but to find them all.
multiSegment: true,
// There will be mutliple XMP namespaces (GDepth, GImage) with the same properties (Mime, Data).
// We don't want them to overwrite each other.
mergeOutput: false,
}
// browser only
var dom
if (isBrowser) {
dom = {
filePicker: document.querySelector('input[type="file"]'),
log: document.querySelector('#log'),
'input-file': document.querySelector('#input-file'),
'depth-map': document.querySelector('#depth-map'),
'depth-source': document.querySelector('#depth-source'),
}
dom.filePicker.addEventListener('change', async e => {
let url = URL.createObjectURL(e.target.files[0])
extractDepthMap(url)
})
}
// do the extraction with demo file
extractDepthMap('../test/fixtures/xmp depth map.jpg')
// Node.js only
async function saveToDisk(xmpNamespace, fileName) {
let fs = await import('fs').then(fs => fs.promises)
// The depth map is stored as base64 string
let base64 = xmpNamespace.Data
let fileExt = xmpNamespace.Mime.split('/').pop()
let buffer = Buffer.from(base64, 'base64')
fs.writeFile(fileName + '.' + fileExt, buffer)
}
// Browser only
async function displayInBrowser(xmpNamespace, id) {
let base64 = xmpNamespace.Data
let mime = xmpNamespace.Mime
let img = dom[id]
img.src = `data:${mime};base64,${base64}`
}
function handleFile(xmpNamespace, fileName) {
if (isBrowser)
displayInBrowser(xmpNamespace, fileName)
else
saveToDisk(xmpNamespace, fileName)
}
async function extractDepthMap(filePath) {
// clear previous image
if (isBrowser) {
dom['input-file'].src = filePath
dom['depth-map'].src = ''
dom['depth-source'].src = ''
dom['log'].innerHTML = ''
}
// extract the data from file
let output = await exifr.parse(filePath, options)
if (output && output.GDepth) {
log('The file contains depth map')
log('GDepth.Format', output.GDepth.Format)
log('GDepth.Near', output.GDepth.Near)
log('GDepth.Far', output.GDepth.Far)
log('GDepth.Mime', output.GDepth.Mime)
// store or display the depth map image
handleFile(output.GDepth, 'depth-map')
} else {
log('The file has no depth map')
return
}
// Besides depth map, there can be original image with no blurring applied.
// NOTE: GImage can be also used for "the other eye" in VR photos
if (output && output.GImage) {
log('The file contains unmodified original photo')
log('GImage.Mime', output.GImage.Mime)
// store or display the source image
handleFile(output.GImage, 'depth-source')
} else {
log(`The file doesn't contain unmodified image`)
}
}
function log(...args) {
if (isBrowser) {
dom.log.innerHTML += args.join(' ') + '\n'
} else {
console.log(...args)
}
}