Skip to content

Extensible tags #365

@Radiergummi

Description

@Radiergummi

Description

I'd like to suggest making the available tags configurable. From a user perspective, I'd imagine passing the tags to the read options, or exporting an ExifReader class that takes them as constructor parameters. Using custom tags would look like so:

Use ExifReader like it currently works (this ought to be the default):

import ExifReader from 'exifreader';

// The default export of the tags module would be an object of the default tags
import defaultTags from 'exifreader/tags';

ExifReader.read(data, {
  tags: defaultTags,
});

// or by omitting tags, which would result in a dynamic import of the defaultTags
ExifReader.read(data);

Use ExifReader with a subset of tags:

import ExifReader from 'exifreader';

// In addition to the default export, the tags module would hold separate exports
// for the individual tag families
import { exif, file, photoshop } from 'exifreader/tags';

ExifReader.read(data, {
  tags: { exif, file, photoshop },
});

Use ExifReader with a custom tag set (more on that below) in addition to the defaults:

import ExifReader from 'exifreader';
import defaultTags from 'exifreader/tags';
import { apple } from './custom-apple-tags-module';

ExifReader.read(data, {
  tags: { ...defaultTags, apple },
});

This would:

  • remove the need for custom builds altogether
  • add support for tree shaking, since the library could be build to avoid importing the tag sets automatically
  • allow using additional tag sets without upstream changes to the library required (but still possible).

To define custom tag sets, one would need an object implementing the below interface:

interface TagSet<T extends number | number[]> {
  read(dataView: DataView, offset: T): Promise<Record<string, Tag>>;

  findOffset(dataView: DataView): Promise<T | undefined>;
}

There may be more thinking required for generalising all existing tag extractors, but it should be possible.

custom-apple-tags-module.ts:

import { defineTagSet } from 'exifreader';

export const apple = defineTagSet({
  async read(dataView, offset) {
    // ...
  },

  async findOffset(dataView) {
    // ...
  },
});

(defineTagSet is just a helper function returning the object to make it easy to type the thing automatically)

Do you think this is feasible, or even an interesting direction to go into? I'm willing to contribute to this.
My motivation is that I need a few tags defined by Apple exifTool knows about, but ExifReader doesn't. Ideally, I'd like to just write a custom module to parse those tags, and if that works well, contribute them back to ExifReader; it would be cool to have an easy extension point. For my use case, I'd also like to use tree shaking, but the custom builds (while a neat solution) don't integrate well with my deployment target.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions