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

exif-js

Package Overview
Dependencies
Maintainers
3
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

exif-js - npm Package Compare versions

Comparing version 2.1.1 to 2.2.0

CHANGELOG.md

2

bower.json
{
"name": "exif-js",
"version": "2.1.1",
"version": "2.2.0",
"homepage": "https://github.com/exif-js/exif-js",

@@ -5,0 +5,0 @@ "authors": [

@@ -168,2 +168,26 @@ (function() {

// EXIF 2.3 Spec
var IFD1Tags = EXIF.IFD1Tags = {
0x0100: "ImageWidth",
0x0101: "ImageHeight",
0x0102: "BitsPerSample",
0x0103: "Compression",
0x0106: "PhotometricInterpretation",
0x0111: "StripOffsets",
0x0112: "Orientation",
0x0115: "SamplesPerPixel",
0x0116: "RowsPerStrip",
0x0117: "StripByteCounts",
0x011A: "XResolution",
0x011B: "YResolution",
0x011C: "PlanarConfiguration",
0x0128: "ResolutionUnit",
0x0201: "JpegIFOffset", // When image format is JPEG, this value show offset to JPEG data stored.(aka "ThumbnailOffset" or "JPEGInterchangeFormat")
0x0202: "JpegIFByteCount", // When image format is JPEG, this value shows data size of JPEG image (aka "ThumbnailLength" or "JPEGInterchangeFormatLength")
0x0211: "YCbCrCoefficients",
0x0212: "YCbCrSubSampling",
0x0213: "YCbCrPositioning",
0x0214: "ReferenceBlackWhite"
};
var StringValues = EXIF.StringValues = {

@@ -349,4 +373,6 @@ ExposureProgram : {

var iptcdata = findIPTCinJPEG(binFile);
var xmpdata= findXMPinJPEG(binFile);
img.exifdata = data || {};
img.iptcdata = iptcdata || {};
img.xmpdata = xmpdata || {};
if (callback) {

@@ -384,3 +410,3 @@ callback.call(img);

}
} else if (window.FileReader && (img instanceof window.Blob || img instanceof window.File)) {
} else if (self.FileReader && (img instanceof self.Blob || img instanceof self.File)) {
var fileReader = new FileReader();

@@ -646,2 +672,70 @@ fileReader.onload = function(e) {

/**
* Given an IFD (Image File Directory) start offset
* returns an offset to next IFD or 0 if it's the last IFD.
*/
function getNextIFDOffset(dataView, dirStart, bigEnd){
//the first 2bytes means the number of directory entries contains in this IFD
var entries = dataView.getUint16(dirStart, !bigEnd);
// After last directory entry, there is a 4bytes of data,
// it means an offset to next IFD.
// If its value is '0x00000000', it means this is the last IFD and there is no linked IFD.
return dataView.getUint32(dirStart + 2 + entries * 12, !bigEnd); // each entry is 12 bytes long
}
function readThumbnailImage(dataView, tiffStart, firstIFDOffset, bigEnd){
// get the IFD1 offset
var IFD1OffsetPointer = getNextIFDOffset(dataView, tiffStart+firstIFDOffset, bigEnd);
if (!IFD1OffsetPointer) {
// console.log('******** IFD1Offset is empty, image thumb not found ********');
return {};
}
else if (IFD1OffsetPointer > dataView.byteLength) { // this should not happen
// console.log('******** IFD1Offset is outside the bounds of the DataView ********');
return {};
}
// console.log('******* thumbnail IFD offset (IFD1) is: %s', IFD1OffsetPointer);
var thumbTags = readTags(dataView, tiffStart, tiffStart + IFD1OffsetPointer, IFD1Tags, bigEnd)
// EXIF 2.3 specification for JPEG format thumbnail
// If the value of Compression(0x0103) Tag in IFD1 is '6', thumbnail image format is JPEG.
// Most of Exif image uses JPEG format for thumbnail. In that case, you can get offset of thumbnail
// by JpegIFOffset(0x0201) Tag in IFD1, size of thumbnail by JpegIFByteCount(0x0202) Tag.
// Data format is ordinary JPEG format, starts from 0xFFD8 and ends by 0xFFD9. It seems that
// JPEG format and 160x120pixels of size are recommended thumbnail format for Exif2.1 or later.
if (thumbTags['Compression']) {
// console.log('Thumbnail image found!');
switch (thumbTags['Compression']) {
case 6:
// console.log('Thumbnail image format is JPEG');
if (thumbTags.JpegIFOffset && thumbTags.JpegIFByteCount) {
// extract the thumbnail
var tOffset = tiffStart + thumbTags.JpegIFOffset;
var tLength = thumbTags.JpegIFByteCount;
thumbTags['blob'] = new Blob([new Uint8Array(dataView.buffer, tOffset, tLength)], {
type: 'image/jpeg'
});
}
break;
case 1:
console.log("Thumbnail image format is TIFF, which is not implemented.");
break;
default:
console.log("Unknown thumbnail image format '%s'", thumbTags['Compression']);
}
}
else if (thumbTags['PhotometricInterpretation'] == 2) {
console.log("Thumbnail image format is RGB, which is not implemented.");
}
return thumbTags;
}
function getStringFromDB(buffer, start, length) {

@@ -744,7 +838,103 @@ var outstr = "";

// extract thumbnail
tags['thumbnail'] = readThumbnailImage(file, tiffOffset, firstIFDOffset, bigEnd);
return tags;
}
function findXMPinJPEG(file) {
if (!('DOMParser' in self)) {
// console.warn('XML parsing not supported without DOMParser');
return;
}
var dataView = new DataView(file);
if (debug) console.log("Got file of length " + file.byteLength);
if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {
if (debug) console.log("Not a valid JPEG");
return false; // not a valid jpeg
}
var offset = 2,
length = file.byteLength,
dom = new DOMParser();
while (offset < (length-4)) {
if (getStringFromDB(dataView, offset, 4) == "http") {
var startOffset = offset - 1;
var sectionLength = dataView.getUint16(offset - 2) - 1;
var xmpString = getStringFromDB(dataView, startOffset, sectionLength)
var xmpEndIndex = xmpString.indexOf('xmpmeta>') + 8;
xmpString = xmpString.substring( xmpString.indexOf( '<x:xmpmeta' ), xmpEndIndex );
var indexOfXmp = xmpString.indexOf('x:xmpmeta') + 10
//Many custom written programs embed xmp/xml without any namespace. Following are some of them.
//Without these namespaces, XML is thought to be invalid by parsers
xmpString = xmpString.slice(0, indexOfXmp)
+ 'xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" '
+ 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '
+ 'xmlns:tiff="http://ns.adobe.com/tiff/1.0/" '
+ 'xmlns:plus="http://schemas.android.com/apk/lib/com.google.android.gms.plus" '
+ 'xmlns:ext="http://www.gettyimages.com/xsltExtension/1.0" '
+ 'xmlns:exif="http://ns.adobe.com/exif/1.0/" '
+ 'xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" '
+ 'xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" '
+ 'xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/" '
+ 'xmlns:xapGImg="http://ns.adobe.com/xap/1.0/g/img/" '
+ 'xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/" '
+ xmpString.slice(indexOfXmp)
var domDocument = dom.parseFromString( xmpString, 'text/xml' );
return xml2Object(domDocument);
} else{
offset++;
}
}
}
function xml2Object(xml) {
try {
var obj = {};
if (xml.children.length > 0) {
for (var i = 0; i < xml.children.length; i++) {
var item = xml.children.item(i);
var attributes = item.attributes;
for(var idx in attributes) {
var itemAtt = attributes[idx];
var dataKey = itemAtt.nodeName;
var dataValue = itemAtt.nodeValue;
if(dataKey !== undefined) {
obj[dataKey] = dataValue;
}
}
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
EXIF.getData = function(img, callback) {
if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false;
if ((self.Image && img instanceof self.Image)
|| (self.HTMLImageElement && img instanceof self.HTMLImageElement)
&& !img.complete)
return false;

@@ -765,2 +955,7 @@ if (!imageHasData(img)) {

}
EXIF.getIptcTag = function(img, tag) {
if (!imageHasData(img)) return;
return img.iptcdata[tag];
}

@@ -779,2 +974,15 @@ EXIF.getAllTags = function(img) {

}
EXIF.getAllIptcTags = function(img) {
if (!imageHasData(img)) return {};
var a,
data = img.iptcdata,
tags = {};
for (a in data) {
if (data.hasOwnProperty(a)) {
tags[a] = data[a];
}
}
return tags;
}

@@ -781,0 +989,0 @@ EXIF.pretty = function(img) {

{
"name": "exif-js",
"version": "2.1.1",
"version": "2.2.0",
"description": "JavaScript library for reading EXIF image metadata",

@@ -5,0 +5,0 @@ "main": "exif.js",

@@ -1,3 +0,86 @@

#Exif.js
# Exif.js
A JavaScript library for reading EXIF meta data from JPEG image files.
A JavaScript library for reading [EXIF meta data](https://en.wikipedia.org/wiki/Exchangeable_image_file_format) from image files.
You can use it on images in the browser, either from an image or a file input element. Both EXIF and IPTC metadata are retrieved.
This package can also be used in AMD or CommonJS environments.
**Note**: The EXIF standard applies only to `.jpg` and `.tiff` images. EXIF logic in this package is based on the EXIF standard v2.2 ([JEITA CP-3451, included in this repo](/spec/Exif2-2.pdf)).
## Install
Install `exif-js` through [NPM](https://www.npmjs.com/#getting-started):
npm install exif-js --save
Or [Bower](http://bower.io/):
bower install exif-js --save
Then add a `script` tag in your an HTML in the [best position](http://stackoverflow.com/questions/436411/where-is-the-best-place-to-put-script-tags-in-html-markup) referencing your local file.
<script src="vendors/exif-js/exif-js"></script>
**Note**: This repo has no `.min.js`. Do your own [minification](https://en.wikipedia.org/wiki/Minification_(programming)) if you want that.
If you prefer another package manager you will probably manage :D. Or you can clone this GIT repository or download it's ZIP file and extract `exif.js` to your project.
## Usage
The package adds a global `EXIF` variable (or AMD or CommonJS equivalent).
Start with calling the `EXIF.getData` function. You pass it an image as a parameter:
- either an image from a `<img src="image.jpg">`
- OR a user selected image in a `<file type="input">` element on your page.
As a second parameter you specify a callback function. In the callback function you should use `this` to access the image with the aforementioned metadata you can then use as you want.
That image now has an extra `exifdata` property which is a Javascript object with the EXIF metadata. You can access it's properties to get data like the *image caption*, the *date a photo was taken* or it's *orientation*.
You can get all tages with `EXIF.getTag`. Or get a single tag with `EXIF.getTag`, where you specify the tag as the second parameter.
The tag names to use are listed in `EXIF.Tags` in `exif.js`.
**Important**: Note that you have to wait for the image to be completely loaded, before calling `getData` or any other function. It will silently fail otherwise.
You can implement this wait, by running your exif-extracting logic on the `window.onLoad` function. Or on an image's own `onLoad` function.
For jQuery users please note that you can NOT (reliably) use jQuery's `ready` event for this. Because it fires before images are loaded.
You could use $(window).load() instead of $(document.ready() (please note that `exif-js has NO dependency on jQuery or any other external library).
**JavaScript**:
```javascript
window.onload=getExif;
function getExif() {
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var make = EXIF.getTag(this, "Make");
var model = EXIF.getTag(this, "Model");
var makeAndModel = document.getElementById("makeAndModel");
makeAndModel.innerHTML = `${make} ${model}`;
});
var img2 = document.getElementById("img2");
EXIF.getData(img2, function() {
var allMetaData = EXIF.getAllTags(this);
var allMetaDataSpan = document.getElementById("allMetaDataSpan");
allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, "\t");
});
}
```
**HTML**:
```html
<img src="image1.jpg" id="img1" />
<pre>Make and model: <span id="makeAndModel"></span></div>
<br/>
<img src="image2.jpg" id="img2" />
<pre id="allMetaDataSpan"></pre>
<br/>
```
Note there are also alternate tags, such the `EXIF.TiffTags`. See the source code for the full definition and use.
You can also get back a string with all the EXIF information in the image pretty printed by using `EXIF.pretty`.
Check the included [example/index.html](/exif-js/exif-js/blob/master/example/index.html).
Please refer to the [source code](exif.js) for more advanced usages such as getting image data from a [File/Blob](https://developer.mozilla.org/en/docs/Web/API/Blob) object (`EXIF.readFromBinaryFile`).
## Contributions
This is an [open source project](LICENSE.md). Please contribute by forking this repo and issueing a pull request. The project has had notable contributions already, like reading ITPC data.
You can also contribute by [filing bugs or new features please issue](/exif-js/issues).
Or improve the documentation. Please update this README when you do a pull request of proposed changes in base functionality.
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