1 | 'use strict'
|
2 |
|
3 | const expect = require('chai').expect
|
4 | const fs = require('fs')
|
5 | const exec = require('child_process').exec
|
6 | const piexif = require('piexifjs')
|
7 | const jpegjs = require('jpeg-js')
|
8 | const jo = require('../src/main.js')
|
9 | const describe = require('mocha').describe
|
10 | const it = require('mocha').it
|
11 |
|
12 | require('chai').should()
|
13 |
|
14 | describe('jpeg-autorotate', function() {
|
15 | itShouldTransform(__dirname + '/samples/image_2.jpg', 'image_2.jpg')
|
16 | itShouldTransform(__dirname + '/samples/image_3.jpg', 'image_3.jpg')
|
17 | itShouldTransform(__dirname + '/samples/image_4.jpg', 'image_4.jpg')
|
18 | itShouldTransform(__dirname + '/samples/image_5.jpg', 'image_5.jpg')
|
19 | itShouldTransform(__dirname + '/samples/image_6.jpg', 'image_6.jpg')
|
20 | itShouldTransform(__dirname + '/samples/image_7.jpg', 'image_7.jpg')
|
21 | itShouldTransform(__dirname + '/samples/image_8.jpg', 'image_8.jpg')
|
22 | itShouldTransform(__dirname + '/samples/image_exif.jpg', 'image_exif.jpg')
|
23 | itShouldTransform(fs.readFileSync(__dirname + '/samples/image_8.jpg'), 'From a buffer')
|
24 |
|
25 | it('Should return an error if the orientation is 1', function(done) {
|
26 | jo.rotate(__dirname + '/samples/image_1.jpg', {}, function(error, buffer) {
|
27 | error.should.have.property('code').equal(jo.errors.correct_orientation)
|
28 | Buffer.isBuffer(buffer).should.be.ok
|
29 | done()
|
30 | })
|
31 | })
|
32 |
|
33 | it('Should return an error if the image does not exist', function(done) {
|
34 | jo.rotate('foo.jpg', {}, function(error, buffer, orientation) {
|
35 | error.should.have.property('code').equal(jo.errors.read_file)
|
36 | expect(buffer).to.equal(null)
|
37 | expect(orientation).to.equal(null)
|
38 | done()
|
39 | })
|
40 | })
|
41 |
|
42 | it('Should return an error if the file is not an image', function(done) {
|
43 | jo.rotate(__dirname + '/samples/textfile.md', {}, function(error, buffer, orientation) {
|
44 | error.should.have.property('code').equal(jo.errors.read_exif)
|
45 | expect(buffer).to.equal(null)
|
46 | expect(orientation).to.equal(null)
|
47 | done()
|
48 | })
|
49 | })
|
50 |
|
51 | it('Should return an error if the path is not a string/buffer', function(done) {
|
52 | jo.rotate(['foo'], {}, function(error, buffer, orientation) {
|
53 | error.should.have.property('code').equal(jo.errors.read_file)
|
54 | expect(buffer).to.equal(null)
|
55 | expect(orientation).to.equal(null)
|
56 | done()
|
57 | })
|
58 | })
|
59 |
|
60 | it('Should work if `options` is not an object', function(done) {
|
61 | jo.rotate(__dirname + '/samples/image_2.jpg', 'options', function(error, buffer, orientation) {
|
62 | expect(error).to.equal(null)
|
63 | Buffer.isBuffer(buffer).should.be.ok
|
64 | expect(orientation).to.equal(2)
|
65 | done()
|
66 | })
|
67 | })
|
68 |
|
69 | it('Should return an error if the image has no orientation tag', function(done) {
|
70 | jo.rotate(__dirname + '/samples/image_no_orientation.jpg', {}, function(error, buffer, orientation) {
|
71 | error.should.have.property('code').equal(jo.errors.no_orientation)
|
72 | Buffer.isBuffer(buffer).should.be.ok
|
73 | expect(orientation).to.equal(null)
|
74 | done()
|
75 | })
|
76 | })
|
77 |
|
78 | it('Should return an error if the image has an unknown orientation tag', function(done) {
|
79 | jo.rotate(__dirname + '/samples/image_unknown_orientation.jpg', {}, function(error, buffer, orientation) {
|
80 | error.should.have.property('code').equal(jo.errors.unknown_orientation)
|
81 | Buffer.isBuffer(buffer).should.be.ok
|
82 | expect(orientation).to.equal(null)
|
83 | done()
|
84 | })
|
85 | })
|
86 |
|
87 | it('Should run on CLI (with glob support)', function(done) {
|
88 | const command = `
|
89 | cp test/samples/image_2.jpg test/samples/image_2.cli.jpg &&
|
90 | cp test/samples/image_3.jpg test/samples/image_3.cli.jpg &&
|
91 | cp test/samples/image_4.jpg test/samples/image_4.cli.jpg &&
|
92 | ./src/cli.js test/samples/image_2.cli.jpg "test/samples/image_{3,4}.cli.jpg" &&
|
93 | rm test/samples/image_2.cli.jpg &&
|
94 | rm test/samples/image_3.cli.jpg &&
|
95 | rm test/samples/image_4.cli.jpg
|
96 | `
|
97 | exec(command, function(error, stdout, stderr) {
|
98 | stdout.should.be.a('string').and.contain('Processed (Orientation was 2)')
|
99 | stdout.should.be.a('string').and.contain('Processed (Orientation was 3)')
|
100 | stdout.should.be.a('string').and.contain('Processed (Orientation was 4)')
|
101 | stderr.should.equal('')
|
102 | done()
|
103 | })
|
104 | })
|
105 |
|
106 |
|
107 |
|
108 | })
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | function itShouldTransform(path_or_buffer, label) {
|
116 | it('Should rotate image (' + label + ')', function(done) {
|
117 | this.timeout(20000)
|
118 | const orig_buffer = typeof path_or_buffer === 'string' ? fs.readFileSync(path_or_buffer) : path_or_buffer
|
119 | const orig_exif = piexif.load(orig_buffer.toString('binary'))
|
120 | const orig_jpeg = jpegjs.decode(orig_buffer)
|
121 | jo.rotate(path_or_buffer, {}, function(error, buffer, orientation, dimensions) {
|
122 | if (error) {
|
123 | throw error
|
124 | }
|
125 | const dest_exif = piexif.load(buffer.toString('binary'))
|
126 | if (orientation < 5 && (orig_jpeg.width !== dimensions.width || orig_jpeg.height !== dimensions.height)) {
|
127 | throw new Error('Dimensions do not match')
|
128 | }
|
129 | if (orientation >= 5 && (orig_jpeg.width !== dimensions.height || orig_jpeg.height !== dimensions.width)) {
|
130 | throw new Error('Dimensions do not match')
|
131 | }
|
132 | if (!compareEXIF(orig_exif, dest_exif)) {
|
133 | throw new Error('EXIF do not match')
|
134 | }
|
135 | if (typeof path_or_buffer === 'string') {
|
136 | fs.writeFileSync(path_or_buffer.replace('samples/', 'samples/transformed/'), buffer)
|
137 | }
|
138 | done()
|
139 | })
|
140 | })
|
141 | }
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 | function compareEXIF(orig, dest) {
|
150 | orig['thumbnail'] = 0
|
151 | dest['thumbnail'] = 0
|
152 | orig['0th'][piexif.ImageIFD.Orientation] = 0
|
153 | dest['0th'][piexif.ImageIFD.Orientation] = 0
|
154 | orig['0th'][piexif.ImageIFD.ExifTag] = 0
|
155 | dest['0th'][piexif.ImageIFD.ExifTag] = 0
|
156 | orig['Exif'][piexif.ExifIFD.PixelXDimension] = 0
|
157 | dest['Exif'][piexif.ExifIFD.PixelXDimension] = 0
|
158 | orig['Exif'][piexif.ExifIFD.PixelYDimension] = 0
|
159 | dest['Exif'][piexif.ExifIFD.PixelYDimension] = 0
|
160 | orig['1st'][piexif.ImageIFD.JPEGInterchangeFormat] = 0
|
161 | dest['1st'][piexif.ImageIFD.JPEGInterchangeFormat] = 0
|
162 | orig['1st'][piexif.ImageIFD.JPEGInterchangeFormatLength] = 0
|
163 | dest['1st'][piexif.ImageIFD.JPEGInterchangeFormatLength] = 0
|
164 |
|
165 | const orig_json = JSON.stringify(orig)
|
166 | const dest_json = JSON.stringify(dest)
|
167 |
|
168 | return orig_json === dest_json
|
169 | }
|