UNPKG

2.75 kBJavaScriptView Raw
1'use strict'
2
3const jpegjs = require('jpeg-js')
4
5const m = {}
6
7/**
8 * Decodes the given buffer and applies the right transformation
9 * Depending on the orientation, it may be a rotation and / or an horizontal flip
10 * @param buffer
11 * @param orientation
12 * @param quality
13 * @param module_callback
14 */
15m.do = function(buffer, orientation, quality, module_callback) {
16 let jpeg = null
17 try {
18 jpeg = jpegjs.decode(buffer)
19 } catch (error) {
20 module_callback(error, null, 0, 0)
21 return
22 }
23 let new_buffer = 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 new_buffer = _rotate(new_buffer, 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 new_buffer = _flip(new_buffer, destWidth, destHeight)
45 }
46
47 const new_jpeg = jpegjs.encode({data: new_buffer, width: destWidth, height: destHeight}, quality)
48 module_callback(null, new_jpeg.data, destWidth, destHeight)
49}
50
51/**
52 * Rotates a buffer (degrees must be a multiple of 90)
53 * Inspired from Jimp (https://github.com/oliver-moran/jimp)
54 * @param buffer
55 * @param width
56 * @param height
57 * @param degrees
58 */
59const _rotate = function(buffer, width, height, degrees) {
60 let loops = degrees / 90
61 while (loops > 0) {
62 const new_buffer = Buffer.alloc(buffer.length)
63 let new_offset = 0
64 for (let x = 0; x < width; x += 1) {
65 for (let y = height - 1; y >= 0; y -= 1) {
66 const offset = (width * y + x) << 2
67 const pixel = buffer.readUInt32BE(offset, true)
68 new_buffer.writeUInt32BE(pixel, new_offset, true)
69 new_offset += 4
70 }
71 }
72 buffer = new_buffer
73 const new_height = width
74 width = height
75 height = new_height
76 loops -= 1
77 }
78 return buffer
79}
80
81/**
82 * Flips a buffer horizontally
83 * @param buffer
84 * @param width
85 * @param height
86 */
87const _flip = function(buffer, width, height) {
88 const new_buffer = Buffer.alloc(buffer.length)
89 for (let x = 0; x < width; x += 1) {
90 for (let y = 0; y < height; y += 1) {
91 const offset = (width * y + x) << 2
92 const new_offset = (width * y + width - 1 - x) << 2
93 const pixel = buffer.readUInt32BE(offset, true)
94 new_buffer.writeUInt32BE(pixel, new_offset, true)
95 }
96 }
97 return new_buffer
98}
99
100module.exports = m