Comparing version 1.0.7 to 2.0.0
433
exif.js
@@ -1,84 +0,99 @@ | ||
BinaryAjax = require('./binaryajax'); | ||
(function() { | ||
var EXIF = (function() { | ||
var debug = false; | ||
var ExifTags = { | ||
var root = this; | ||
var EXIF = function(obj) { | ||
if (obj instanceof EXIF) return obj; | ||
if (!(this instanceof EXIF)) return new EXIF(obj); | ||
this.EXIFwrapped = obj; | ||
}; | ||
if (typeof exports !== 'undefined') { | ||
if (typeof module !== 'undefined' && module.exports) { | ||
exports = module.exports = EXIF; | ||
} | ||
exports.EXIF = EXIF; | ||
} else { | ||
root.EXIF = EXIF; | ||
} | ||
var ExifTags = EXIF.Tags = { | ||
// version tags | ||
0x9000 : "ExifVersion", // EXIF version | ||
0xA000 : "FlashpixVersion", // Flashpix format version | ||
0x9000 : "ExifVersion", // EXIF version | ||
0xA000 : "FlashpixVersion", // Flashpix format version | ||
// colorspace tags | ||
0xA001 : "ColorSpace", // Color space information tag | ||
0xA001 : "ColorSpace", // Color space information tag | ||
// image configuration | ||
0xA002 : "PixelXDimension", // Valid width of meaningful image | ||
0xA003 : "PixelYDimension", // Valid height of meaningful image | ||
0x9101 : "ComponentsConfiguration", // Information about channels | ||
0x9102 : "CompressedBitsPerPixel", // Compressed bits per pixel | ||
0xA002 : "PixelXDimension", // Valid width of meaningful image | ||
0xA003 : "PixelYDimension", // Valid height of meaningful image | ||
0x9101 : "ComponentsConfiguration", // Information about channels | ||
0x9102 : "CompressedBitsPerPixel", // Compressed bits per pixel | ||
// user information | ||
0x927C : "MakerNote", // Any desired information written by the manufacturer | ||
0x9286 : "UserComment", // Comments by user | ||
0x927C : "MakerNote", // Any desired information written by the manufacturer | ||
0x9286 : "UserComment", // Comments by user | ||
// related file | ||
0xA004 : "RelatedSoundFile", // Name of related sound file | ||
0xA004 : "RelatedSoundFile", // Name of related sound file | ||
// date and time | ||
0x9003 : "DateTimeOriginal", // Date and time when the original image was generated | ||
0x9004 : "DateTimeDigitized", // Date and time when the image was stored digitally | ||
0x9290 : "SubsecTime", // Fractions of seconds for DateTime | ||
0x9291 : "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal | ||
0x9292 : "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized | ||
0x9003 : "DateTimeOriginal", // Date and time when the original image was generated | ||
0x9004 : "DateTimeDigitized", // Date and time when the image was stored digitally | ||
0x9290 : "SubsecTime", // Fractions of seconds for DateTime | ||
0x9291 : "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal | ||
0x9292 : "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized | ||
// picture-taking conditions | ||
0x829A : "ExposureTime", // Exposure time (in seconds) | ||
0x829D : "FNumber", // F number | ||
0x8822 : "ExposureProgram", // Exposure program | ||
0x8824 : "SpectralSensitivity", // Spectral sensitivity | ||
0x8827 : "ISOSpeedRatings", // ISO speed rating | ||
0x8828 : "OECF", // Optoelectric conversion factor | ||
0x9201 : "ShutterSpeedValue", // Shutter speed | ||
0x9202 : "ApertureValue", // Lens aperture | ||
0x9203 : "BrightnessValue", // Value of brightness | ||
0x9204 : "ExposureBias", // Exposure bias | ||
0x9205 : "MaxApertureValue", // Smallest F number of lens | ||
0x9206 : "SubjectDistance", // Distance to subject in meters | ||
0x9207 : "MeteringMode", // Metering mode | ||
0x9208 : "LightSource", // Kind of light source | ||
0x9209 : "Flash", // Flash status | ||
0x9214 : "SubjectArea", // Location and area of main subject | ||
0x920A : "FocalLength", // Focal length of the lens in mm | ||
0xA20B : "FlashEnergy", // Strobe energy in BCPS | ||
0xA20C : "SpatialFrequencyResponse", // | ||
0xA20E : "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit | ||
0xA20F : "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit | ||
0xA210 : "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution | ||
0xA214 : "SubjectLocation", // Location of subject in image | ||
0xA215 : "ExposureIndex", // Exposure index selected on camera | ||
0xA217 : "SensingMethod", // Image sensor type | ||
0xA300 : "FileSource", // Image source (3 == DSC) | ||
0xA301 : "SceneType", // Scene type (1 == directly photographed) | ||
0xA302 : "CFAPattern", // Color filter array geometric pattern | ||
0xA401 : "CustomRendered", // Special processing | ||
0xA402 : "ExposureMode", // Exposure mode | ||
0xA403 : "WhiteBalance", // 1 = auto white balance, 2 = manual | ||
0xA404 : "DigitalZoomRation", // Digital zoom ratio | ||
0xA405 : "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm) | ||
0xA406 : "SceneCaptureType", // Type of scene | ||
0xA407 : "GainControl", // Degree of overall image gain adjustment | ||
0xA408 : "Contrast", // Direction of contrast processing applied by camera | ||
0xA409 : "Saturation", // Direction of saturation processing applied by camera | ||
0xA40A : "Sharpness", // Direction of sharpness processing applied by camera | ||
0xA40B : "DeviceSettingDescription", // | ||
0xA40C : "SubjectDistanceRange", // Distance to subject | ||
0x829A : "ExposureTime", // Exposure time (in seconds) | ||
0x829D : "FNumber", // F number | ||
0x8822 : "ExposureProgram", // Exposure program | ||
0x8824 : "SpectralSensitivity", // Spectral sensitivity | ||
0x8827 : "ISOSpeedRatings", // ISO speed rating | ||
0x8828 : "OECF", // Optoelectric conversion factor | ||
0x9201 : "ShutterSpeedValue", // Shutter speed | ||
0x9202 : "ApertureValue", // Lens aperture | ||
0x9203 : "BrightnessValue", // Value of brightness | ||
0x9204 : "ExposureBias", // Exposure bias | ||
0x9205 : "MaxApertureValue", // Smallest F number of lens | ||
0x9206 : "SubjectDistance", // Distance to subject in meters | ||
0x9207 : "MeteringMode", // Metering mode | ||
0x9208 : "LightSource", // Kind of light source | ||
0x9209 : "Flash", // Flash status | ||
0x9214 : "SubjectArea", // Location and area of main subject | ||
0x920A : "FocalLength", // Focal length of the lens in mm | ||
0xA20B : "FlashEnergy", // Strobe energy in BCPS | ||
0xA20C : "SpatialFrequencyResponse", // | ||
0xA20E : "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit | ||
0xA20F : "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit | ||
0xA210 : "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution | ||
0xA214 : "SubjectLocation", // Location of subject in image | ||
0xA215 : "ExposureIndex", // Exposure index selected on camera | ||
0xA217 : "SensingMethod", // Image sensor type | ||
0xA300 : "FileSource", // Image source (3 == DSC) | ||
0xA301 : "SceneType", // Scene type (1 == directly photographed) | ||
0xA302 : "CFAPattern", // Color filter array geometric pattern | ||
0xA401 : "CustomRendered", // Special processing | ||
0xA402 : "ExposureMode", // Exposure mode | ||
0xA403 : "WhiteBalance", // 1 = auto white balance, 2 = manual | ||
0xA404 : "DigitalZoomRation", // Digital zoom ratio | ||
0xA405 : "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm) | ||
0xA406 : "SceneCaptureType", // Type of scene | ||
0xA407 : "GainControl", // Degree of overall image gain adjustment | ||
0xA408 : "Contrast", // Direction of contrast processing applied by camera | ||
0xA409 : "Saturation", // Direction of saturation processing applied by camera | ||
0xA40A : "Sharpness", // Direction of sharpness processing applied by camera | ||
0xA40B : "DeviceSettingDescription", // | ||
0xA40C : "SubjectDistanceRange", // Distance to subject | ||
// other tags | ||
0xA005 : "InteroperabilityIFDPointer", | ||
0xA420 : "ImageUniqueID" // Identifier assigned uniquely to each image | ||
0xA420 : "ImageUniqueID" // Identifier assigned uniquely to each image | ||
}; | ||
var TiffTags = { | ||
var TiffTags = EXIF.TiffTags = { | ||
0x0100 : "ImageWidth", | ||
@@ -119,3 +134,3 @@ 0x0101 : "ImageHeight", | ||
var GPSTags = { | ||
var GPSTags = EXIF.GPSTags = { | ||
0x0000 : "GPSVersionID", | ||
@@ -154,3 +169,3 @@ 0x0001 : "GPSLatitudeRef", | ||
var StringValues = { | ||
var StringValues = EXIF.StringValues = { | ||
ExposureProgram : { | ||
@@ -294,6 +309,6 @@ 0 : "Not defined", | ||
function addEvent(element, event, handler) { | ||
if (element.addEventListener) { | ||
element.addEventListener(event, handler, false); | ||
} else if (element.attachEvent) { | ||
element.attachEvent("on" + event, handler); | ||
if (element.addEventListener) { | ||
element.addEventListener(event, handler, false); | ||
} else if (element.attachEvent) { | ||
element.attachEvent("on" + event, handler); | ||
} | ||
@@ -306,8 +321,36 @@ } | ||
function base64ToArrayBuffer(base64, contentType) { | ||
contentType = contentType || base64.match(/^data\:([^\;]+)\;base64,/mi)[1] || ''; // e.g. 'data:image/jpeg;base64,...' => 'image/jpeg' | ||
base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, ''); | ||
var binary = atob(base64); | ||
var len = binary.length; | ||
var buffer = new ArrayBuffer(len); | ||
var view = new Uint8Array(buffer); | ||
for (var i = 0; i < len; i++) { | ||
view[i] = binary.charCodeAt(i); | ||
} | ||
return buffer; | ||
} | ||
function objectURLToBlob(url, callback) { | ||
var http = new XMLHttpRequest(); | ||
http.open("GET", url, true); | ||
http.responseType = "blob"; | ||
http.onload = function(e) { | ||
if (this.status == 200 || this.status === 0) { | ||
callback(this.response); | ||
} | ||
}; | ||
http.send(); | ||
} | ||
function getImageData(img, callback) { | ||
function handleBinaryFile(binFile) { | ||
var data = findEXIFinJPEG(binFile); | ||
var iptcdata = findIPTCinJPEG(binFile); | ||
img.exifdata = data || {}; | ||
img.iptcdata = iptcdata || {}; | ||
if (callback) { | ||
callback.call(img) | ||
callback.call(img); | ||
} | ||
@@ -317,10 +360,32 @@ } | ||
if (img instanceof Image || img instanceof HTMLImageElement) { | ||
BinaryAjax(img.src, function(http) { | ||
handleBinaryFile(http.binaryResponse); | ||
}); | ||
} else if (window.FileReader && img instanceof window.File) { | ||
if (/^data\:/i.test(img.src)) { // Data URI | ||
var arrayBuffer = base64ToArrayBuffer(img.src); | ||
handleBinaryFile(arrayBuffer); | ||
} else if (/^blob\:/i.test(img.src)) { // Object URL | ||
var fileReader = new FileReader(); | ||
fileReader.onload = function(e) { | ||
handleBinaryFile(e.target.result); | ||
}; | ||
objectURLToBlob(img.src, function (blob) { | ||
fileReader.readAsArrayBuffer(blob); | ||
}); | ||
} else { | ||
var http = new XMLHttpRequest(); | ||
http.onload = function() { | ||
if (http.status == "200") { | ||
handleBinaryFile(http.response); | ||
} else { | ||
throw "Could not load image"; | ||
} | ||
http = null; | ||
}; | ||
http.open("GET", img.src, true); | ||
http.responseType = "arraybuffer"; | ||
http.send(null); | ||
} | ||
} else if (window.FileReader && (img instanceof window.Blob || img instanceof window.File)) { | ||
var fileReader = new FileReader(); | ||
fileReader.onload = function(e) { | ||
if (debug) console.log("Got file of length " + e.target.result.byteLength); | ||
if (debug) console.log("Got file of length " + e.target.result.byteLength); | ||
handleBinaryFile(e.target.result); | ||
@@ -333,6 +398,6 @@ }; | ||
function findEXIFinJPEG(file) { | ||
var dataView = new DataView(file); | ||
if (debug) console.log("Got file of length " + file.byteLength); | ||
function findEXIFinJPEG(file) { | ||
var dataView = new DataView(file); | ||
if (debug) console.log("Got file of length " + file.byteLength); | ||
if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { | ||
@@ -349,3 +414,3 @@ if (debug) console.log("Not a valid JPEG"); | ||
if (dataView.getUint8(offset) != 0xFF) { | ||
if (debug) console.log("Not a valid marker at offset " + offset + ", found: " + file.getByteAt(offset)); | ||
if (debug) console.log("Not a valid marker at offset " + offset + ", found: " + dataView.getUint8(offset)); | ||
return false; // not a valid marker, something is wrong | ||
@@ -355,5 +420,5 @@ } | ||
marker = dataView.getUint8(offset + 1); | ||
if (debug) console.log(marker); | ||
if (debug) console.log(marker); | ||
// we could implement handling for other markers here, | ||
// we could implement handling for other markers here, | ||
// but we're only looking for 0xFFE1 for EXIF data | ||
@@ -363,5 +428,5 @@ | ||
if (debug) console.log("Found 0xFFE1 marker"); | ||
return readEXIFData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2); | ||
// offset += 2 + file.getShortAt(offset+2, true); | ||
@@ -377,9 +442,109 @@ | ||
function findIPTCinJPEG(file) { | ||
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; | ||
var isFieldSegmentStart = function(dataView, offset){ | ||
return ( | ||
dataView.getUint8(offset) === 0x38 && | ||
dataView.getUint8(offset+1) === 0x42 && | ||
dataView.getUint8(offset+2) === 0x49 && | ||
dataView.getUint8(offset+3) === 0x4D && | ||
dataView.getUint8(offset+4) === 0x04 && | ||
dataView.getUint8(offset+5) === 0x04 | ||
); | ||
}; | ||
while (offset < length) { | ||
if ( isFieldSegmentStart(dataView, offset )){ | ||
// Get the length of the name header (which is padded to an even number of bytes) | ||
var nameHeaderLength = dataView.getUint8(offset+7); | ||
if(nameHeaderLength % 2 !== 0) nameHeaderLength += 1; | ||
// Check for pre photoshop 6 format | ||
if(nameHeaderLength === 0) { | ||
// Always 4 | ||
nameHeaderLength = 4; | ||
} | ||
var startOffset = offset + 8 + nameHeaderLength; | ||
var sectionLength = dataView.getUint16(offset + 6 + nameHeaderLength); | ||
return readIPTCData(file, startOffset, sectionLength); | ||
break; | ||
} | ||
// Not the marker, continue searching | ||
offset++; | ||
} | ||
} | ||
var IptcFieldMap = { | ||
0x78 : 'caption', | ||
0x6E : 'credit', | ||
0x19 : 'keywords', | ||
0x37 : 'dateCreated', | ||
0x50 : 'byline', | ||
0x55 : 'bylineTitle', | ||
0x7A : 'captionWriter', | ||
0x69 : 'headline', | ||
0x74 : 'copyright', | ||
0x0F : 'category' | ||
}; | ||
function readIPTCData(file, startOffset, sectionLength){ | ||
var dataView = new DataView(file); | ||
var data = {}; | ||
var fieldValue, fieldName, dataSize, segmentType, segmentSize; | ||
var segmentStartPos = startOffset; | ||
while(segmentStartPos < startOffset+sectionLength) { | ||
if(dataView.getUint8(segmentStartPos) === 0x1C && dataView.getUint8(segmentStartPos+1) === 0x02){ | ||
segmentType = dataView.getUint8(segmentStartPos+2); | ||
if(segmentType in IptcFieldMap) { | ||
dataSize = dataView.getInt16(segmentStartPos+3); | ||
segmentSize = dataSize + 5; | ||
fieldName = IptcFieldMap[segmentType]; | ||
fieldValue = getStringFromDB(dataView, segmentStartPos+5, dataSize); | ||
// Check if we already stored a value with this name | ||
if(data.hasOwnProperty(fieldName)) { | ||
// Value already stored with this name, create multivalue field | ||
if(data[fieldName] instanceof Array) { | ||
data[fieldName].push(fieldValue); | ||
} | ||
else { | ||
data[fieldName] = [data[fieldName], fieldValue]; | ||
} | ||
} | ||
else { | ||
data[fieldName] = fieldValue; | ||
} | ||
} | ||
} | ||
segmentStartPos++; | ||
} | ||
return data; | ||
} | ||
function readTags(file, tiffStart, dirStart, strings, bigEnd) { | ||
var entries = file.getUint16(dirStart, !bigEnd), | ||
tags = {}, | ||
tags = {}, | ||
entryOffset, tag, | ||
i; | ||
for (i=0;i<entries;i++) { | ||
@@ -438,3 +603,3 @@ entryOffset = dirStart + i*12 + 2; | ||
vals = []; | ||
for (var n=0;n<numValues;n++) { | ||
for (n=0;n<numValues;n++) { | ||
vals[n] = file.getUint32(valueOffset + 4*n, !bigEnd); | ||
@@ -445,3 +610,3 @@ } | ||
case 5: // rational = two long values, first is numerator, second is denominator | ||
case 5: // rational = two long values, first is numerator, second is denominator | ||
if (numValues == 1) { | ||
@@ -490,10 +655,10 @@ numerator = file.getUint32(valueOffset, !bigEnd); | ||
function getStringFromDB(buffer, start, length) { | ||
var outstr = ""; | ||
for (n = start; n < start+length; n++) { | ||
outstr += String.fromCharCode(buffer.getUint8(n)); | ||
} | ||
return outstr; | ||
} | ||
function getStringFromDB(buffer, start, length) { | ||
var outstr = ""; | ||
for (n = start; n < start+length; n++) { | ||
outstr += String.fromCharCode(buffer.getUint8(n)); | ||
} | ||
return outstr; | ||
} | ||
function readEXIFData(file, start) { | ||
@@ -520,3 +685,3 @@ if (getStringFromDB(file, start, 4) != "Exif") { | ||
if (file.getUint16(tiffOffset+2, !bigEnd) != 0x002A) { | ||
if (file.getUint16(tiffOffset+2, !bigEnd) != 0x002A) { | ||
if (debug) console.log("Not valid TIFF data! (no 0x002A)"); | ||
@@ -526,8 +691,10 @@ return false; | ||
if (file.getUint32(tiffOffset+4, !bigEnd) != 0x00000008) { | ||
if (debug) console.log("Not valid TIFF data! (First offset not 8)", file.getUint16(tiffOffset+4, !bigEnd)); | ||
var firstIFDOffset = file.getUint32(tiffOffset+4, !bigEnd); | ||
if (firstIFDOffset < 0x00000008) { | ||
if (debug) console.log("Not valid TIFF data! (First offset less than 8)", file.getUint32(tiffOffset+4, !bigEnd)); | ||
return false; | ||
} | ||
tags = readTags(file, tiffOffset, tiffOffset+8, TiffTags, bigEnd); | ||
tags = readTags(file, tiffOffset, tiffOffset + firstIFDOffset, TiffTags, bigEnd); | ||
@@ -546,7 +713,7 @@ if (tags.ExifIFDPointer) { | ||
case "CustomRendered" : | ||
case "WhiteBalance" : | ||
case "GainControl" : | ||
case "WhiteBalance" : | ||
case "GainControl" : | ||
case "Contrast" : | ||
case "Saturation" : | ||
case "Sharpness" : | ||
case "Sharpness" : | ||
case "SubjectDistanceRange" : | ||
@@ -556,3 +723,3 @@ case "FileSource" : | ||
break; | ||
case "ExifVersion" : | ||
@@ -562,9 +729,9 @@ case "FlashpixVersion" : | ||
break; | ||
case "ComponentsConfiguration" : | ||
exifData[tag] = | ||
StringValues.Components[exifData[tag][0]] | ||
+ StringValues.Components[exifData[tag][1]] | ||
+ StringValues.Components[exifData[tag][2]] | ||
+ StringValues.Components[exifData[tag][3]]; | ||
case "ComponentsConfiguration" : | ||
exifData[tag] = | ||
StringValues.Components[exifData[tag][0]] + | ||
StringValues.Components[exifData[tag][1]] + | ||
StringValues.Components[exifData[tag][2]] + | ||
StringValues.Components[exifData[tag][3]]; | ||
break; | ||
@@ -580,7 +747,7 @@ } | ||
switch (tag) { | ||
case "GPSVersionID" : | ||
gpsData[tag] = gpsData[tag][0] | ||
+ "." + gpsData[tag][1] | ||
+ "." + gpsData[tag][2] | ||
+ "." + gpsData[tag][3]; | ||
case "GPSVersionID" : | ||
gpsData[tag] = gpsData[tag][0] + | ||
"." + gpsData[tag][1] + | ||
"." + gpsData[tag][2] + | ||
"." + gpsData[tag][3]; | ||
break; | ||
@@ -595,5 +762,5 @@ } | ||
EXIF.getData = function(img, callback) { | ||
if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false; | ||
function getData(img, callback) { | ||
if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false; | ||
if (!imageHasData(img)) { | ||
@@ -609,3 +776,3 @@ getImageData(img, callback); | ||
function getTag(img, tag) { | ||
EXIF.getTag = function(img, tag) { | ||
if (!imageHasData(img)) return; | ||
@@ -615,5 +782,5 @@ return img.exifdata[tag]; | ||
function getAllTags(img) { | ||
EXIF.getAllTags = function(img) { | ||
if (!imageHasData(img)) return {}; | ||
var a, | ||
var a, | ||
data = img.exifdata, | ||
@@ -629,3 +796,3 @@ tags = {}; | ||
function pretty(img) { | ||
EXIF.pretty = function(img) { | ||
if (!imageHasData(img)) return ""; | ||
@@ -651,22 +818,12 @@ var a, | ||
function readFromBinaryFile(file) { | ||
EXIF.readFromBinaryFile = function(file) { | ||
return findEXIFinJPEG(file); | ||
} | ||
return { | ||
readFromBinaryFile : readFromBinaryFile, | ||
pretty : pretty, | ||
getTag : getTag, | ||
getAllTags : getAllTags, | ||
getData : getData, | ||
Tags : ExifTags, | ||
TiffTags : TiffTags, | ||
GPSTags : GPSTags, | ||
StringValues : StringValues | ||
}; | ||
if (typeof define === 'function' && define.amd) { | ||
define('exif-js', [], function() { | ||
return EXIF; | ||
}); | ||
} | ||
}.call(this)); | ||
})(); | ||
module.exports = EXIF; |
{ | ||
"name": "exif-js", | ||
"version": "1.0.7", | ||
"description": "A JavaScript library for reading EXIF meta data from JPEG image files.", | ||
"version": "2.0.0", | ||
"description": "JavaScript library for reading EXIF image metadata", | ||
"main": "exif.js", | ||
@@ -9,25 +9,24 @@ "directories": { | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/webthusiast/exif-js" | ||
"url": "https://github.com/jseidelin/exif-js" | ||
}, | ||
"homepage": "https://github.com/webthusiast/exif-js", | ||
"keywords": [ | ||
"exif" | ||
], | ||
"author": "Jacob Seidelin", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/jseidelin/exif-js/issues" | ||
}, | ||
"keywords": [ | ||
"exif", | ||
"binaryajax", | ||
"nihilogic", | ||
"browserify", | ||
"commonjs" | ||
], | ||
"author": "Jacob Seidelin <jseidelin@nihilogic.dk> (http://blog.nihilogic.dk/)", | ||
"maintainers": [ | ||
"Roald de Vries <roald@webthusiast.nl> (http://webthusiast.nl/)" | ||
], | ||
"license": "MIT" | ||
"homepage": "https://github.com/jseidelin/exif-js", | ||
"ignore": [ | ||
"**/.*", | ||
"node_modules", | ||
"bower_components", | ||
"test", | ||
"tests", | ||
"spec", | ||
"example" | ||
] | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
973621
0
10
739