UNPKG

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