-
Notifications
You must be signed in to change notification settings - Fork 0
/
EXIF_Orientation.html
120 lines (113 loc) · 4 KB
/
EXIF_Orientation.html
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<!--https://qiita.com/zaru/items/0ce7757c721ebd170683-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div><input type="file" id="file" /></div>
<script>
// const getOrientation = buffer => {
// const dv = new DataView(buffer)
// if (dv.getUint16(2) !== 65505) {
// return 0
// }
// const littleEndian = dv.getUint8(12) === 73
// const count = dv.getUint16(20, littleEndian)
// for (let i = 0; i < count; i++) {
// const start = 22 + i * 12
// const tag = dv.getUint16(start, littleEndian)
// if (tag === 274) {
// const value = dv.getUint16(start + 8, littleEndian)
// return value
// }
// }
// return 0
// }
const getOrientation = buffer => {
const dv = new DataView(buffer)
let app1MarkerStart = 2
// もし JFIF で APP0 Marker がある場合は APP1 Marker の取得位置をずらす
if (dv.getUint16(app1MarkerStart) !== 65505) {
const length = dv.getUint16(4)
app1MarkerStart += length + 2
}
if (dv.getUint16(app1MarkerStart) !== 65505) {
return 0
}
// エンディアンを取得
const littleEndian = dv.getUint8(app1MarkerStart + 10) === 73
// フィールドの数を確認
const count = dv.getUint16(app1MarkerStart + 18, littleEndian)
for (let i = 0; i < count; i++) {
const start = app1MarkerStart + 20 + i * 12
const tag = dv.getUint16(start, littleEndian)
// Orientation の Tag は 274
if (tag === 274) {
// Orientation は Type が SHORT なので 2byte だけ読む
return dv.getUint16(start + 8, littleEndian)
}
}
return 0
}
const arrayBufferToDataURL = arrBuf => {
const blob = new Blob([arrBuf], { type: 'image/jpeg' })
return window.URL.createObjectURL(blob)
}
const embedImageTag = dataURL => {
const img = new Image()
img.src = dataURL
img.width = '200'
document.body.appendChild(img)
return img
}
const createTransformedCanvas = (orientation, img) => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
if ([5,6,7,8].indexOf(orientation) > -1) {
canvas.width = img.height
canvas.height = img.width
} else {
canvas.width = img.width
canvas.height = img.height
}
switch (orientation) {
case 2: ctx.transform(-1, 0, 0, 1, img.width, 0); break
case 3: ctx.transform(-1, 0, 0, -1, img.width, img.height); break
case 4: ctx.transform(1, 0, 0, -1, 0, img.height); break
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break
case 6: ctx.transform(0, 1, -1, 0, img.height, 0); break
case 7: ctx.transform(0, -1, -1, 0, img.height, img.width); break
case 8: ctx.transform(0, -1, 1, 0, 0, img.width); break
}
ctx.drawImage(img, 0, 0)
return canvas
}
document.getElementById('file').addEventListener('change', (e) => {
const file = e.target.files[0]
const reader = new FileReader()
reader.addEventListener('load', () => {
const orientation = getOrientation(reader.result)
if (orientation === 0 || orientation === 1) {
const data = arrayBufferToDataURL(reader.result)
const img = embedImageTag(data)
img.addEventListener('load', () => {
window.URL.revokeObjectURL(data)
})
} else {
const img = new Image()
img.src = arrayBufferToDataURL(reader.result)
img.addEventListener('load', () => {
const canvas = createTransformedCanvas(orientation, img)
window.URL.revokeObjectURL(img.src)
embedImageTag(canvas.toDataURL('image/jpeg'))
})
}
})
reader.readAsArrayBuffer(file)
})
</script>
</body>
</html>