-
Notifications
You must be signed in to change notification settings - Fork 0
/
resize.ts
133 lines (106 loc) · 3.8 KB
/
resize.ts
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
import sharp from 'sharp';
import { ExifOptions } from './exifOptions';
import { doSync, JSONObject } from 'do-sync';
import { Size, Sized } from 'types';
export interface IOutput extends JSONObject {
type: string
}
export interface JSONError extends Error, JSONObject {
type: "error",
context?: Input
}
export interface ResizeRequest extends JSONObject {
filepath: string,
exif?: ExifOptions,
sizes: Size[]
}
export interface Input extends JSONObject {
requests: ResizeRequest[]
}
export interface SizedImage extends JSONObject, Sized {
base64: string
}
interface ExifJSON extends JSONObject {}
export interface ResizeResponse extends JSONObject {
sizes: SizedImage[]
exif?: ExifJSON
}
export interface Success extends IOutput {
type: 'success'
responses: ResizeResponse[]
}
export const asyncResize:
(Input: Input) => Promise<Success | JSONError>
=
async({ requests }) => {
const main = async () => {
let Sharp: typeof sharp;
Sharp = require('sharp') as any;
const boolXor:
(a: boolean, b: boolean) => boolean
=
(a, b) => (a && !b) || (!b && a)
;
const _handleImage:
(rq: ResizeRequest) => Promise<ResizeResponse>
=
async ({ filepath, exif: exifReq, sizes }) => {
let img: sharp.Sharp = await Sharp(filepath);
const buf = await img.toBuffer();
const { width, height } = await img.metadata();
if (width == undefined || height == undefined)
throw new Error("could not get width or height of image");
// only resize smaller
const validSizes = sizes.filter((size: Size) => {
if (typeof size == "string") return true;
const [w, h] = size;
const target = { w, h };
return (target.w <= width) || (target.h <= height)
});
const resizedImages = await Promise.all(validSizes.map<Promise<SizedImage>>(async (size: Size, n, a) => {
let [w, h] = size == "original"?
[width, height]: size;
const resized = await Sharp(buf).resize(w, h, {
fit: 'inside',
}).jpeg({
progressive: true
});
const base64 = (await resized.toBuffer()).toString('base64');
return {
width: w, height: h,
base64
}
}));
return {
sizes: resizedImages
}
}
const handleImage: typeof _handleImage = async (...args) => {
return _handleImage(...args);
}
const responses: (ResizeResponse)[] =
await Promise.all(requests.map(handleImage));
return responses;
}
try {
return {
type: 'success',
responses: await main()
}
} catch (e) {
if (!(e instanceof Error)) return {
type: 'error',
name: 'weird error',
message: 'something very odd has happened',
context: { requests }
}
const { name, message, stack } = e;
return {
name, message, stack, type: 'error',
context: { requests }
}
}
}
;
export const resize = doSync(asyncResize);
export default resize;