/
label.js
149 lines (122 loc) · 3.63 KB
/
label.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const cp = require('child_process')
const fsp = require('fs').promises
const AWS = require('aws-sdk')
const util = require('util')
const path = require('path')
AWS.config.update({ region: 'eu-west-1' })
const exec = util.promisify(cp.exec)
const s3 = new AWS.S3({ apiVersion: '2006-03-01' })
exports.handler = async (event) => {
let record = event.Records[0]
let rand = Math.random().toString(32).substr(2)
// filename without path and also without extension
let basename = path.basename(record.s3.object.key, path.extname(record.s3.object.key))
let data = {
region: record.awsRegion,
bucket: record.s3.bucket.name,
key: record.s3.object.key,
input: `/tmp/${rand}`,
output: `/tmp/convert-${rand}`,
converted: `converted/${basename}.jpg`
}
try {
await getLabel(data)
await getUpload(data)
await compute(data)
await draw(data)
await putConverted(data)
return {
statusCode: 200,
body: `https://${data.bucket}.s3.${data.region}.amazonaws.com/${data.converted}`,
}
} catch (err) {
throw new Error(err)
}
}
// get the label JSON object from S3
async function getLabel(data) {
let label = await s3
.getObject({
Bucket: data.bucket,
Key: data.key
})
.promise()
var json = JSON.parse(label.Body)
data.upload = json.Key
// if bird, cat or dog previously found
if (json.Instance != null) {
data.name = json.Name
data.instance = json.Instance
}
return Promise.resolve(data)
}
// get the uploaded image object from S3 and write it to /tmp
async function getUpload(data) {
let upload = await s3
.getObject({
Bucket: data.bucket,
Key: data.upload
})
.promise()
return fsp.writeFile(data.input, upload.Body)
}
// compute data for the image
async function compute(data) {
// get image width and height
let size = await exec(`/opt/bin/identify -format '%w %h' ${data.input}`)
let arr = size.stdout.split(' ')
let iw = parseFloat(arr[0])
let ih = parseFloat(arr[1])
// imagemagick rectangle coords
if (data.instance != null) {
let left = Math.round(iw * data.instance.BoundingBox.Left)
let top = Math.round(ih * data.instance.BoundingBox.Top)
let width = left + Math.round(iw * data.instance.BoundingBox.Width)
let height = top + Math.round(ih * data.instance.BoundingBox.Height)
let outleft = left - 30
let outtop = top - 30
let outwidth = width + 30
let outheight = height + 30
// blue for bird
let color = 'blue'
if (data.name == 'Cat') color = 'red'
else if (data.name == 'Dog') color = 'green'
data.draw = {
left,
top,
width,
height,
outleft,
outtop,
outwidth,
outheight,
color
}
}
return Promise.resolve(data)
}
// draw the rectangle or convert to gray
async function draw(data) {
let cmd = ''
if (data.instance != null) {
cmd = `/opt/bin/convert ${data.input} ` +
`\\\( +clone -fill white -colorize 100 -fill ${data.draw.color} -draw "rectangle ${data.draw.outleft},${data.draw.outtop} ${data.draw.outwidth},${data.draw.outheight}" ` +
`-fill white -draw "rectangle ${data.draw.left},${data.draw.top} ${data.draw.width},${data.draw.height}" \\\) -compose multiply -composite ${data.output}`
} else {
cmd = `/opt/bin/convert ${data.input} -colorspace Gray ${data.output}`
}
return exec(cmd)
}
// put an object from /tmp to S3
async function putConverted(data) {
let body = await fsp.readFile(data.output)
return s3
.putObject({
Body: body,
Bucket: data.bucket,
Key: data.converted,
ACL: 'public-read',
ContentType: 'image/jpeg'
})
.promise()
}