UNPKG

2.52 kBJavaScriptView Raw
1const jpegjs = require('jpeg-js')
2
3const m = {}
4
5/**
6 * Decode the given buffer and applies the right transformation
7 * Depending on the orientation, it may be a rotation and / or an horizontal flip
8 */
9m.rotateBuffer = function(buffer, orientation, quality) {
10 let jpeg = null
11 try {
12 jpeg = jpegjs.decode(buffer)
13 } catch (error) {
14 return Promise.reject(error)
15 }
16 let newBuffer = jpeg.data
17
18 const transformations = {
19 2: {rotate: 0, flip: true},
20 3: {rotate: 180, flip: false},
21 4: {rotate: 180, flip: true},
22 5: {rotate: 90, flip: true},
23 6: {rotate: 90, flip: false},
24 7: {rotate: 270, flip: true},
25 8: {rotate: 270, flip: false},
26 }
27
28 if (transformations[orientation].rotate > 0) {
29 newBuffer = rotatePixels(newBuffer, jpeg.width, jpeg.height, transformations[orientation].rotate)
30 }
31
32 const ratioWillChange = (transformations[orientation].rotate / 90) % 2 === 1
33 const destWidth = ratioWillChange ? jpeg.height : jpeg.width
34 const destHeight = ratioWillChange ? jpeg.width : jpeg.height
35
36 if (transformations[orientation].flip) {
37 newBuffer = flipPixels(newBuffer, destWidth, destHeight)
38 }
39
40 const newJpeg = jpegjs.encode({data: newBuffer, width: destWidth, height: destHeight}, quality)
41 return Promise.resolve({buffer: newJpeg.data, width: destWidth, height: destHeight})
42}
43
44/**
45 * Rotate a buffer (degrees must be a multiple of 90)
46 * Inspired from Jimp (https://github.com/oliver-moran/jimp)
47 */
48function rotatePixels(buffer, width, height, degrees) {
49 let loops = degrees / 90
50 while (loops > 0) {
51 const newBuffer = Buffer.alloc(buffer.length)
52 let newOffset = 0
53 for (let x = 0; x < width; x += 1) {
54 for (let y = height - 1; y >= 0; y -= 1) {
55 const offset = (width * y + x) << 2
56 const pixel = buffer.readUInt32BE(offset, true)
57 newBuffer.writeUInt32BE(pixel, newOffset, true)
58 newOffset += 4
59 }
60 }
61 buffer = newBuffer
62 const newHeight = width
63 width = height
64 height = newHeight
65 loops -= 1
66 }
67 return buffer
68}
69
70/**
71 * Flip a buffer horizontally
72 */
73function flipPixels(buffer, width, height) {
74 const newBuffer = Buffer.alloc(buffer.length)
75 for (let x = 0; x < width; x += 1) {
76 for (let y = 0; y < height; y += 1) {
77 const offset = (width * y + x) << 2
78 const newOffset = (width * y + width - 1 - x) << 2
79 const pixel = buffer.readUInt32BE(offset, true)
80 newBuffer.writeUInt32BE(pixel, newOffset, true)
81 }
82 }
83 return newBuffer
84}
85
86module.exports = m