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