### Install Exifr using npm
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Install the Exifr package using npm for Node.js projects.
```bash
npm install exifr
```
--------------------------------
### Importing Exifr using CommonJS
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Example of how to import and use Exifr in a Node.js environment using the CommonJS module system.
```javascript
const exifr = require('exifr')
async function run () {
const exif = await exifr.parse(file)
console.log(exif)
}
run()
```
--------------------------------
### Basic Usage: Reading EXIF Data
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Demonstrates how to read EXIF data from an image file using Exifr. This is a fundamental example for getting started.
```javascript
import exifr from 'exifr'
const exif = await exifr.parse(file)
console.log(exif)
```
--------------------------------
### Importing Exifr using ES Modules
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Example of how to import and use Exifr in an environment that supports ES Modules, such as modern browsers or Node.js with module support.
```javascript
import exifr from 'exifr'
async function run () {
const exif = await exifr.parse(file)
console.log(exif)
}
run()
```
--------------------------------
### XMP XML to JSON Parsing Example
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Demonstrates how Exifr's minimalistic XML parser transforms a given XMP structure into a JSON object, illustrating rules for attributes, simple tags, and arrays.
```xml
Mike KovaříkSome string herejpegxmptiffiptc
```
```js
{
name: 'Exifr', // attribute belonging to the same namespace
author: 'Mike Kovařík', // simple tag of the namespace
description: {lang: 'en-us', value: 'Some string here'}, // tag with attrs and value becomes object
formats: 'jpeg', // single item array is unwrapped
segments: ['xmp', 'tiff', 'iptc'] // array as usual
}
```
--------------------------------
### Image Thumbnail Extraction Example
Source: https://github.com/mikekovarik/exifr/blob/master/examples/thumbnail.html
This JavaScript code snippet demonstrates the process of extracting a thumbnail from an image using the Exifr library. It handles image loading, thumbnail extraction, and displays image dimensions and extraction time. It also includes error handling for files without thumbnails.
```javascript
function promiseImg(img) {
if (img.naturalWidth !== 0) {
return Promise.resolve()
} else {
return new Promise((resolve, reject) => {
img.onload = resolve
img.onerror = reject
})
}
}
var promiseTimeout = millis => new Promise(resolve => setTimeout(resolve, millis))
let original = document.querySelector("#original")
let thumbnail = document.querySelector("#thumbnail")
let originalDesc = document.querySelector("#original-desc")
let thumbnailDesc = document.querySelector("#thumbnail-desc")
processFile('../test/fixtures/IMG_20180725_163423.jpg')
async function processFile(arg) {
let url
if (arg instanceof Blob)
url = URL.createObjectURL(arg)
else
url = arg
original.src = url
await promiseImg(original)
// original image loaded, extract thumb
let t0 = performance.now()
thumbnail.src = await exifr.thumbnailUrl(original)
console.log('original ', original.src)
console.log('thumbnail', thumbnail.src)
let t1 = performance.now()
// thumb extracted
printImgInfo(original, originalDesc)
try {
await promiseTimeout() // needed for reloading after selecting another img
await promiseImg(thumbnail)
printImgInfo(thumbnail, thumbnailDesc, `extracted in ${Math.round(t1 - t0)} ms`)
} catch (err) {
printImgInfo(thumbnail, thumbnailDesc, `The file has no thumbnail`)
}
}
function printImgInfo(img, pre, ...lines) {
if (img.naturalWidth > 0 && img.naturalHeight > 0) {
pre.innerHTML = [
`width: ${img.naturalWidth}`,
`height: ${img.naturalHeight}`,
...lines
].join('\n')
} else {
pre.innerHTML = lines.join('\n')
}
}
document.querySelector('input[type="file"]').addEventListener('change', async e => {
processFile(e.target.files[0])
})
```
--------------------------------
### Extracting Full TIFF Segment
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
This example demonstrates how to extract the entire TIFF segment from an image file, which contains all IFD blocks and other related data.
```javascript
import exifr from 'exifr'
const exif = await exifr.tiff(file)
console.log(exif)
```
--------------------------------
### Extracting Thumbnail Image Data
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Provides examples for obtaining the thumbnail image data as a buffer or as an object URL for direct use in browsers.
```javascript
let thumbBuffer = await exifr.thumbnail(file)
// or get object URL (browser only)
img.src = await exifr.thumbnailUrl(file)
```
--------------------------------
### Extract Image Rotation Data
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Use this snippet to get rotation instructions for an image. It provides angle, mirroring, and dimension swap information, crucial for handling browser autorotation quirks.
```javascript
let r = await exifr.rotation(image)
if (r.css) {
img.style.transform = `rotate(${r.deg}deg) scale(${r.scaleX}, ${r.scaleY})`
}
```
--------------------------------
### Demo Initialization and Event Listeners
Source: https://github.com/mikekovarik/exifr/blob/master/examples/legacy.html
Sets up event listeners for three demo buttons and initializes the first demo on page load. It also includes logic to clear the output before running a demo if the `clear` argument is true.
```javascript
document.getElementById('demo1').addEventListener('click', runDemo1)
document.getElementById('demo2').addEventListener('click', runDemo2)
document.getElementById('demo3').addEventListener('click', runDemo3)
function runDemo1(clear) {
if (clear) $output.innerHTML = 'parsing file'
parseFile('../test/fixtures/IMG_20180725_163423-tiny.jpg')
}
function runDemo2(clear) {
if (clear) $output.innerHTML = 'extracting depth map'
extractDepthMap('../test/fixtures/xmp depth map.jpg', {xmp: true, mergeOutput: false, multiSegment: true})
}
function runDemo3(clear) {
if (clear) $output.innerHTML = 'parsing file'
parseFile('../test/fixtures/IMG_20180725_163423-tiny.jpg', {tiff: false, icc: true, multiSegment: true})
}
// load demo file first
runDemo1(false)
```
--------------------------------
### Instantiate and Use Exifr Class
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Shows how to manually instantiate the Exifr class for efficient simultaneous parsing of metadata and thumbnail extraction. Remember to close the file handle in Node.js if read in chunked mode.
```javascript
let exr = new Exifr(options)
await exr.read(file)
let output = await exr.parse()
let buffer = await exr.extractThumbnail()
await exr.file?.close?.()
```
--------------------------------
### Initialize Exifr and Event Listeners
Source: https://github.com/mikekovarik/exifr/blob/master/benchmark/gps-dnd.html
Imports the Exifr library and sets up event listeners for file drops and input changes to handle image processing. It targets HTML elements for logging and file input.
```javascript
import exifr from '../src/bundles/full.mjs'
import {gpsOnlyOptions, Exifr} from '../src/bundles/full.mjs'
let $log = document.querySelector('#log')
let memUsed = 0
let dropzone = document.body
dropzone.addEventListener('dragenter', e => e.preventDefault())
dropzone.addEventListener('dragover', e => e.preventDefault())
dropzone.addEventListener('drop', e => {
e.preventDefault()
handleFiles(e.dataTransfer.files)
})
document.querySelector('input[type="file"]').addEventListener('change', e => {
e.preventDefault()
handleFiles(e.target.files)
})
```
--------------------------------
### Customizing Exifr Build
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Shows how to create a custom build of Exifr by importing only specific components like file readers, segment parsers, and dictionaries. This can reduce bundle size.
```javascript
import parse from 'exifr/src/parsers/parse'
import readBlob from 'exifr/src/readers/blob'
import dictionary from 'exifr/src/dictionaries/exiftool'
const exif = await parse(file, {
fileReader: readBlob,
dictionary: dictionary
})
console.log(exif)
```
--------------------------------
### Basic Exifr Parsing
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Demonstrates two ways to parse EXIF data: directly from a file path or by providing a file buffer.
```javascript
// exifr reads the file from disk, only a few hundred bytes.
exifr.parse('./myimage.jpg')
.then(output => console.log('Camera:', output.Make, output.Model))
// Or read the file on your own and feed the buffer into exifr.
fs.readFile('./myimage.jpg')
.then(exifr.parse)
.then(output => console.log('Camera:', output.Make, output.Model))
```
--------------------------------
### Import Exifr in Node.js (CommonJS and ESM)
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Demonstrates how to import Exifr in Node.js environments using both CommonJS and ES Module syntax. The 'full' bundle is used by default.
```javascript
// Modern Node.js can import CommonJS
import exifr from 'exifr' // => exifr/dist/full.umd.cjs
// Explicily import ES Module
import exifr from 'exifr/dist/full.esm.mjs' // to use ES Modules
// CommonJS, old Node.js
var exifr = require('exifr') // => exifr/dist/full.umd.cjs
```
--------------------------------
### Include Exifr in Browsers (ESM, UMD, Legacy)
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Shows how to include Exifr in web pages using different script formats. The 'lite' bundle is recommended for browsers.
```html
```
--------------------------------
### Import Exifr using named exports
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Illustrates an alternative way to import Exifr using named exports, although the default export is recommended.
```javascript
import * as exifr from 'exifr'
```
--------------------------------
### UMD Integration in Browser
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Shows how to use Exifr in a browser environment by including the UMD build via a script tag. Parses EXIF data from an image element.
```html
```
--------------------------------
### Main Script: Spawn Worker and Handle Messages
Source: https://github.com/mikekovarik/exifr/blob/master/examples/worker.html
Spawns a Web Worker to process an image file and logs the time taken and EXIF data received. Ensure 'worker.js' is in the same directory.
```javascript
let worker = new Worker('worker.js')
let pre = document.querySelector('pre')
function log(string) {
pre.innerText += string + '\n'
}
log("main script spawned worker")
let t1 = performance.now()
worker.postMessage('../test/fixtures/IMG_20180725_163423.jpg')
worker.onmessage = e => {
let t2 = performance.now()
log(`${(t2 - t1).toFixed(1)} ms`)
log('main script received exif from worker')
log('-------------------------------------------------------')
log(JSON.stringify(e.data, null, 2))
}
```
--------------------------------
### Parse Sidecar Files with Exifr
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Demonstrates how to parse sidecar metadata files like .xmp or .icc. The third argument can optionally specify the segment type for performance.
```javascript
exifr.sidecar('./img_1234.icc')
```
```javascript
exifr.sidecar('./img_1234.icc', {translateKeys: false})
```
```javascript
exifr.sidecar('./img_1234.colorprofile', {translateKeys: false}, 'icc')
```
--------------------------------
### Using Base64 String as Input
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Demonstrates how to use a Base64 encoded image string as input for Exifr parsing. Useful when images are stored as strings rather than files.
```javascript
import exifr from 'exifr'
const exif = await exifr.parse(base64String)
console.log(exif)
```
--------------------------------
### Exifr Benchmark: Overall Performance Comparison
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
This benchmark compares the average time taken by Exifr, exifreader, and exiftool to process a large number of photos. Exifr shows superior performance.
```text
2036 photos (in total 22GB):
lib | average | all files
---------------------------------
exifr | 2.5ms | 5s <--- !!!
exifreader | 9.5ms | 19.5s
exiftool | 76ms | 154s
```
--------------------------------
### Import Map Configuration for Exifr Tests
Source: https://github.com/mikekovarik/exifr/blob/master/test/index.html
Defines import map for test dependencies. Ensure you are using a compatible browser and have necessary flags enabled.
```json
{ "imports": { "chai": "./empty.mjs", "path": "./empty.mjs", "express": "./empty.mjs", "child_process": "./empty.mjs", "util": "./empty.mjs", "fs": "./empty.mjs" } }
```
--------------------------------
### Exifr Benchmark: Chunked vs. Whole File Reading
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
This benchmark demonstrates the performance difference between reading an entire file and reading only the necessary chunks for metadata extraction. Reading by chunks is significantly faster.
```text
user reads file 8.4 ms
exifr reads whole file 8.2 ms
exifr reads file by chunks 0.5 ms <--- !!!
only parsing, not reading 0.2 ms <--- !!!
```
--------------------------------
### Reading EXIF Data with Options
Source: https://github.com/mikekovarik/exifr/blob/master/index.html
Shows how to parse EXIF data with specific options, such as including TIFF segments or sanitizing values. Useful for fine-tuning the parsing process.
```javascript
import exifr from 'exifr'
const exif = await exifr.parse(file, {
tiff: {
ifd0: true,
exif: true,
gps: true,
interop: true,
ifd1: true
},
makerNote: true,
userComment: true,
xmp: true,
icc: true,
iptc: true,
jfif: true,
ihdr: true,
mergeOutput: true,
sanitize: true,
reviveValues: true,
translateKeys: true,
translateValues: true,
multiSegment: true
})
console.log(exif)
```
--------------------------------
### ESM Integration in Browser
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Demonstrates using Exifr in modern browsers with ES Modules. Parses EXIF data from multiple files selected via an input element.
```html
```
--------------------------------
### Shortcut for Picking Specific TIFF Tags
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Shows how to use shortcuts to selectively extract specific tags from EXIF and GPS TIFF blocks.
```js
// Only extract FNumber + ISO tags from EXIF and GPSLatitude + GPSLongitude from GPS
{
exif: true, gps: true,
pick: ['FNumber', 'ISO', 'GPSLatitude', 0x0004] // 0x0004 is GPSLongitude
}
// is a shortcut for
{exif: ['FNumber', 'ISO'], gps: ['GPSLatitude', 0x0004]}
// which is another shortcut for
{exif: {pick: ['FNumber', 'ISO']}, gps: {pick: ['GPSLatitude', 0x0004]}}
```
--------------------------------
### Importing Modules for Custom HEIC/TIFF Build
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Import modules for parsing HEIC and TIFF files, extracting TIFF segment data, and using TIFF EXIF value dictionaries. This configuration avoids importing file readers, assuming data is provided as Uint8Array.
```javascript
import * as exifr from 'exifr/src/core.mjs'
import 'exifr/src/file-parsers/heic.mjs'
import 'exifr/src/file-parsers/tiff.mjs'
import 'exifr/src/segment-parsers/tiff.mjs'
import 'exifr/src/dicts/tiff-exif-values.mjs'
```
--------------------------------
### Exifr class
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Provides a class-based interface for instantiating Exifr, reading files, and parsing metadata or extracting thumbnails efficiently, especially when both operations are needed.
```APIDOC
## `Exifr` class
### Description
Provides a class-based interface for instantiating Exifr, reading files, and parsing metadata or extracting thumbnails efficiently, especially when both operations are needed.
### Constructor
- `new Exifr(options)`: Instantiates a new Exifr object with optional configuration.
### Methods
- `.read(file)`: Loads the specified file into the Exifr instance.
- `.parse()`: Parses the loaded file to extract EXIF data.
- `.extractThumbnail()`: Extracts the embedded thumbnail from the loaded file.
- `.file?.close?.()`: Closes the file handle if opened in chunked mode (Node.js specific).
### Usage Example
```js
let exr = new Exifr(options)
await exr.read(file)
let output = await exr.parse()
let buffer = await exr.extractThumbnail()
await exr.file?.close?.()
```
```
--------------------------------
### Global Error Handler and Output Function
Source: https://github.com/mikekovarik/exifr/blob/master/examples/legacy.html
Sets up a global error handler to log issues and a function to print output to the DOM. Uses `var` for older browser compatibility.
```javascript
var $output = document.querySelector('#output')
var $reload = document.querySelector('#reload')
window.onerror = function(message, source, lone, col, error) {
console.log('ONERROR')
var lines = [
'********************** ERROR **********************',
'message: ' + message,
'source: ' + source,
'lone: ' + lone,
'col: ' + col
]
if (error) {
lines.push('description: ' + error.description)
lines.push('message: ' + error.message)
lines.push('name: ' + error.name)
lines.push('number: ' + error.number)
lines.push(error.stack)
}
printOutput(lines)
}
function printOutput(lines) {
$output.innerHTML += '\n' + lines.join('\n') + '\n\n'
}
```
--------------------------------
### parse(file[, options])
Source: https://github.com/mikekovarik/exifr/blob/master/README.md
Parses EXIF data from a given file and returns an object containing the EXIF information. An optional options argument can be provided to customize the parsing behavior.
```APIDOC
## `parse(file[, options])`
### Description
Parses EXIF data from a given file and returns an object containing the EXIF information. An optional options argument can be provided to customize the parsing behavior.
### Parameters
#### Path Parameters
- **file** (string | Buffer | ArrayBuffer | Uint8Array | DataView | Blob | File | img element) - Required - The input file to parse. Can be a file path, URL, Base64 string, Buffer, ArrayBuffer, Blob, File, or an element.
- **options** (object) - Optional - Configuration options for parsing.
### Returns
- `Promise