1 | const jpegjs = require('jpeg-js')
|
2 |
|
3 | const m = {}
|
4 | module.exports = m
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | m.rotateBuffer = (buffer, orientation, quality, maxResolutionInMP, maxMemoryUsageInMB) => {
|
11 | let jpeg = null
|
12 | const options = {}
|
13 | if (maxResolutionInMP !== null) {
|
14 | options.maxResolutionInMP = maxResolutionInMP
|
15 | }
|
16 | if (maxMemoryUsageInMB !== null) {
|
17 | options.maxMemoryUsageInMB = maxMemoryUsageInMB
|
18 | }
|
19 | try {
|
20 | jpeg = jpegjs.decode(buffer, options)
|
21 | } catch (error) {
|
22 | return Promise.reject(error)
|
23 | }
|
24 | let newBuffer = jpeg.data
|
25 |
|
26 | const transformations = {
|
27 | 2: {rotate: 0, flip: true},
|
28 | 3: {rotate: 180, flip: false},
|
29 | 4: {rotate: 180, flip: true},
|
30 | 5: {rotate: 90, flip: true},
|
31 | 6: {rotate: 90, flip: false},
|
32 | 7: {rotate: 270, flip: true},
|
33 | 8: {rotate: 270, flip: false},
|
34 | }
|
35 |
|
36 | if (transformations[orientation].rotate > 0) {
|
37 | newBuffer = rotatePixels(newBuffer, jpeg.width, jpeg.height, transformations[orientation].rotate)
|
38 | }
|
39 |
|
40 | const ratioWillChange = (transformations[orientation].rotate / 90) % 2 === 1
|
41 | const destWidth = ratioWillChange ? jpeg.height : jpeg.width
|
42 | const destHeight = ratioWillChange ? jpeg.width : jpeg.height
|
43 |
|
44 | if (transformations[orientation].flip) {
|
45 | newBuffer = flipPixels(newBuffer, destWidth, destHeight)
|
46 | }
|
47 |
|
48 | const newJpeg = jpegjs.encode({data: newBuffer, width: destWidth, height: destHeight}, quality)
|
49 | return Promise.resolve({buffer: newJpeg.data, width: destWidth, height: destHeight})
|
50 | }
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | function rotatePixels(buffer, width, height, degrees) {
|
57 | let loops = degrees / 90
|
58 | while (loops > 0) {
|
59 | const newBuffer = Buffer.alloc(buffer.length)
|
60 | let newOffset = 0
|
61 | for (let x = 0; x < width; x += 1) {
|
62 | for (let y = height - 1; y >= 0; y -= 1) {
|
63 | const offset = (width * y + x) << 2
|
64 | const pixel = buffer.readUInt32BE(offset, true)
|
65 | newBuffer.writeUInt32BE(pixel, newOffset, true)
|
66 | newOffset += 4
|
67 | }
|
68 | }
|
69 | buffer = newBuffer
|
70 | const newHeight = width
|
71 | width = height
|
72 | height = newHeight
|
73 | loops -= 1
|
74 | }
|
75 | return buffer
|
76 | }
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | function flipPixels(buffer, width, height) {
|
82 | const newBuffer = Buffer.alloc(buffer.length)
|
83 | for (let x = 0; x < width; x += 1) {
|
84 | for (let y = 0; y < height; y += 1) {
|
85 | const offset = (width * y + x) << 2
|
86 | const newOffset = (width * y + width - 1 - x) << 2
|
87 | const pixel = buffer.readUInt32BE(offset, true)
|
88 | newBuffer.writeUInt32BE(pixel, newOffset, true)
|
89 | }
|
90 | }
|
91 | return newBuffer
|
92 | }
|