Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@eris/exif

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eris/exif - npm Package Compare versions

Comparing version 0.4.2-alpha.13 to 0.4.2-alpha.14

3

dist/decoder/ifd-entry.js

@@ -52,2 +52,3 @@ "use strict";

case types_1.IFDDataType.Undefined:
case types_1.IFDDataType.Unknown:
return '';

@@ -78,3 +79,3 @@ default:

const dataReader = reader.readAsReader(4);
log.verbose(`read tag ${tags_1.getFriendlyName(tag)} (${tag})`);
log.verbose(`read tag ${tags_1.getFriendlyName(tag)} (tag: ${tag}, length: ${length})`);
return new IFDEntry(startOffset, tag, dataType, length, dataReader);

@@ -81,0 +82,0 @@ }

@@ -154,3 +154,3 @@ "use strict";

static isJPEG(buffer) {
return buffer[0] === 0xff && buffer[1] === 0xd8;
return buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff;
}

@@ -157,0 +157,0 @@ static injectEXIFMetadata(jpegBuffer, exifBuffer) {

@@ -6,2 +6,3 @@ /// <reference types="node" />

private readonly _reader;
private _variant;
private _ifds;

@@ -15,2 +16,8 @@ private _cachedMetadata;

private _readStripOffsetsAsJPEG;
/**
* Panasonic mislabels all of their tags so the names make no sense.
* The only thing they really label is the offset of the RAW data and the JPEG is before that.
* So we'll just search for JPEG markers in between the IFDs and the offset of the raw data.
*/
private _readPanasonicJPEG;
private _readLargestJPEG;

@@ -17,0 +24,0 @@ extractJPEG(options?: IJPEGOptions): IBufferLike;

@@ -11,3 +11,10 @@ "use strict";

const ifd_entry_1 = require("./ifd-entry");
const TIFF_MAGIC_VERSION = 42;
var Variant;
(function (Variant) {
Variant["Standard"] = "standard";
Variant["Olympus"] = "olympus";
Variant["Panasonic"] = "panasonic";
Variant["Unknown"] = "unknown";
})(Variant || (Variant = {}));
const TIFF_MAGIC_VERSION = 0x2a;
/**

@@ -18,2 +25,7 @@ * Olympus raw files are basically TIFFs but with a replaced magic text

const OLYMPUS_MAGIC_VERSION = 0x4f52;
/**
* Panasonic raw files are basically TIFFs but with a replaced magic text
* @see https://libopenraw.freedesktop.org/formats/rw2/
*/
const PANASONIC_MAGIC_VERSION = 0x55;
const log = log_1.createLogger('decoder');

@@ -40,3 +52,9 @@ class TIFFDecoder {

const version = this._reader.read(2);
if (version !== TIFF_MAGIC_VERSION && version !== OLYMPUS_MAGIC_VERSION) {
if (version === TIFF_MAGIC_VERSION)
this._variant = Variant.Standard;
if (version === OLYMPUS_MAGIC_VERSION)
this._variant = Variant.Olympus;
if (version === PANASONIC_MAGIC_VERSION)
this._variant = Variant.Panasonic;
if (this._variant === Variant.Unknown) {
throw new Error(`Unrecognized TIFF version: ${version.toString(16)}`);

@@ -122,2 +140,50 @@ }

}
/**
* Panasonic mislabels all of their tags so the names make no sense.
* The only thing they really label is the offset of the RAW data and the JPEG is before that.
* So we'll just search for JPEG markers in between the IFDs and the offset of the raw data.
*/
_readPanasonicJPEG() {
if (this._variant !== Variant.Panasonic)
return;
const ifdEntries = this.extractIFDEntries();
const searchStart = Math.max(...ifdEntries.map(value => value.startOffset));
const endEntry = this._ifds[0].entries.find(entry => entry.tag === types_1.IFDTag.PanasonicJPEGEnd);
if (!searchStart || !endEntry)
return;
const endEntryValue = endEntry.getValue();
if (typeof endEntryValue !== 'number')
return;
let startIndex = Infinity;
let endIndex = Infinity;
const buffer = this._reader.getBuffer();
for (let i = searchStart; i < endEntryValue; i++) {
if (buffer[i] !== 0xff)
continue;
if (buffer[i + 1] !== 0xd8)
continue;
if (buffer[i + 2] !== 0xff)
continue;
startIndex = i;
break;
}
for (let i = endEntryValue; i > searchStart; i--) {
if (buffer[i - 1] !== 0xff)
continue;
if (buffer[i] !== 0xd9)
continue;
endIndex = i;
break;
}
if (!Number.isFinite(startIndex))
return;
if (!Number.isFinite(endIndex))
return;
if (endIndex - startIndex < 4000)
return;
const jpegBuffer = buffer.slice(startIndex, endIndex + 1);
if (!jpeg_decoder_1.JPEGDecoder.isJPEG(jpegBuffer))
return;
return jpegBuffer;
}
_readLargestJPEG() {

@@ -138,4 +204,8 @@ // Try to read the JPEG thumbnail first

return maxThumbnailJPEG;
// Try the manufacturer specific previews if none the standard ones worked
const panasonicJPEG = this._readPanasonicJPEG();
if (panasonicJPEG)
return panasonicJPEG;
// Fail loudly if all else fails
throw new Error('Could not find thumbnail or read StripOffsets IFDs');
throw new Error('Could not find an embedded JPEG');
}

@@ -168,2 +238,6 @@ extractJPEG(options = {}) {

target[name] = value;
const panasonicName = tags_1.panasonicConversionTags[name];
if (this._variant === Variant.Panasonic && panasonicName) {
target[panasonicName] = value;
}
});

@@ -170,0 +244,0 @@ });

@@ -7,2 +7,3 @@ import { IBufferLike, IReader, Endian } from '../utils/types';

constructor(_buffer: IBufferLike, _position?: number, _endianness?: Endian);
getBuffer(): IBufferLike;
hasNext(): boolean;

@@ -9,0 +10,0 @@ getPosition(): number;

@@ -10,2 +10,5 @@ "use strict";

}
getBuffer() {
return this._buffer;
}
hasNext() {

@@ -12,0 +15,0 @@ return this._position < this._buffer.length;

@@ -7,2 +7,3 @@ import { IIFDTagDefinition, IFDTagName, XMPTagName } from './types';

export declare const xmpTags: Record<XMPTagName, boolean>;
export declare const panasonicConversionTags: Partial<Record<IFDTagName, IFDTagName>>;
export declare function getFriendlyName(code: number): IFDTagName;

@@ -14,2 +14,5 @@ "use strict";

};
exports.panasonicConversionTags = {
GPSDestBearingRef: 'ISO',
};
// TODO: fill in all IFDDataTypes with -1

@@ -16,0 +19,0 @@ const _tags = [

@@ -14,2 +14,3 @@ /// <reference types="node" />

export interface IReader {
getBuffer(): IBufferLike;
hasNext(): boolean;

@@ -77,3 +78,4 @@ getPosition(): number;

ThumbnailLength = 514,
EXIFOffset = 34665
EXIFOffset = 34665,
PanasonicJPEGEnd = 280
}

@@ -80,0 +82,0 @@ export declare enum IFDGroup {

@@ -23,2 +23,3 @@ "use strict";

IFDTag[IFDTag["EXIFOffset"] = 34665] = "EXIFOffset";
IFDTag[IFDTag["PanasonicJPEGEnd"] = 280] = "PanasonicJPEGEnd";
})(IFDTag = exports.IFDTag || (exports.IFDTag = {}));

@@ -25,0 +26,0 @@ var IFDGroup;

@@ -57,2 +57,3 @@ import {getFriendlyName} from '../utils/tags'

case IFDDataType.Undefined:
case IFDDataType.Unknown:
return ''

@@ -89,3 +90,3 @@ default:

log.verbose(`read tag ${getFriendlyName(tag)} (${tag})`)
log.verbose(`read tag ${getFriendlyName(tag)} (tag: ${tag}, length: ${length})`)
return new IFDEntry(startOffset, tag, dataType, length, dataReader)

@@ -92,0 +93,0 @@ }

@@ -199,3 +199,3 @@ import {TIFFDecoder} from '../decoder/tiff-decoder'

public static isJPEG(buffer: IBufferLike): boolean {
return buffer[0] === 0xff && buffer[1] === 0xd8
return buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff
}

@@ -202,0 +202,0 @@

import {IFD} from '../decoder/ifd'
import {getFriendlyName} from '../utils/tags'
import {getFriendlyName, panasonicConversionTags} from '../utils/tags'
import {Reader} from '../utils/reader'

@@ -23,3 +23,10 @@ import {TIFFEncoder} from '../encoder/tiff-encoder'

const TIFF_MAGIC_VERSION = 42
enum Variant {
Standard = 'standard',
Olympus = 'olympus',
Panasonic = 'panasonic',
Unknown = 'unknown',
}
const TIFF_MAGIC_VERSION = 0x2a
/**

@@ -30,2 +37,7 @@ * Olympus raw files are basically TIFFs but with a replaced magic text

const OLYMPUS_MAGIC_VERSION = 0x4f52
/**
* Panasonic raw files are basically TIFFs but with a replaced magic text
* @see https://libopenraw.freedesktop.org/formats/rw2/
*/
const PANASONIC_MAGIC_VERSION = 0x55

@@ -43,2 +55,3 @@ const log = createLogger('decoder')

private readonly _reader: IReader
private _variant: Variant
private _ifds: IIFD[]

@@ -67,3 +80,6 @@ private _cachedMetadata: IGenericMetadata

const version = this._reader.read(2)
if (version !== TIFF_MAGIC_VERSION && version !== OLYMPUS_MAGIC_VERSION) {
if (version === TIFF_MAGIC_VERSION) this._variant = Variant.Standard
if (version === OLYMPUS_MAGIC_VERSION) this._variant = Variant.Olympus
if (version === PANASONIC_MAGIC_VERSION) this._variant = Variant.Panasonic
if (this._variant === Variant.Unknown) {
throw new Error(`Unrecognized TIFF version: ${version.toString(16)}`)

@@ -164,2 +180,45 @@ }

/**
* Panasonic mislabels all of their tags so the names make no sense.
* The only thing they really label is the offset of the RAW data and the JPEG is before that.
* So we'll just search for JPEG markers in between the IFDs and the offset of the raw data.
*/
private _readPanasonicJPEG(): IBufferLike | undefined {
if (this._variant !== Variant.Panasonic) return
const ifdEntries = this.extractIFDEntries()
const searchStart = Math.max(...ifdEntries.map(value => value.startOffset))
const endEntry = this._ifds[0].entries.find(entry => entry.tag === IFDTag.PanasonicJPEGEnd)
if (!searchStart || !endEntry) return
const endEntryValue = endEntry.getValue()
if (typeof endEntryValue !== 'number') return
let startIndex = Infinity
let endIndex = Infinity
const buffer = this._reader.getBuffer()
for (let i = searchStart; i < endEntryValue; i++) {
if (buffer[i] !== 0xff) continue
if (buffer[i + 1] !== 0xd8) continue
if (buffer[i + 2] !== 0xff) continue
startIndex = i
break
}
for (let i = endEntryValue; i > searchStart; i--) {
if (buffer[i - 1] !== 0xff) continue
if (buffer[i] !== 0xd9) continue
endIndex = i
break
}
if (!Number.isFinite(startIndex)) return
if (!Number.isFinite(endIndex)) return
if (endIndex - startIndex < 4000) return
const jpegBuffer = buffer.slice(startIndex, endIndex + 1)
if (!JPEGDecoder.isJPEG(jpegBuffer)) return
return jpegBuffer
}
private _readLargestJPEG(): IBufferLike {

@@ -178,4 +237,9 @@ // Try to read the JPEG thumbnail first

if (maxThumbnailJPEG) return maxThumbnailJPEG
// Try the manufacturer specific previews if none the standard ones worked
const panasonicJPEG = this._readPanasonicJPEG()
if (panasonicJPEG) return panasonicJPEG
// Fail loudly if all else fails
throw new Error('Could not find thumbnail or read StripOffsets IFDs')
throw new Error('Could not find an embedded JPEG')
}

@@ -212,2 +276,7 @@

target[name] = value
const panasonicName = panasonicConversionTags[name]
if (this._variant === Variant.Panasonic && panasonicName) {
target[panasonicName] = value
}
})

@@ -214,0 +283,0 @@ })

@@ -10,2 +10,6 @@ import {IBufferLike, IReader, Endian} from '../utils/types'

public getBuffer(): IBufferLike {
return this._buffer
}
public hasNext(): boolean {

@@ -12,0 +16,0 @@ return this._position < this._buffer.length

@@ -17,2 +17,9 @@ import {IIFDTagDefinition, IFDTagName, IFDGroup, IFDDataType, XMPTagName} from './types'

export const panasonicConversionTags: Partial<Record<IFDTagName, IFDTagName>> = {
GPSDestBearingRef: 'ISO',
// Just figure these out with XNViewMP :/
// GPSLatitude: 'SensorWidth'
// GPSLongitudeRef: 'SensorHeight
}
// TODO: fill in all IFDDataTypes with -1

@@ -19,0 +26,0 @@ const _tags: Array<[IFDTagName, number, IFDDataType, IFDGroup]> = [

@@ -17,2 +17,3 @@ export interface ILogger {

export interface IReader {
getBuffer(): IBufferLike
hasNext(): boolean

@@ -89,2 +90,3 @@ getPosition(): number

EXIFOffset = 34665,
PanasonicJPEGEnd = 280, // MinSampleValue normally, marks the start of the RAW data
}

@@ -91,0 +93,0 @@

{
"name": "@eris/exif",
"version": "0.4.2-alpha.13",
"version": "0.4.2-alpha.14",
"description": "Parses EXIF data.",

@@ -41,3 +41,3 @@ "main": "./dist/index.js",

},
"gitHead": "88663db1a984e24d9a12a050161d805be91d8cb6"
"gitHead": "7ef5d393ef281749cb3ba173abf70056f879dad5"
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc