Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extensible tags #365

Open
Radiergummi opened this issue Aug 2, 2024 · 2 comments
Open

Extensible tags #365

Radiergummi opened this issue Aug 2, 2024 · 2 comments

Comments

@Radiergummi
Copy link

Radiergummi commented Aug 2, 2024

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.

@mattiasw
Copy link
Owner

mattiasw commented Aug 5, 2024

Hi,

It's definitely an interesting suggestion to look into. There already is a thread about it actually: #243

The customizability is not going to be as good as with the custom builds for a couple of reasons mentioned in the other issue but I think the plugin architecture is a much better solution. I should have some more time on my hands after the (European) summer and can have a more proper look at it then.

In the meantime it might be possible to add the Apple tags for you into the library directly (unless they are stored in a heavy Apple-specific way). I will have a look at the latest next week.

Thanks for the descriptive suggestion.

@mattiasw
Copy link
Owner

mattiasw commented Aug 9, 2024

I seem to have spoken too soon. The Apple tags are stored in the maker notes. This makes them very suitable to rather be a custom module instead.

If you need these tags sooner rather than later I would suggest getting the MakerNotes tag using ExifReader and then write your own parser of that block of binary data (present in the value property of the tag). I don't know the specification of it but from a quick look at the byte codes for a file I have it seems to start with Apple iOS and then two null bytes (I assume the exact string will be different for different devices).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants