Skip to content

Commit 859f227

Browse files
Merge pull request #454 from geotiffjs/feat-ifd-improvements
feat: keep a separate map of tag IDs to parsed IFD values in `ImageFileDescriptor` object
2 parents af0421b + d86d638 commit 859f227

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
"lint:fix": "npm run lint -- --fix",
144144
"prepare": "npm run build",
145145
"pretest": "npm run lint",
146-
"test": "mocha --full-trace test/geotiff.spec.js"
146+
"test": "mocha --full-trace test/*.spec.js"
147147
},
148148
"author": "Fabian Schindler",
149149
"browser": {

src/geotiff.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,20 @@ function getValues(dataSlice, fieldType, count, offset) {
175175
}
176176

177177
/**
178-
* Data class to store the parsed file directory, geo key directory and
178+
* Data class to store the parsed file directory (+ its raw form), geo key directory and
179179
* offset to the next IFD
180180
*/
181181
class ImageFileDirectory {
182-
constructor(fileDirectory, geoKeyDirectory, nextIFDByteOffset) {
182+
/**
183+
* Create an ImageFileDirectory.
184+
* @param {object} fileDirectory the file directory, mapping tag names to values
185+
* @param {Map} rawFileDirectory the raw file directory, mapping tag IDs to values
186+
* @param {object} geoKeyDirectory the geo key directory, mapping geo key names to values
187+
* @param {number} nextIFDByteOffset the byte offset to the next IFD
188+
*/
189+
constructor(fileDirectory, rawFileDirectory, geoKeyDirectory, nextIFDByteOffset) {
183190
this.fileDirectory = fileDirectory;
191+
this.rawFileDirectory = rawFileDirectory;
184192
this.geoKeyDirectory = geoKeyDirectory;
185193
this.nextIFDByteOffset = nextIFDByteOffset;
186194
}
@@ -372,6 +380,7 @@ class GeoTIFF extends GeoTIFFBase {
372380
}
373381

374382
const fileDirectory = {};
383+
const rawFileDirectory = new Map();
375384

376385
// loop over the IFD and create a file directory object
377386
let i = offset + (this.bigTiff ? 8 : 2);
@@ -414,8 +423,12 @@ class GeoTIFF extends GeoTIFFBase {
414423
value = fieldValues;
415424
}
416425

417-
// write the tags value to the file directly
418-
fileDirectory[fieldTagNames[fieldTag]] = value;
426+
// write the tags value to the file directory
427+
const tagName = fieldTagNames[fieldTag];
428+
if (tagName) {
429+
fileDirectory[tagName] = value;
430+
}
431+
rawFileDirectory.set(fieldTag, value);
419432
}
420433
const geoKeyDirectory = parseGeoKeyDirectory(fileDirectory);
421434
const nextIFDByteOffset = dataSlice.readOffset(
@@ -424,6 +437,7 @@ class GeoTIFF extends GeoTIFFBase {
424437

425438
return new ImageFileDirectory(
426439
fileDirectory,
440+
rawFileDirectory,
427441
geoKeyDirectory,
428442
nextIFDByteOffset,
429443
);

src/globals.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,25 @@ for (const key in fieldTypeNames) {
213213
}
214214
}
215215

216+
/**
217+
* Registers a new field tag
218+
* @param {number} tag the numeric tiff tag
219+
* @param {string} name the name of the tag that will be reported in the IFD
220+
* @param {number} type the tags data type
221+
* @param {Boolean} isArray whether the tag is an array
222+
*/
223+
export function registerTag(tag, name, type = undefined, isArray = false) {
224+
fieldTags[name] = tag;
225+
fieldTagNames[tag] = name;
226+
227+
if (type) {
228+
fieldTypes[name] = type;
229+
}
230+
if (isArray) {
231+
arrayFields.push(tag);
232+
}
233+
}
234+
216235
export const photometricInterpretations = {
217236
WhiteIsZero: 0,
218237
BlackIsZero: 1,

test/globals.spec.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable global-require, no-unused-expressions */
2+
import { expect } from 'chai';
3+
4+
import { registerTag, fieldTags, fieldTagNames, fieldTypes, arrayFields } from '../src/globals.js';
5+
6+
describe('registerTag()', () => {
7+
it('shall register simple tags', () => {
8+
registerTag(0xBEA1, 'TestTag');
9+
expect(fieldTags).to.have.property('TestTag');
10+
expect(fieldTagNames).to.have.property(String(0xBEA1));
11+
expect(fieldTypes).to.not.have.property('TestTag');
12+
expect(arrayFields).to.not.include(0xBEA1);
13+
});
14+
it('shall register tags with type', () => {
15+
registerTag(0xBEA2, 'TestTagRational', 'RATIONAL');
16+
expect(fieldTags).to.have.property('TestTagRational');
17+
expect(fieldTagNames).to.have.property(String(0xBEA2));
18+
expect(fieldTypes).to.have.property('TestTagRational');
19+
expect(arrayFields).to.not.include(0xBEA1);
20+
});
21+
it('shall register array tags', () => {
22+
registerTag(0xBEA3, 'TestTagArray', undefined, true);
23+
expect(fieldTags).to.have.property('TestTagArray');
24+
expect(fieldTagNames).to.have.property(String(0xBEA3));
25+
expect(fieldTypes).to.not.have.property('TestTagArray');
26+
expect(arrayFields).to.include(0xBEA3);
27+
});
28+
it('shall register typed array tags', () => {
29+
registerTag(0xBEA4, 'TestTagArrayTyped', 'LONG', true);
30+
expect(fieldTags).to.have.property('TestTagArrayTyped');
31+
expect(fieldTagNames).to.have.property(String(0xBEA4));
32+
expect(fieldTypes).to.have.property('TestTagArrayTyped');
33+
expect(arrayFields).to.include(0xBEA4);
34+
});
35+
});

0 commit comments

Comments
 (0)