Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Support for images with `src` of type "Data URI" (Base64) or "Object URL" (Blob). #6

Closed
wants to merge 1 commit into from

2 participants

@grimen

Support for images with src of type "Data URI" (Base64) or "Object URL" (Blob). No need for any remote requests; ideal for targeting cross-domain and/or performance issues.

@grimen grimen Support for images with `src` of type "Data URI" (Base64) or "Object …
…URL" (Blob). No need for any remote requests; ideal for targeting cross-domain and/or performance issues.
bfd6a07
@jseidelin
Owner

Finally got around to look at this. Merged your additions manually. Thanks!

@jseidelin jseidelin closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 29, 2013
  1. @grimen

    Support for images with `src` of type "Data URI" (Base64) or "Object …

    grimen authored
    …URL" (Blob). No need for any remote requests; ideal for targeting cross-domain and/or performance issues.
This page is out of date. Refresh to see the latest.
Showing with 85 additions and 30 deletions.
  1. +85 −30 exif.js
View
115 exif.js
@@ -57,7 +57,7 @@ var EXIF = (function() {
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", //
+ 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
@@ -77,7 +77,7 @@ var EXIF = (function() {
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", //
+ 0xA40B : "DeviceSettingDescription", //
0xA40C : "SubjectDistanceRange", // Distance to subject
// other tags
@@ -294,10 +294,10 @@ var EXIF = (function() {
};
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);
}
}
@@ -305,6 +305,37 @@ var EXIF = (function() {
return !!(img.exifdata);
}
+ function base64ToBlob(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);
+ }
+ var blob = new Blob([view], {type: contentType});
+
+ return blob;
+ }
+
+ function objectURLToBlob (object_url, callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', object_url, true);
+ xhr.responseType = 'blob';
+ xhr.onload = function(e) {
+ var blob;
+ if (this.status === 200) {
+ blob = this.response;
+ }
+ callback(blob);
+ };
+ xhr.send();
+ }
+
function getImageData(img, callback) {
function handleBinaryFile(binFile) {
var data = findEXIFinJPEG(binFile);
@@ -315,10 +346,34 @@ var EXIF = (function() {
}
if (img instanceof Image) {
- 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 fileReader = new FileReader();
+
+ fileReader.onload = function(e) {
+ handleBinaryFile(new BinaryFile(e.target.result));
+ };
+
+ var blob = base64ToBlob(img.src);
+
+ fileReader.readAsBinaryString(blob);
+
+ } else if (/^blob\:/i.test(img.src)) { // Object URL
+ var fileReader = new FileReader();
+
+ fileReader.onload = function(e) {
+ handleBinaryFile(new BinaryFile(e.target.result));
+ };
+
+ objectURLToBlob(img.src, function (blob) {
+ fileReader.readAsBinaryString(blob);
+ });
+
+ } else { // HTTP URL
+ BinaryAjax(img.src, function(http) {
+ handleBinaryFile(http.binaryResponse);
+ });
+ }
+ } else if (img instanceof Blob || (window.FileReader && img instanceof window.File)) {
var fileReader = new FileReader();
fileReader.onload = function(e) {
@@ -346,20 +401,20 @@ var EXIF = (function() {
marker = file.getByteAt(offset+1);
- // 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
if (marker == 22400) {
if (debug) console.log("Found 0xFFE1 marker");
-
+
return readEXIFData(file, offset + 4, file.getShortAt(offset+2, true)-2);
-
+
// offset += 2 + file.getShortAt(offset+2, true);
} else if (marker == 225) {
// 0xE1 = Application-specific 1 (for EXIF)
if (debug) console.log("Found 0xFFE1 marker");
-
+
return readEXIFData(file, offset + 4, file.getShortAt(offset+2, true)-2);
} else {
@@ -373,10 +428,10 @@ var EXIF = (function() {
function readTags(file, tiffStart, dirStart, strings, bigEnd) {
var entries = file.getShortAt(dirStart, bigEnd),
- tags = {},
+ tags = {},
entryOffset, tag,
i;
-
+
for (i=0;i<entries;i++) {
entryOffset = dirStart + i*12 + 2;
tag = strings[file.getShortAt(entryOffset, bigEnd)];
@@ -526,23 +581,23 @@ var EXIF = (function() {
case "SceneCaptureType" :
case "SceneType" :
case "CustomRendered" :
- case "WhiteBalance" :
- case "GainControl" :
+ case "WhiteBalance" :
+ case "GainControl" :
case "Contrast" :
case "Saturation" :
- case "Sharpness" :
+ case "Sharpness" :
case "SubjectDistanceRange" :
case "FileSource" :
exifData[tag] = StringValues[tag][exifData[tag]];
break;
-
+
case "ExifVersion" :
case "FlashpixVersion" :
exifData[tag] = String.fromCharCode(exifData[tag][0], exifData[tag][1], exifData[tag][2], exifData[tag][3]);
break;
-
- case "ComponentsConfiguration" :
- exifData[tag] =
+
+ case "ComponentsConfiguration" :
+ exifData[tag] =
StringValues.Components[exifData[tag][0]]
+ StringValues.Components[exifData[tag][1]]
+ StringValues.Components[exifData[tag][2]]
@@ -557,10 +612,10 @@ var EXIF = (function() {
gpsData = readTags(file, tiffOffset, tiffOffset + tags.GPSInfoIFDPointer, GPSTags, bigEnd);
for (tag in gpsData) {
switch (tag) {
- case "GPSVersionID" :
- gpsData[tag] = gpsData[tag][0]
- + "." + gpsData[tag][1]
- + "." + gpsData[tag][2]
+ case "GPSVersionID" :
+ gpsData[tag] = gpsData[tag][0]
+ + "." + gpsData[tag][1]
+ + "." + gpsData[tag][2]
+ "." + gpsData[tag][3];
break;
}
@@ -591,7 +646,7 @@ var EXIF = (function() {
function getAllTags(img) {
if (!imageHasData(img)) return {};
- var a,
+ var a,
data = img.exifdata,
tags = {};
for (a in data) {
@@ -627,14 +682,14 @@ var EXIF = (function() {
return findEXIFinJPEG(file);
}
-
+
return {
readFromBinaryFile : readFromBinaryFile,
pretty : pretty,
getTag : getTag,
getAllTags : getAllTags,
getData : getData,
-
+
Tags : ExifTags,
TiffTags : TiffTags,
GPSTags : GPSTags,
Something went wrong with that request. Please try again.