Code Monkey home page Code Monkey logo

exif-reader's Introduction

exif-reader

A small EXIF image metadata reader.

Usage

npm install exif-reader
var exif = require('exif-reader');

// decode raw exif data from a buffer
var metadata = exif(buf);

Support is also built into jpg-stream for extracting EXIF data from JPEGs using this module.

Resulting properties are grouped as follows:

  • bigEndian: determines the endianness of the buffers (in case of non-ascii data)
  • Image: basic TIFF properties about the image
  • Thumbnail: basic TIFF properties about the embedded thumbnail
  • Photo: full exif data
  • GPSInfo: GPS/location data about the image
  • Iop: interoperability information

Not all of these properties will always be defined.

All standard Exif tags are supported.

Here is some example output:

{
  bigEndian: false,
  Image: {
    ImageWidth: 2448,
    ImageLength: 3264,
    Make: 'Some Make',
    Model: 'Some Model',
    Orientation: 1,
    XResolution: 72,
    YResolution: 72,
    ResolutionUnit: 2,
    Software: 'HDR+ 1.0.520435816zd',
    DateTime: 2023-05-20T17:02:00.000Z,
    YCbCrPositioning: 1,
  },
  Thumbnail: {
    ImageWidth: 219,
    ImageLength: 292,
    Compression: 6,
    Orientation: 1,
    XResolution: 72,
    YResolution: 72,
    ResolutionUnit: 2,
  },
  Photo: {
    ExposureTime: 0.016679,
    FNumber: 2,
    ExposureProgram: 2,
    ISOSpeedRatings: 129,
    ExifVersion: Buffer(4) [Uint8Array] [ 48, 50, 51, 50 ],
    DateTimeOriginal: 2023-05-20T17:02:00.000Z,
    DateTimeDigitized: 2023-05-20T17:02:00.000Z,
    OffsetTime: '+02:00',
    OffsetTimeOriginal: '+02:00',
    OffsetTimeDigitized: '+02:00',
    ShutterSpeedValue: 5.91,
    ApertureValue: 2,
    BrightnessValue: 2.54,
    ExposureBiasValue: 0,
    MaxApertureValue: 2,
    SubjectDistance: 0.35,
    MeteringMode: 2,
    Flash: 16,
    FocalLength: 2.57,
    SubSecTime: '811',
    SubSecTimeOriginal: '811',
    SubSecTimeDigitized: '811',
    FlashpixVersion: Buffer(4) [Uint8Array] [ 48, 49, 48, 48 ],
    ColorSpace: 1,
    PixelXDimension: 2448,
    PixelYDimension: 3264,
    InteroperabilityTag: 958,
    SensingMethod: 2,
    CustomRendered: 1,
    ExposureMode: 0,
    WhiteBalance: 0,
    DigitalZoomRatio: 1.4,
    FocalLengthIn35mmFilm: 24,
    SceneCaptureType: 0,
    Contrast: 0,
    Saturation: 0,
    Sharpness: 0,
    SubjectDistanceRange: 1,
    LensMake: 'Some Lens Make',
    LensModel: 'Some front camera 2.57mm f/2.0',
    CompositeImage: 3
  },
  GPSInfo: {
    GPSLatitudeRef: 'N',
    GPSLatitude: [ 49, 1, 3.12 ],
    GPSLongitudeRef: 'E',
    GPSLongitude: [ 11, 1, 4.56 ],
    GPSAltitudeRef: 0,
    GPSAltitude: 296.1,
    GPSTimeStamp: [ 15, 1, 48 ],
    GPSImgDirectionRef: 'M',
    GPSImgDirection: 258,
    GPSDateStamp: '2023:05:20'
  }
}

License

MIT

exif-reader's People

Contributors

atombrenner avatar blakeembrey avatar devongovett avatar inukshuk avatar lovell avatar papandreou avatar paxvista avatar thomasgassmann avatar tpishi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

exif-reader's Issues

Little endian EXIF within a HEIF image

Hey.
Gives an error when trying to read exif data from .avif format

Error: Invalid EXIF data: buffer should start with "Exif", "MM" or "II".

Does this library not support avif parsing?

PNG, little endian without Exif\0\0 prefix: Invalid EXIF data: buffer should start with "Exif", "MM" or "II".

Code

  const sharpImage = sharp(src, { animated: true });

  sharpImage.png({ quality: quality });

  sharpImage.withExif({
    IFD0: {
      Software: `sharp:${quality}`,
    },
  });

  sharpImage.keepMetadata();

  sharpImage.keepExif();

  const buffer = await sharpImage.toBuffer();

  const { exif } = await sharp(buffer).metadata();

  console.log(exif?.toString());

  try {
    if (exif !== undefined) {
      console.log(exif.toString().substring(0, 2) === "II");
      console.log(ExifReader.load(exif));
    }
  } catch (err) {
    console.log(err);
  }

Buffer to string

II↕☺♥☺☺→☺♣☺b☺♣☺(☺♥☺☻1☺☻ r‼☻♥☺☺i�♦☺|x2☻�♥x2☻�♥sharp:80♠�♦0210☺�♦☺☻♥�♦0100☺�♥☺��☻�♦☺�☻♥�♦☺ ♥

Exception

Error: Invalid EXIF data: buffer should start with "Exif", "MM" or "II".
    at module.exports (\node_modules\exif-reader\index.js:8:13)
    at test (\vite.config.ts:130:50)
    at async FSWatcher.<anonymous> (\vite.config.ts:102:5)

Typescript Definitions

If you use this project with typescript, you have to create a declaration file every time to prevent this error:

Could not find a declaration file for module 'exif-reader'. '/home/Code/node_modules/exif-reader/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/exif-reader` if it exists or add a new declaration (.d.ts) file containing `declare module 'exif-reader';`

It will be easier to add type definitions directly to this project instead of maintaining a mirror in the already too large DefinetelyTyped (@types) project.

Can't parse array buffer returned by axios: Invalid EXIF data: buffer should start with "Exif", "MM" or "II".

import axios from "axios";
import exifReader from "exif-reader";

async function fetchAndParseEXIF(url) {
  try {
    const response = await axios.get(url, {
      responseType: "arraybuffer",
    });

    console.log("Buffer length:", response.data.byteLength);

    const exifData = exifReader(response.data);

    console.log(exifData);
  } catch (error) {
    console.error("Error fetching or parsing EXIF data:", error);
  }
}

fetchAndParseEXIF("http://lzwlkj.oss-cn-shenzhen.aliyuncs.com/jahy/vc-upload-1713346760053-4.jpg");

When there is damaged Exif header - it causes out of memory

If Exif offsets happen to be random garbage - package tries to split at those random positions without validation. This will cause "Out Of Memory" error and process stop node itself.

I'd suggest as first command in readTag function add validation of abnormal valueOffset and numValues:

function readTag(buffer, offset, bigEndian) {
...
    // Prevent damaged Exif data to cause Out Of Memory
    if (valueOffset >= buffer.length || numValues > 1000000 || valueOffset + numValues * valueSize >= buffer.length)
      throw new Error("Damaged Exif data");

numValues > 1000000 (just assumed very large number) - but without this check - last comparsion may not always work - it can rollower.

Attached damaged header Exif information
damaged_header.zip

data: buffer should start with "Exif"

trying to read a buffer created using:
var exifreader = Npm.require('exif-reader');

var buf = Buffer.from(fileObj.blob, 'binary');
var meta = exifreader(buf);

RFC: Use standard Exif group and tag names

Use standard Exif group and tag names generated from Exiv2 metatdata

Note: This is a RFC and not a real issue. My intention is to get
feedback about an idea I had when tried to solve my own issue #27 for better
Typescript support.

While working on this issue I noticed some things that made me scratch my head

  • where could I find an official Exif spec?
  • why are tags distributed into different groups?
  • why do we have the same tag name for different tag ids?
  • what are the correct types? Where are they specified?
  • why are some tags missing and are accessible only by tag id?

So I spent some time looking at exiftool
which seems to be the original inspiration to this project.

Then I found the nice Exiv2 project with
a working link to the Exif spec and
a well structured list of all standard Exif tags together with type information.

When I realised that the exiv2 cli was already installed on my machine, I used it
to compare the ouptut of exiv2 and exif-reader with exiv2 -p e some.jpg.

IMHO the exiv2 project is trying to follow the spec one to one, while the exiftool project
diverges a bit. For example the tag 0x0132 is called DateTime in Exif and Exiv2, but ModifyDate
in exiftool and exif-reader. Exiftool lists tags that are not found in the specs.
The exiv2 project provides structured access to the data type of each tag, my
original motiviation for starting all this.

So my proposal is, can we just generate the tags.js file and the type definition index.d.ts
based on the metadata from eviv2? That would give us some benefits

  • standard group and tagnames, reuse of the eviv2 documentation
  • a more uptodate list of tags
  • automatic generated typescript types

It also has some drawbacks:

  • some tag names would change (e.g. ModifyDate to DateTime) so this
    is a breaking change tha needs a major (2.0) release
  • non Exif tags (e.g. InkSet, InkNames or FaxRecvParams) now no longer have a tag name (but would
    still be accessible by tag id if they are actually inside a file)
  • dependent project must apply changes when upgrading (easy with Typescript support)

I prepared a branch of my proposed change. Please have a look.

I think this change would align this project with the Exif Spec,
but I fully understand that this is a breaking change that will cause effort for users of this project.
In most cases it's just adjusting tag names. The following table of changed tag names
will help with that. Only if someone relied on the edge case, when a file really contains
different values for different tags with the same name (e.g. WhiteBalance),
they will experience a behavioural change.

Duplicate Tag Names

This is most probable a bug in exif-reader, as those tags would return wrong results if
they exist in the same file:

Tag Name TagIds
ImageWidth 0x0100, 0xbc80
ImageHeight 0x0101, 0xbc81
JPEGTables 0x015b, 0x01b5
FlashEnergy 0x920b, 0xa20b
SpatialFrequencyResponse 0x920c, 0xa20c
Noise 0x920d, 0xa20d
FocalPlaneXResolution 0x920e, 0xa20e
FocalPlaneYResolution 0x920f, 0xa20f
FocalPlaneResolutionUnit 0x9210, 0xa210
ImageNumber 0x9211, 0xa211
SecurityClassification 0x9212, 0xa212
ImageHistory 0x9213, 0xa213
ExposureIndex 0x9215, 0xa215
TIFF-EPStandardID 0x9216, 0xa216
SensingMethod 0x9217, 0xa217
WhiteBalance 0xa403, 0xfe4e
Contrast 0xa408, 0xfe54
Saturation 0xa409, 0xfe55
Sharpness 0xa40a, 0xfe56

Changed Tag Names

Current Tag Name Proposed Tag Name Exiv2/Exif
InteropIndex InteroperabilityIndex
InteropVersion InteroperabilityVersion
OldSubfileType SubfileType
ImageHeight ImageLength
ModifyDate DateTime
SubIFD SubIFDs
NumberofInks NumberOfInks
ThumbnailOffset JPEGInterchangeFormat
ThumbnailLength JPEGInterchangeFormatLength
ApplicationNotes XMLPacket
RelatedImageHeight RelatedImageLength
CFAPattern2 CFAPattern
IPTC-NAA IPTCNAA
PhotoshopSettings ImageResources
ExifOffset ExifTag
ICC_Profile InterColorProfile
GPSInfo GPSTag
ISO ISOSpeedRatings
Opto-ElectricConvFactor OECF
TIFF-EPStandardID TIFFEPStandardID
InteropOffset InteroperabilityTag
FocalLengthIn35mmFormat FocalLengthIn35mmFilm
PrintIM PrintImageMatching
DNGLensInfo LensInfo
CameraCalibrationSig CameraCalibrationSignature
ProfileCalibrationSig ProfileCalibrationSignature
ProfileIFD ExtraCameraProfiles
OriginalBestQualitySize OriginalBestQualityFinalSize

New Tag Names

Current Tag Name Proposed Tag Name Exiv2/Exif
28722 VignettingCorrParams
28725 ChromaticAberrationCorrParams
28727 DistortionCorrParams
51177 DepthFormat
51178 DepthNear
51179 DepthFar
51180 DepthUnits
51181 DepthMeasureType
51182 EnhanceParams
52525 ProfileGainTableMap
52526 SemanticName
52528 SemanticInstanceID
52529 CalibrationIlluminant3
52530 CameraCalibration3
52531 ColorMatrix3
52532 ForwardMatrix3
52533 IlluminantData1
52534 IlluminantData2
52535 IlluminantData3
52536 MaskSubArea
52537 ProfileHueSatMapData3
52538 ReductionMatrix3
52539 RGBTables
36880 OffsetTime
36881 OffsetTimeOriginal
36882 OffsetTimeDigitized
37888 Temperature
37889 Humidity
37890 Pressure
37891 WaterDepth
37892 Acceleration
37893 CameraElevationAngle
42080 CompositeImage
42081 SourceImageNumberOfCompositeImage
42082 SourceExposureTimesOfCompositeImage

Non standard Tag Names (removed)

A sampling of those values on https://exiftool.org/TagNames/EXIF.html indicates that they are either
offsets to vendor specific IFDs or are not part of any IFD (basicly undocumented on exiftool)

Current Tag Name Generic Tag Id, not present in Exif Standard
MinSampleValue 280
MaxSampleValue 281
FreeOffsets 288
FreeByteCounts 289
ColorResponseUnit 300
BadFaxLines 326
CleanFaxData 327
ConsecutiveBadFaxLines 328
GlobalParametersIFD 400
ProfileType 401
FaxProfile 402
CodingMethods 403
VersionYear 404
ModeNumber 405
Decode 433
DefaultImageColor 434
T82Options 435
StripRowCounts 559
USPTOMiscellaneous 999
XP_DIP_XML 18247
StitchInfo 18248
WangTag1 32931
WangAnnotation 32932
WangTag3 32933
WangTag4 32934
Matteing 32995
DataType 32996
ImageDepth 32997
TileDepth 32998
Model2 33405
KodakIFD 33424
MDFileTag 33445
MDScalePixel 33446
MDColorTable 33447
MDLabName 33448
MDSampleInfo 33449
MDPrepDate 33450
MDPrepTime 33451
MDFileUnits 33452
PixelScale 33550
AdventScale 33589
AdventRevision 33590
UIC1Tag 33628
UIC2Tag 33629
UIC3Tag 33630
UIC4Tag 33631
IntergraphPacketData 33918
IntergraphFlagRegisters 33919
IntergraphMatrix 33920
INGRReserved 33921
ModelTiePoint 33922
Site 34016
ColorSequence 34017
IT8Header 34018
RasterPadding 34019
BitsPerRunLength 34020
BitsPerExtendedRunLength 34021
ColorTable 34022
ImageColorIndicator 34023
BackgroundColorIndicator 34024
ImageColorValue 34025
BackgroundColorValue 34026
PixelIntensityRange 34027
TransparencyIndicator 34028
ColorCharacterization 34029
HCUsage 34030
TrapIndicator 34031
CMYKEquivalent 34032
SEMInfo 34118
AFCP_IPTC 34152
PixelMagicJBIGOptions 34232
ModelTransform 34264
WB_GRGBLevels 34306
LeafData 34310
TIFF_FXExtensions 34687
MultiProfiles 34688
SharedData 34689
T88Options 34690
ImageLayer 34732
GeoTiffDirectory 34735
GeoTiffDoubleParams 34736
GeoTiffAsciiParams 34737
FaxRecvParams 34908
FaxSubAddress 34909
FaxRecvTime 34910
LeafSubIFD 34954
CIP3DataFile 37434
CIP3Sheet 37435
CIP3Side 37436
StoNits 37439
MSDocumentText 37679
MSPropertySetStorage 37680
MSDocumentTextPosition 37681
ImageSourceData 37724
TIFF-EPStandardID 41494
GDALMetadata 42112
GDALNoData 42113
ExpandSoftware 44992
ExpandLens 44993
ExpandFilm 44994
ExpandFilterLens 44995
ExpandScanner 44996
ExpandFlashLamp 44997
PixelFormat 48129
Transformation 48130
Uncompressed 48131
ImageType 48132
ImageHeight 48257
WidthResolution 48258
HeightResolution 48259
ImageOffset 48320
ImageByteCount 48321
AlphaOffset 48322
AlphaByteCount 48323
ImageDataDiscard 48324
AlphaDataDiscard 48325
OceScanjobDesc 50215
OceApplicationSelector 50216
OceIDNumber 50217
OceImageLogic 50218
Annotations 50255
USPTOOriginalContentType 50560
RawImageSegmentation 50752
AliasLayerMetadata 50784
PanasonicTitle 50898
PanasonicTitle2 50899
Padding 59932
OffsetSchema 59933
OwnerName 65000
SerialNumber 65001
Lens 65002
KDC_IFD 65024
RawFile 65100
Converter 65101
Exposure 65105
Shadows 65106
Brightness 65107
Smoothness 65111
MoireFilter 65112

Support for non-ASCII charsets

According to the spec, exif only supports ASCII.

2 = ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.

Yet in practice, a lot of tools write UTF8 text into fields such as ImageDescription.

My suggestion would be to optionally support different charsets when decoding exif type 2.

If that's a change you're willing to accept, I'd gladly submit a PR.

Exif from PNGs with eXIf chunk

Hi there!

I just ran into the same issue as #11 ("Buffer must start with Exif") when using exif-reader on the "exif data" from a PNG. I'm using sharp to extract the metadata (as per the example in that other thread)

const sharp = require('sharp');
const exifReader = require('exif-reader');

sharp('example.png')
  .metadata()
  .then(({ exif }) => {
    const exifProperties = exifReader(exif);
    console.log(exifProperties);
  });

is this supposed to work? Is exif-reader capable of reading the exif data coming from a PNG? I'm assuming the error is thrown because of the format differences between exif data in JPEGs vs "exif" data under metadata chunks in PNGs? 🤔

On some images Orientation gets reported incorrectly

Having tested several node/js exif parsers there appears to be a bug in your implementation.

Certain Images report having an Orientation of 6 when all other readers report a value of 8. I'm not sure why this would be but I have been able to confirm that it is yours that is incorrect as transforming the resulting image based upon the your retrieved Orientation value shows an incorrectly rotated image.

DateTime?? or MoidyDate sometimes illegal value when the parsing day is 31st

Hi.

In the function parseDate, date.setUTCMonth() is called after new Date() (means current local time).
But, if the current date is 31st and the parsing value is like "2016:09:17 09:36:23",
then date.setUTCMonth('09'-1) cannot change the month to September but October since the day
has been set to 31st in the constructor. So, the parsed day is "Mon Oct 17 2016 18:36:23"

I think if the value date is initialized not new date(), but something fix day time like
new Date(2001,0,2,0,0,0,0); (Jan, 2nd 2001 00:00:00 in the local time),
this illegal value will not be occurred.

You can easily reproduce if new Date() changes to new Date(2016,11,31,23,59,59,0); for example.

Wrong type definition export

The current export of the type definition in index.d.ts looks like this:

export default function exif(buffer: Buffer): Exif;

However, the current implementation in index.js does not export any default. The type definition should actually look like this (similar to the old type definitions):

declare function exif(buffer: Buffer): Exif;
export = exif;

or you need to adapt the exports in index.js appropriately.

When I import the library using import exifReader from 'exif-reader'; I will get following runtime error:

(0 , exif_reader_1.default) is not a function

It only works when I import and use it the following way:

import * as exifReader from 'exif-reader';

const metadata = await sharp(file).metadata();
 // @ts-ignore
const exif = exifReader(metadata.exif);

(I cannot set "esModuleInterop": true in tsconfig due to some other library.)

Any get EXIF from video files?

Hi,

great piece of code. Works well with images. however I was looking into getting exif data from video formats. Do you know anything about it? I would love to make that work.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.