Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,16 @@ var JpegImage = (function jpegImage() {
}
}
// TODO APP1 - Exif
if (fileMarker === 0xFFE1) {
if (appData[0] === 0x45 &&
appData[1] === 0x78 &&
appData[2] === 0x69 &&
appData[3] === 0x66 &&
appData[4] === 0) { // 'EXIF\x00'
this.exifBuffer = appData.subarray(5, appData.length);
}
}

if (fileMarker === 0xFFEE) {
if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F &&
appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0) { // 'Adobe\x00'
Expand Down Expand Up @@ -1050,6 +1060,7 @@ function decode(jpegData, opts) {
var image = {
width: decoder.width,
height: decoder.height,
exifBuffer: decoder.exifBuffer,
data: opts.useTArray ?
new Uint8Array(bytesNeeded) :
new Buffer(bytesNeeded)
Expand Down
29 changes: 28 additions & 1 deletion lib/encoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,33 @@ function JPEGEncoder(quality) {
writeByte(0); // thumbnwidth
writeByte(0); // thumbnheight
}


function writeAPP1(exifBuffer) {
if (!exifBuffer) return;

writeWord(0xFFE1); // APP1 marker

if (exifBuffer[0] === 0x45 &&
exifBuffer[1] === 0x78 &&
exifBuffer[2] === 0x69 &&
exifBuffer[3] === 0x66) {
// Buffer already starts with EXIF, just use it directly
writeWord(exifBuffer.length + 2); // length is buffer + length itself!
} else {
// Buffer doesn't start with EXIF, write it for them
writeWord(exifBuffer.length + 5 + 2); // length is buffer + EXIF\0 + length itself!
writeByte(0x45); // E
writeByte(0x78); // X
writeByte(0x69); // I
writeByte(0x66); // F
writeByte(0); // = "EXIF",'\0'
}

for (var i = 0; i < exifBuffer.length; i++) {
writeByte(exifBuffer[i]);
}
}

function writeSOF0(width, height)
{
writeWord(0xFFC0); // marker
Expand Down Expand Up @@ -599,6 +625,7 @@ function JPEGEncoder(quality) {
// Add JPEG headers
writeWord(0xFFD8); // SOI
writeAPP0();
writeAPP1(image.exifBuffer);
writeDQT();
writeSOF0(image.width,image.height);
writeDHT();
Expand Down
10 changes: 10 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,13 @@ it('should be able to decode a JPEG into RGB', function(t) {
t.assert(rawImageData.data instanceof Uint8Array, 'data is a typed array');
t.end();
});

it('should be able to encode/decode image with exif data', function(t) {
var jpegData = fixture('grumpycat.jpg');
var imageData = jpeg.decode(new Uint8Array(jpegData));
t.assert(imageData.exifBuffer, 'decodes an exif buffer');
var encodedData = jpeg.encode(imageData);
var loopImageData = jpeg.decode(new Uint8Array(encodedData.data));
t.bufferEqual(loopImageData.exifBuffer, imageData.exifBuffer);
t.end();
});