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

Using exifr.parse on a buffer that contains just exif data #101

Open
rijkvanzanten opened this issue Dec 14, 2022 · 1 comment
Open

Using exifr.parse on a buffer that contains just exif data #101

rijkvanzanten opened this issue Dec 14, 2022 · 1 comment

Comments

@rijkvanzanten
Copy link

Heya!

Is it possible to have exifr.parse function on a buffer that just contains exif data rather than a whole file?

I'm currently relying on Sharp to gather some file metadata (like width/height/orientation), and would like to use Exifr to (optionally) parse the Exif information if Sharp returns it. I do not have a Buffer with the full file contents available (nor am I able to get it), so I was hoping I could stream the file to sharp, have sharp prepare an Exif buffer, and parse that out with Exifr.
For example:

import { createReadStream } from 'node:fs';
import { pipeline } from 'node:stream/promises';
import sharp from 'sharp';
import { parse } from 'exifr';

const stream = createReadStream('./path/to/large/file.jpg');

const getMetadata = (stream) => new Promise((resolve, reject) => {
  pipeline(stream, sharp().metadata(async (err, sharpMetadata) => {
    if (err) return reject(err);
    
    // Do stuff with sharp metadata

    if (sharpMetadata.exif) {
      const exifData = await parse(sharpMetadata.exif);
      //               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    }

    // etc
  });
});

At the moment, the highlighted section errors with an error: Error: Unknown file format, which I believe stems from the fact that exifr expects the buffer to contain all file data, rather than just the exif information.

@paescuj
Copy link

paescuj commented Dec 15, 2022

For now, we might be able to extend the Exifr class and inject the corresponding parser manually (based on image type detected by sharp).

Super dirty examplary code:

import { Exifr } from 'exifr';

const formatMap = {
  jpeg: 'JpegFileParser'
  // ...
};

class CustomExifr extends Exifr {
  constructor(parser, options) {
    this.fileParser = parser;
    super(options);
  }
}

// sharp stuff

    if (sharpMetadata.exif) {
      const parserType = formatMap[sharpMetadata.format];
      if (parserType) {
        // try...catch
        const Parser = (await import(`exifr/file-parsers/${sharpMetadata.format}`)).[parserType];
        const exifr = new CustomExifr(new Parser(/* <need to look into parser options> */), exifrOptions);
        await exifr.read(sharpMetadata.exif);
        const exifData = await exifr.parse();
        //
      }
      //
    }

//

No idea whether a) those classes are indeed exported and available b) this would be sufficient or still too few / wrong data for exifr to process...

Obivously, if this approach would work and with the agreement of @MikeKovarik, we could then handle this in exifr itself (happy to come up with a PR in that case).

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