1 | [](https://github.com/johansatge/jpeg-autorotate/releases)
|
2 | [](https://www.pkgstats.com/pkg:jpeg-autorotate)
|
3 | [](https://github.com/johansatge/jpeg-autorotate/commits/master)
|
4 | [](https://travis-ci.com/johansatge/jpeg-autorotate)
|
5 | [](https://codecov.io/github/johansatge/jpeg-autorotate/)
|
6 | [](https://packagephobia.com/result?p=jpeg-autorotate)
|
7 |
|
8 | 
|
9 |
|
10 | > A node module to rotate JPEG images based on EXIF orientation.
|
11 |
|
12 | ---
|
13 |
|
14 | * [What does it do](#what-does-it-do)
|
15 | * [Installation](#installation)
|
16 | * [Usage](#usage)
|
17 | * [Options](#options)
|
18 | * [CLI](#cli)
|
19 | * [Node module](#node-module)
|
20 | * [Sample usage](#sample-usage)
|
21 | * [Error handling](#error-handling)
|
22 | * [Troubleshooting](#troubleshooting)
|
23 | * [Thumbnail too large](#thumbnail-too-large)
|
24 | * [Changelog](#changelog)
|
25 | * [License](#license)
|
26 | * [Contributing](#contributing)
|
27 | * [Credits](#credits)
|
28 |
|
29 | ## What does it do
|
30 |
|
31 | This module applies the right orientation to a JPEG image, based on its EXIF tag. More precisely, it:
|
32 |
|
33 | * Rotates the pixels
|
34 | * Rotates the thumbnail, if there is one
|
35 | * Writes `1` in the `Orientation` EXIF tag (this is the default orientation)
|
36 | * Updates the `PixelXDimension` and `PixelYDimension` EXIF values
|
37 | * Does **not** alter the other EXIF tags
|
38 |
|
39 | It may be useful, if:
|
40 |
|
41 | * You need to compress your image with a tool that strips EXIF data without rotating the pixels (like the great [ImageOptim](https://imageoptim.com/))
|
42 | * You need to upload the image, but the destination application does not support EXIF orientation (like [WordPress](https://wordpress.org/))
|
43 | * You just want to get rid of the orientation tag, while leaving the other tags **intact**
|
44 |
|
45 | > More information about EXIF:
|
46 | >
|
47 | > * [EXIF Orientation Handling Is a Ghetto](http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/)
|
48 | > * [Standard EXIF Tags](http://www.exiv2.org/tags.html)
|
49 |
|
50 | ## Installation
|
51 |
|
52 | _This module needs Node `>=12`._
|
53 |
|
54 | Install with [npm](https://www.npmjs.com/):
|
55 |
|
56 | ```bash
|
57 | $ npm install jpeg-autorotate --global
|
58 | # --global isn't required if you plan to use the node module
|
59 | ```
|
60 |
|
61 | ## Usage
|
62 |
|
63 | ### Options
|
64 |
|
65 | | Option | Default value | Description |
|
66 | | --- | --- | --- |
|
67 | | `quality` | `100` | Quality of the JPEG. Uncompressed by default, so the resulting image may be bigger than the original one. |
|
68 | | `jpegjsMaxResolutionInMP` | `jpeg-js` default | `maxResolutionInMP` option in `jpeg-js` ([doc](https://github.com/eugeneware/jpeg-js#decode-options)) |
|
69 | | `jpegjsMaxMemoryUsageInMB` | `jpeg-js` default | `maxMemoryUsageInMB` option in `jpeg-js` ([doc](https://github.com/eugeneware/jpeg-js#decode-options)) |
|
70 |
|
71 | ### CLI
|
72 |
|
73 | Rotate a single image:
|
74 |
|
75 | ```bash
|
76 | $ jpeg-autorotate /Users/johan/IMG_1234.jpg
|
77 | ```
|
78 |
|
79 | Rotate a set of images:
|
80 |
|
81 | ```bash
|
82 | $ jpeg-autorotate /Users/johan/images/IMG_*.jpg
|
83 | ```
|
84 |
|
85 | Glob support:
|
86 |
|
87 | ```bash
|
88 | $ jpeg-autorotate "/Users/johan/images/IMG_*.{jpg,jpeg,JPG,JPEG}"
|
89 | ```
|
90 |
|
91 | Passing options:
|
92 |
|
93 | ```
|
94 | $ jpeg-autorotate /Users/johan/IMG_1234.jpg --quality=85 --jpegjsMaxResolutionInMP=1234
|
95 | ```
|
96 |
|
97 | ### Node module
|
98 |
|
99 | The Node module will load the image, apply the rotation, and return the binary data as a [Buffer](https://nodejs.org/api/buffer.html), allowing you to:
|
100 |
|
101 | * Save it on disk
|
102 | * Load it in an image processing module (like [jimp](https://github.com/oliver-moran/jimp), [lwip](https://github.com/EyalAr/lwip), [gm](https://github.com/aheckmann/gm)...)
|
103 | * ...
|
104 |
|
105 | #### Sample usage
|
106 |
|
107 | ```js
|
108 | const jo = require('jpeg-autorotate')
|
109 | const options = {
|
110 | quality: 8,
|
111 | jpegjsMaxResolutionInMP: 1234,
|
112 | }
|
113 | const path = '/Users/johan/IMG_1234.jpg' // You can use a Buffer too
|
114 |
|
115 | //
|
116 | // With a callback:
|
117 | //
|
118 | jo.rotate(path, options, (error, buffer, orientation, dimensions, quality) => {
|
119 | if (error) {
|
120 | console.log('An error occurred when rotating the file: ' + error.message)
|
121 | return
|
122 | }
|
123 | console.log(`Orientation was ${orientation}`)
|
124 | console.log(`Dimensions after rotation: ${dimensions.width}x${dimensions.height}`)
|
125 | console.log(`Quality: ${quality}`)
|
126 | // ...Do whatever you need with the resulting buffer...
|
127 | })
|
128 |
|
129 | //
|
130 | // With a Promise:
|
131 | //
|
132 | jo.rotate(path, options)
|
133 | .then(({buffer, orientation, dimensions, quality}) => {
|
134 | console.log(`Orientation was ${orientation}`)
|
135 | console.log(`Dimensions after rotation: ${dimensions.width}x${dimensions.height}`)
|
136 | console.log(`Quality: ${quality}`)
|
137 | // ...Do whatever you need with the resulting buffer...
|
138 | })
|
139 | .catch((error) => {
|
140 | console.log('An error occurred when rotating the file: ' + error.message)
|
141 | })
|
142 | ```
|
143 |
|
144 | #### Error handling
|
145 |
|
146 | The `error` object returned by the module contains a readable `message`, but also a `code` for better error handling. Available codes are the following:
|
147 |
|
148 | ```js
|
149 | const jo = require('jpeg-autorotate')
|
150 |
|
151 | jo.errors.read_file // File could not be opened
|
152 | jo.errors.read_exif // EXIF data could not be read
|
153 | jo.errors.no_orientation // No orientation tag was found
|
154 | jo.errors.unknown_orientation // The orientation tag is unknown
|
155 | jo.errors.correct_orientation // The image orientation is already correct
|
156 | jo.errors.rotate_file // An error occurred when rotating the image
|
157 | ```
|
158 |
|
159 | Example:
|
160 |
|
161 | ```js
|
162 | const jo = require('jpeg-autorotate')
|
163 | jo.rotate('/image.jpg')
|
164 | .catch((error) => {
|
165 | if (error.code === jo.errors.correct_orientation) {
|
166 | console.log('The orientation of this image is already correct!')
|
167 | }
|
168 | })
|
169 | ```
|
170 |
|
171 | ## Troubleshooting
|
172 |
|
173 | ### Thumbnail too large
|
174 |
|
175 | The [piexifjs](https://github.com/hMatoba/piexifjs/) module has a [64kb limit](https://github.com/hMatoba/piexifjs/blob/7b9140ab8ebb8ff620bb20f6319a337dd150092b/piexif.js#L236-L243) when reading thumbnails.
|
176 | If you get the _Given thumbnail is too large_ error, you can try to remove the thumbnail from the image before rotating it:
|
177 |
|
178 | ```js
|
179 | import piexif from 'piexifjs'
|
180 |
|
181 | function deleteThumbnailFromExif(imageBuffer) {
|
182 | const imageString = imageBuffer.toString('binary')
|
183 | const exifObj = piexif.load(imageString)
|
184 | delete exifObj['thumbnail']
|
185 | delete exifObj['1st']
|
186 | const exifBytes = piexif.dump(exifObj)
|
187 | return Buffer.from(piexif.insert(exifBytes, imageString), 'binary')
|
188 | }
|
189 | ```
|
190 |
|
191 | ## Changelog
|
192 |
|
193 | This project uses [semver](http://semver.org/).
|
194 |
|
195 | | Version | Date | Notes |
|
196 | | --- | --- | --- |
|
197 | | `8.0.1` | 2022-01-10 | Remove `colors` package from dependencies |
|
198 | | `8.0.0` | 2021-11-12 | Node 16 support<br>Drop support for Node 10 |
|
199 | | `7.1.1` | 2020-10-11 | Introduce code coverage<br>Fix an error if `options` are not passed |
|
200 | | `7.1.0` | 2020-10-10 | Introduce `jpegjsMaxResolutionInMP` & `jpegjsMaxMemoryUsageInMB` options (#26) |
|
201 | | `7.0.0` | 2020-09-19 | Don't publish test and linting files on NPM |
|
202 | | `6.0.0` | 2020-05-30 | Dependencies update<br>Drop support for Node < 10<br>From `jpeg-js` update: _images larger than 100 megapixels or requiring more than 512MB of memory to decode will throw_ |
|
203 | | `5.0.3` | 2019-12-24 | Fix multiple file support in CLI<br>Dependencies update |
|
204 | | `5.0.2` | 2019-09-28 | Dependencies update |
|
205 | | `5.0.1` | 2019-06-08 | Fix CLI support |
|
206 | | `5.0.0` | 2019-03-03 | Drop `--jobs` CLI option<br>Drop support for Node 6 & 7<br>Introduce new `quality` property in the `jo.rotate` callback<br>Public API now supports both callbacks and Promises<br>Update documentation accordingly<br>Update dependencies |
|
207 | | `4.0.1` | 2018-11-29 | Fix rotations `5` and `7` (issue #11) |
|
208 | | `4.0.0` | 2018-07-15 | Drop support for Node 4 & 5<br>Unpublish lockfile<br>Use prettier for code formatting<br>Update documentation<br>Update dependencies |
|
209 | | `3.1.0` | 2017-12-03 | Output dimensions after rotation |
|
210 | | `3.0.1` | 2017-07-30 | Node 8 support<br>Update dependencies |
|
211 | | `3.0.0` | 2017-02-11 | CLI supports `glob`<br>No more `node 0.12` support<br>Drop semicolons<br>Add eslint rules |
|
212 | | `2.0.0` | 2016-06-03 | Supports buffers in entry<br>Returns a buffer even if there was an error<br>Improves tests |
|
213 | | `1.1.0` | 2016-04-23 | Adds test suite, removes lwip dependency |
|
214 | | `1.0.3` | 2016-03-29 | Displays help when no path given in CLI |
|
215 | | `1.0.2` | 2016-03-21 | Adds missing options in CLI help |
|
216 | | `1.0.1` | 2016-03-21 | Fixes NPM publishing fail ^\_^ |
|
217 | | `1.0.0` | 2016-03-21 | Initial version |
|
218 |
|
219 | ## License
|
220 |
|
221 | This project is released under the [MIT License](license.md).
|
222 |
|
223 | ## Contributing
|
224 |
|
225 | Bug reports and feature requests are welcome! More details in the [contribution guidelines](contributing.md).
|
226 |
|
227 | ## Credits
|
228 |
|
229 | * [piexifjs](https://github.com/hMatoba/piexifjs)
|
230 | * [jpeg-js](https://github.com/eugeneware/jpeg-js)
|
231 | * [exif-orientation-examples](https://github.com/recurser/exif-orientation-examples)
|
232 | * [yargs](https://github.com/bcoe/yargs)
|
233 | * [FontAwesome](http://fontawesome.io/)
|
234 | * [Chai](http://chaijs.com/)
|
235 | * [Mocha](http://mochajs.org)
|
236 | * [eslint](http://eslint.org)
|
237 | * [glob](https://github.com/isaacs/node-glob)
|
238 | * [prettier](https://prettier.io/)
|