Skip to content

Commit e3e0c24

Browse files
committed
Add support for Exif tags in PNG images
1 parent 3a3b5d5 commit e3e0c24

File tree

5 files changed

+30
-3
lines changed

5 files changed

+30
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ You can try it out on the
2323
| ----------|---------|---------|---------|---------|---------|-----------|
2424
| JPEG | **yes** | **yes** | **yes** | **yes** | **yes** | **yes** |
2525
| TIFF | **yes** | **yes** | **yes** | **yes** | ??? | no |
26-
| PNG | no | no | **yes** | no | no | no |
26+
| PNG | **yes** | no | **yes** | no | no | no |
2727
| HEIC/HEIF | **yes** | no | no | **yes** | ??? | no |
2828
| WebP | **yes** | no | **yes** | **yes** | ??? | **yes** |
2929

dist/exif-reader.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/exif-reader.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/image-header-png.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export const TYPE_TEXT = 'tEXt';
2323
export const TYPE_ITXT = 'iTXt';
2424
export const TYPE_PHYS = 'pHYs';
2525
export const TYPE_TIME = 'tIME';
26+
export const TYPE_EXIF = 'eXIf';
2627

2728
function isPngFile(dataView) {
2829
return !!dataView && getStringFromDataView(dataView, 0, PNG_ID.length) === PNG_ID;
@@ -61,6 +62,9 @@ function findPngOffsets(dataView) {
6162
type: chunkType,
6263
offset: offset + PNG_CHUNK_DATA_OFFSET
6364
});
65+
} else if (isPngExifChunk(dataView, offset)) {
66+
offsets.hasAppMarkers = true;
67+
offsets.tiffHeaderOffset = offset + PNG_CHUNK_DATA_OFFSET;
6468
} else if (isPngChunk(dataView, offset)) {
6569
offsets.hasAppMarkers = true;
6670
if (!offsets.pngChunkOffsets) {
@@ -96,6 +100,10 @@ function isPngTextChunk(dataView, offset) {
96100
return chunkType === PNG_CHUNK_TYPE_TEXT || chunkType === PNG_CHUNK_TYPE_ITXT;
97101
}
98102

103+
function isPngExifChunk(dataView, offset) {
104+
return getStringFromDataView(dataView, offset + PNG_CHUNK_TYPE_OFFSET, PNG_CHUNK_TYPE_SIZE) === TYPE_EXIF;
105+
}
106+
99107
function isPngChunk(dataView, offset) {
100108
const SUPPORTED_PNG_CHUNK_TYPES = [TYPE_PHYS, TYPE_TIME];
101109
const chunkType = getStringFromDataView(dataView, offset + PNG_CHUNK_TYPE_OFFSET, PNG_CHUNK_TYPE_SIZE);

test/unit/image-header-spec.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,25 @@ describe('image-header', () => {
401401
});
402402
});
403403

404+
it('should find eXIf chunks', () => {
405+
const chunkData = '\x01\x02\x03';
406+
const chunkLength = `\x00\x00\x00${String.fromCharCode(chunkData.length)}`;
407+
const chunkType = 'eXIf';
408+
const crcChecksum = '\x00\x00\x00\x00';
409+
410+
const dataView = getDataView(
411+
PNG_IMAGE_START
412+
+ chunkLength + chunkType + chunkData + crcChecksum
413+
);
414+
415+
const appMarkerValues = ImageHeader.parseAppMarkers(dataView);
416+
417+
expect(appMarkerValues).to.deep.equal({
418+
hasAppMarkers: true,
419+
tiffHeaderOffset: PNG_IMAGE_START.length + chunkLength.length + chunkType.length,
420+
});
421+
});
422+
404423
it('should handle when PNG files have been excluded in a custom build', () => {
405424
ImageHeaderRewireAPI.__Rewire__('Constants', {USE_PNG: false});
406425
const dataView = getDataView(PNG_IMAGE_START);

0 commit comments

Comments
 (0)