-
-
Notifications
You must be signed in to change notification settings - Fork 764
/
Copy pathimage-bitmap.js
155 lines (129 loc) · 3.83 KB
/
image-bitmap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import fileType from 'file-type';
import EXIFParser from 'exif-parser';
import { throwError } from '@jimp/utils';
import * as constants from '../constants';
import * as MIME from './mime';
import promisify from './promisify';
function getMIMEFromBuffer(buffer, path) {
const fileTypeFromBuffer = fileType(buffer);
if (fileTypeFromBuffer) {
// If fileType returns something for buffer, then return the mime given
return fileTypeFromBuffer.mime;
}
if (path) {
// If a path is supplied, and fileType yields no results, then retry with MIME
// Path can be either a file path or a url
return MIME.getType(path);
}
return null;
}
/*
* Automagically rotates an image based on its EXIF data (if present)
* @param img a constants object
*/
function exifRotate(img) {
const exif = img._exif;
if (exif && exif.tags && exif.tags.Orientation) {
switch (img._exif.tags.Orientation) {
case 1: // Horizontal (normal)
// do nothing
break;
case 2: // Mirror horizontal
img.mirror(true, false);
break;
case 3: // Rotate 180
img.rotate(180);
break;
case 4: // Mirror vertical
img.mirror(false, true);
break;
case 5: // Mirror horizontal and rotate 270 CW
img.rotate(-90).mirror(true, false);
break;
case 6: // Rotate 90 CW
img.rotate(-90);
break;
case 7: // Mirror horizontal and rotate 90 CW
img.rotate(90).mirror(true, false);
break;
case 8: // Rotate 270 CW
img.rotate(-270);
break;
default:
break;
}
}
return img;
}
// parses a bitmap from the constructor to the JIMP bitmap property
export function parseBitmap(data, path, cb) {
const mime = getMIMEFromBuffer(data, path);
if (typeof mime !== 'string') {
return cb(new Error('Could not find MIME for Buffer <' + path + '>'));
}
this._originalMime = mime.toLowerCase();
try {
const mime = this.getMIME();
if (this.constructor.decoders[mime]) {
this.bitmap = this.constructor.decoders[mime](data);
} else {
return throwError.call(this, 'Unsupported MIME type: ' + mime, cb);
}
} catch (error) {
return cb.call(this, error, this);
}
try {
this._exif = EXIFParser.create(data).parse();
exifRotate(this); // EXIF data
} catch (error) {
/* meh */
}
cb.call(this, null, this);
return this;
}
function compositeBitmapOverBackground(Jimp, image) {
return new Jimp(
image.bitmap.width,
image.bitmap.height,
image._background
).composite(image, 0, 0).bitmap;
}
/**
* Converts the image to a buffer
* @param {string} mime the mime type of the image buffer to be created
* @param {function(Error, Jimp)} cb a Node-style function to call with the buffer as the second argument
* @returns {Jimp} this for chaining of methods
*/
export function getBuffer(mime, cb) {
if (mime === constants.AUTO) {
// allow auto MIME detection
mime = this.getMIME();
}
if (typeof mime !== 'string') {
return throwError.call(this, 'mime must be a string', cb);
}
if (typeof cb !== 'function') {
return throwError.call(this, 'cb must be a function', cb);
}
mime = mime.toLowerCase();
if (this._rgba && this.constructor.hasAlpha[mime]) {
this.bitmap.data = Buffer.from(this.bitmap.data);
} else {
// when format doesn't support alpha
// composite onto a new image so that the background shows through alpha channels
this.bitmap.data = compositeBitmapOverBackground(
this.constructor,
this
).data;
}
if (this.constructor.encoders[mime]) {
const buffer = this.constructor.encoders[mime](this);
cb.call(this, null, buffer);
} else {
cb.call(this, 'Unsupported MIME type: ' + mime);
}
return this;
}
export function getBufferAsync(mime) {
return promisify(getBuffer, this, mime);
}