mirror of
				https://github.com/flynx/PortableMag.git
				synced 2025-11-03 21:40:17 +00:00 
			
		
		
		
	
		
			
	
	
		
			895 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			895 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Javascript EXIF Reader - jQuery plugin 0.1.3
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/
							 | 
						||
| 
								 | 
							
								 * Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt]
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var BinaryFile = function(strData, iDataOffset, iDataLength) {
							 | 
						||
| 
								 | 
							
									var data = strData;
							 | 
						||
| 
								 | 
							
									var dataOffset = iDataOffset || 0;
							 | 
						||
| 
								 | 
							
									var dataLength = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this.getRawData = function() {
							 | 
						||
| 
								 | 
							
										return data;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (typeof strData == "string") {
							 | 
						||
| 
								 | 
							
										dataLength = iDataLength || data.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.getByteAt = function(iOffset) {
							 | 
						||
| 
								 | 
							
											return data.charCodeAt(iOffset + dataOffset) & 0xFF;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} else if (typeof strData == "unknown") {
							 | 
						||
| 
								 | 
							
										dataLength = iDataLength || IEBinary_getLength(data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										this.getByteAt = function(iOffset) {
							 | 
						||
| 
								 | 
							
											return IEBinary_getByteAt(data, iOffset + dataOffset);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this.getLength = function() {
							 | 
						||
| 
								 | 
							
										return dataLength;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this.getSByteAt = function(iOffset) {
							 | 
						||
| 
								 | 
							
										var iByte = this.getByteAt(iOffset);
							 | 
						||
| 
								 | 
							
										if (iByte > 127)
							 | 
						||
| 
								 | 
							
											return iByte - 256;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											return iByte;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this.getShortAt = function(iOffset, bBigEndian) {
							 | 
						||
| 
								 | 
							
										var iShort = bBigEndian ? 
							 | 
						||
| 
								 | 
							
											(this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1)
							 | 
						||
| 
								 | 
							
											: (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset)
							 | 
						||
| 
								 | 
							
										if (iShort < 0) iShort += 65536;
							 | 
						||
| 
								 | 
							
										return iShort;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.getSShortAt = function(iOffset, bBigEndian) {
							 | 
						||
| 
								 | 
							
										var iUShort = this.getShortAt(iOffset, bBigEndian);
							 | 
						||
| 
								 | 
							
										if (iUShort > 32767)
							 | 
						||
| 
								 | 
							
											return iUShort - 65536;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											return iUShort;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.getLongAt = function(iOffset, bBigEndian) {
							 | 
						||
| 
								 | 
							
										var iByte1 = this.getByteAt(iOffset),
							 | 
						||
| 
								 | 
							
											iByte2 = this.getByteAt(iOffset + 1),
							 | 
						||
| 
								 | 
							
											iByte3 = this.getByteAt(iOffset + 2),
							 | 
						||
| 
								 | 
							
											iByte4 = this.getByteAt(iOffset + 3);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var iLong = bBigEndian ? 
							 | 
						||
| 
								 | 
							
											(((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4
							 | 
						||
| 
								 | 
							
											: (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;
							 | 
						||
| 
								 | 
							
										if (iLong < 0) iLong += 4294967296;
							 | 
						||
| 
								 | 
							
										return iLong;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.getSLongAt = function(iOffset, bBigEndian) {
							 | 
						||
| 
								 | 
							
										var iULong = this.getLongAt(iOffset, bBigEndian);
							 | 
						||
| 
								 | 
							
										if (iULong > 2147483647)
							 | 
						||
| 
								 | 
							
											return iULong - 4294967296;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											return iULong;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.getStringAt = function(iOffset, iLength) {
							 | 
						||
| 
								 | 
							
										var aStr = [];
							 | 
						||
| 
								 | 
							
										for (var i=iOffset,j=0;i<iOffset+iLength;i++,j++) {
							 | 
						||
| 
								 | 
							
											aStr[j] = String.fromCharCode(this.getByteAt(i));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return aStr.join("");
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this.getCharAt = function(iOffset) {
							 | 
						||
| 
								 | 
							
										return String.fromCharCode(this.getByteAt(iOffset));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.toBase64 = function() {
							 | 
						||
| 
								 | 
							
										return window.btoa(data);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									this.fromBase64 = function(strBase64) {
							 | 
						||
| 
								 | 
							
										data = window.atob(strBase64);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var BinaryAjax = (function() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function createRequest() {
							 | 
						||
| 
								 | 
							
										var oHTTP = null;
							 | 
						||
| 
								 | 
							
										if (window.XMLHttpRequest) {
							 | 
						||
| 
								 | 
							
											oHTTP = new XMLHttpRequest();
							 | 
						||
| 
								 | 
							
										} else if (window.ActiveXObject) {
							 | 
						||
| 
								 | 
							
											oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return oHTTP;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function getHead(strURL, fncCallback, fncError) {
							 | 
						||
| 
								 | 
							
										var oHTTP = createRequest();
							 | 
						||
| 
								 | 
							
										if (oHTTP) {
							 | 
						||
| 
								 | 
							
											if (fncCallback) {
							 | 
						||
| 
								 | 
							
												if (typeof(oHTTP.onload) != "undefined") {
							 | 
						||
| 
								 | 
							
													oHTTP.onload = function() {
							 | 
						||
| 
								 | 
							
														if (oHTTP.status == "200") {
							 | 
						||
| 
								 | 
							
															fncCallback(this);
							 | 
						||
| 
								 | 
							
														} else {
							 | 
						||
| 
								 | 
							
															if (fncError) fncError();
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														oHTTP = null;
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													oHTTP.onreadystatechange = function() {
							 | 
						||
| 
								 | 
							
														if (oHTTP.readyState == 4) {
							 | 
						||
| 
								 | 
							
															if (oHTTP.status == "200") {
							 | 
						||
| 
								 | 
							
																fncCallback(this);
							 | 
						||
| 
								 | 
							
															} else {
							 | 
						||
| 
								 | 
							
																if (fncError) fncError();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															oHTTP = null;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											oHTTP.open("HEAD", strURL, true);
							 | 
						||
| 
								 | 
							
											oHTTP.send(null);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											if (fncError) fncError();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function sendRequest(strURL, fncCallback, fncError, aRange, bAcceptRanges, iFileSize) {
							 | 
						||
| 
								 | 
							
										var oHTTP = createRequest();
							 | 
						||
| 
								 | 
							
										if (oHTTP) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var iDataOffset = 0;
							 | 
						||
| 
								 | 
							
											if (aRange && !bAcceptRanges) {
							 | 
						||
| 
								 | 
							
												iDataOffset = aRange[0];
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											var iDataLen = 0;
							 | 
						||
| 
								 | 
							
											if (aRange) {
							 | 
						||
| 
								 | 
							
												iDataLen = aRange[1]-aRange[0]+1;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (fncCallback) {
							 | 
						||
| 
								 | 
							
												if (typeof(oHTTP.onload) != "undefined") {
							 | 
						||
| 
								 | 
							
													oHTTP.onload = function() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
							 | 
						||
| 
								 | 
							
															this.binaryResponse = new BinaryFile(this.responseText, iDataOffset, iDataLen);
							 | 
						||
| 
								 | 
							
															this.fileSize = iFileSize || this.getResponseHeader("Content-Length");
							 | 
						||
| 
								 | 
							
															fncCallback(this);
							 | 
						||
| 
								 | 
							
														} else {
							 | 
						||
| 
								 | 
							
															if (fncError) fncError();
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														oHTTP = null;
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
												} else {
							 | 
						||
| 
								 | 
							
													oHTTP.onreadystatechange = function() {
							 | 
						||
| 
								 | 
							
														if (oHTTP.readyState == 4) {
							 | 
						||
| 
								 | 
							
															if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
							 | 
						||
| 
								 | 
							
																this.binaryResponse = new BinaryFile(oHTTP.responseBody, iDataOffset, iDataLen);
							 | 
						||
| 
								 | 
							
																this.fileSize = iFileSize || this.getResponseHeader("Content-Length");
							 | 
						||
| 
								 | 
							
																fncCallback(this);
							 | 
						||
| 
								 | 
							
															} else {
							 | 
						||
| 
								 | 
							
																if (fncError) fncError();
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
															oHTTP = null;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													};
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											oHTTP.open("GET", strURL, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (oHTTP.overrideMimeType) oHTTP.overrideMimeType('text/plain; charset=x-user-defined');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (aRange && bAcceptRanges) {
							 | 
						||
| 
								 | 
							
												oHTTP.setRequestHeader("Range", "bytes=" + aRange[0] + "-" + aRange[1]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											oHTTP.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 1970 00:00:00 GMT");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											oHTTP.send(null);
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											if (fncError) fncError();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return function(strURL, fncCallback, fncError, aRange) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (aRange) {
							 | 
						||
| 
								 | 
							
											getHead(
							 | 
						||
| 
								 | 
							
												strURL, 
							 | 
						||
| 
								 | 
							
												function(oHTTP) {
							 | 
						||
| 
								 | 
							
													var iLength = parseInt(oHTTP.getResponseHeader("Content-Length"),10);
							 | 
						||
| 
								 | 
							
													var strAcceptRanges = oHTTP.getResponseHeader("Accept-Ranges");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													var iStart, iEnd;
							 | 
						||
| 
								 | 
							
													iStart = aRange[0];
							 | 
						||
| 
								 | 
							
													if (aRange[0] < 0) 
							 | 
						||
| 
								 | 
							
														iStart += iLength;
							 | 
						||
| 
								 | 
							
													iEnd = iStart + aRange[1] - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													sendRequest(strURL, fncCallback, fncError, [iStart, iEnd], (strAcceptRanges == "bytes"), iLength);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											sendRequest(strURL, fncCallback, fncError);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								document.write(
							 | 
						||
| 
								 | 
							
									"<script type='text/vbscript'>\r\n"
							 | 
						||
| 
								 | 
							
									+ "Function IEBinary_getByteAt(strBinary, iOffset)\r\n"
							 | 
						||
| 
								 | 
							
									+ "	IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n"
							 | 
						||
| 
								 | 
							
									+ "End Function\r\n"
							 | 
						||
| 
								 | 
							
									+ "Function IEBinary_getLength(strBinary)\r\n"
							 | 
						||
| 
								 | 
							
									+ "	IEBinary_getLength = LenB(strBinary)\r\n"
							 | 
						||
| 
								 | 
							
									+ "End Function\r\n"
							 | 
						||
| 
								 | 
							
									+ "</script>\r\n"
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var EXIF = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var bDebug = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.Tags = {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// version tags
							 | 
						||
| 
								 | 
							
									0x9000 : "ExifVersion",			// EXIF version
							 | 
						||
| 
								 | 
							
									0xA000 : "FlashpixVersion",		// Flashpix format version
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// colorspace tags
							 | 
						||
| 
								 | 
							
									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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// user information
							 | 
						||
| 
								 | 
							
									0x927C : "MakerNote",			// Any desired information written by the manufacturer
							 | 
						||
| 
								 | 
							
									0x9286 : "UserComment",			// Comments by user
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// related 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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// 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
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// other tags
							 | 
						||
| 
								 | 
							
									0xA005 : "InteroperabilityIFDPointer",
							 | 
						||
| 
								 | 
							
									0xA420 : "ImageUniqueID"		// Identifier assigned uniquely to each image
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.TiffTags = {
							 | 
						||
| 
								 | 
							
									0x0100 : "ImageWidth",
							 | 
						||
| 
								 | 
							
									0x0101 : "ImageHeight",
							 | 
						||
| 
								 | 
							
									0x8769 : "ExifIFDPointer",
							 | 
						||
| 
								 | 
							
									0x8825 : "GPSInfoIFDPointer",
							 | 
						||
| 
								 | 
							
									0xA005 : "InteroperabilityIFDPointer",
							 | 
						||
| 
								 | 
							
									0x0102 : "BitsPerSample",
							 | 
						||
| 
								 | 
							
									0x0103 : "Compression",
							 | 
						||
| 
								 | 
							
									0x0106 : "PhotometricInterpretation",
							 | 
						||
| 
								 | 
							
									0x0112 : "Orientation",
							 | 
						||
| 
								 | 
							
									0x0115 : "SamplesPerPixel",
							 | 
						||
| 
								 | 
							
									0x011C : "PlanarConfiguration",
							 | 
						||
| 
								 | 
							
									0x0212 : "YCbCrSubSampling",
							 | 
						||
| 
								 | 
							
									0x0213 : "YCbCrPositioning",
							 | 
						||
| 
								 | 
							
									0x011A : "XResolution",
							 | 
						||
| 
								 | 
							
									0x011B : "YResolution",
							 | 
						||
| 
								 | 
							
									0x0128 : "ResolutionUnit",
							 | 
						||
| 
								 | 
							
									0x0111 : "StripOffsets",
							 | 
						||
| 
								 | 
							
									0x0116 : "RowsPerStrip",
							 | 
						||
| 
								 | 
							
									0x0117 : "StripByteCounts",
							 | 
						||
| 
								 | 
							
									0x0201 : "JPEGInterchangeFormat",
							 | 
						||
| 
								 | 
							
									0x0202 : "JPEGInterchangeFormatLength",
							 | 
						||
| 
								 | 
							
									0x012D : "TransferFunction",
							 | 
						||
| 
								 | 
							
									0x013E : "WhitePoint",
							 | 
						||
| 
								 | 
							
									0x013F : "PrimaryChromaticities",
							 | 
						||
| 
								 | 
							
									0x0211 : "YCbCrCoefficients",
							 | 
						||
| 
								 | 
							
									0x0214 : "ReferenceBlackWhite",
							 | 
						||
| 
								 | 
							
									0x0132 : "DateTime",
							 | 
						||
| 
								 | 
							
									0x010E : "ImageDescription",
							 | 
						||
| 
								 | 
							
									0x010F : "Make",
							 | 
						||
| 
								 | 
							
									0x0110 : "Model",
							 | 
						||
| 
								 | 
							
									0x0131 : "Software",
							 | 
						||
| 
								 | 
							
									0x013B : "Artist",
							 | 
						||
| 
								 | 
							
									0x8298 : "Copyright"
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.GPSTags = {
							 | 
						||
| 
								 | 
							
									0x0000 : "GPSVersionID",
							 | 
						||
| 
								 | 
							
									0x0001 : "GPSLatitudeRef",
							 | 
						||
| 
								 | 
							
									0x0002 : "GPSLatitude",
							 | 
						||
| 
								 | 
							
									0x0003 : "GPSLongitudeRef",
							 | 
						||
| 
								 | 
							
									0x0004 : "GPSLongitude",
							 | 
						||
| 
								 | 
							
									0x0005 : "GPSAltitudeRef",
							 | 
						||
| 
								 | 
							
									0x0006 : "GPSAltitude",
							 | 
						||
| 
								 | 
							
									0x0007 : "GPSTimeStamp",
							 | 
						||
| 
								 | 
							
									0x0008 : "GPSSatellites",
							 | 
						||
| 
								 | 
							
									0x0009 : "GPSStatus",
							 | 
						||
| 
								 | 
							
									0x000A : "GPSMeasureMode",
							 | 
						||
| 
								 | 
							
									0x000B : "GPSDOP",
							 | 
						||
| 
								 | 
							
									0x000C : "GPSSpeedRef",
							 | 
						||
| 
								 | 
							
									0x000D : "GPSSpeed",
							 | 
						||
| 
								 | 
							
									0x000E : "GPSTrackRef",
							 | 
						||
| 
								 | 
							
									0x000F : "GPSTrack",
							 | 
						||
| 
								 | 
							
									0x0010 : "GPSImgDirectionRef",
							 | 
						||
| 
								 | 
							
									0x0011 : "GPSImgDirection",
							 | 
						||
| 
								 | 
							
									0x0012 : "GPSMapDatum",
							 | 
						||
| 
								 | 
							
									0x0013 : "GPSDestLatitudeRef",
							 | 
						||
| 
								 | 
							
									0x0014 : "GPSDestLatitude",
							 | 
						||
| 
								 | 
							
									0x0015 : "GPSDestLongitudeRef",
							 | 
						||
| 
								 | 
							
									0x0016 : "GPSDestLongitude",
							 | 
						||
| 
								 | 
							
									0x0017 : "GPSDestBearingRef",
							 | 
						||
| 
								 | 
							
									0x0018 : "GPSDestBearing",
							 | 
						||
| 
								 | 
							
									0x0019 : "GPSDestDistanceRef",
							 | 
						||
| 
								 | 
							
									0x001A : "GPSDestDistance",
							 | 
						||
| 
								 | 
							
									0x001B : "GPSProcessingMethod",
							 | 
						||
| 
								 | 
							
									0x001C : "GPSAreaInformation",
							 | 
						||
| 
								 | 
							
									0x001D : "GPSDateStamp",
							 | 
						||
| 
								 | 
							
									0x001E : "GPSDifferential"
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.StringValues = {
							 | 
						||
| 
								 | 
							
									ExposureProgram : {
							 | 
						||
| 
								 | 
							
										0 : "Not defined",
							 | 
						||
| 
								 | 
							
										1 : "Manual",
							 | 
						||
| 
								 | 
							
										2 : "Normal program",
							 | 
						||
| 
								 | 
							
										3 : "Aperture priority",
							 | 
						||
| 
								 | 
							
										4 : "Shutter priority",
							 | 
						||
| 
								 | 
							
										5 : "Creative program",
							 | 
						||
| 
								 | 
							
										6 : "Action program",
							 | 
						||
| 
								 | 
							
										7 : "Portrait mode",
							 | 
						||
| 
								 | 
							
										8 : "Landscape mode"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									MeteringMode : {
							 | 
						||
| 
								 | 
							
										0 : "Unknown",
							 | 
						||
| 
								 | 
							
										1 : "Average",
							 | 
						||
| 
								 | 
							
										2 : "CenterWeightedAverage",
							 | 
						||
| 
								 | 
							
										3 : "Spot",
							 | 
						||
| 
								 | 
							
										4 : "MultiSpot",
							 | 
						||
| 
								 | 
							
										5 : "Pattern",
							 | 
						||
| 
								 | 
							
										6 : "Partial",
							 | 
						||
| 
								 | 
							
										255 : "Other"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									LightSource : {
							 | 
						||
| 
								 | 
							
										0 : "Unknown",
							 | 
						||
| 
								 | 
							
										1 : "Daylight",
							 | 
						||
| 
								 | 
							
										2 : "Fluorescent",
							 | 
						||
| 
								 | 
							
										3 : "Tungsten (incandescent light)",
							 | 
						||
| 
								 | 
							
										4 : "Flash",
							 | 
						||
| 
								 | 
							
										9 : "Fine weather",
							 | 
						||
| 
								 | 
							
										10 : "Cloudy weather",
							 | 
						||
| 
								 | 
							
										11 : "Shade",
							 | 
						||
| 
								 | 
							
										12 : "Daylight fluorescent (D 5700 - 7100K)",
							 | 
						||
| 
								 | 
							
										13 : "Day white fluorescent (N 4600 - 5400K)",
							 | 
						||
| 
								 | 
							
										14 : "Cool white fluorescent (W 3900 - 4500K)",
							 | 
						||
| 
								 | 
							
										15 : "White fluorescent (WW 3200 - 3700K)",
							 | 
						||
| 
								 | 
							
										17 : "Standard light A",
							 | 
						||
| 
								 | 
							
										18 : "Standard light B",
							 | 
						||
| 
								 | 
							
										19 : "Standard light C",
							 | 
						||
| 
								 | 
							
										20 : "D55",
							 | 
						||
| 
								 | 
							
										21 : "D65",
							 | 
						||
| 
								 | 
							
										22 : "D75",
							 | 
						||
| 
								 | 
							
										23 : "D50",
							 | 
						||
| 
								 | 
							
										24 : "ISO studio tungsten",
							 | 
						||
| 
								 | 
							
										255 : "Other"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									Flash : {
							 | 
						||
| 
								 | 
							
										0x0000 : "Flash did not fire",
							 | 
						||
| 
								 | 
							
										0x0001 : "Flash fired",
							 | 
						||
| 
								 | 
							
										0x0005 : "Strobe return light not detected",
							 | 
						||
| 
								 | 
							
										0x0007 : "Strobe return light detected",
							 | 
						||
| 
								 | 
							
										0x0009 : "Flash fired, compulsory flash mode",
							 | 
						||
| 
								 | 
							
										0x000D : "Flash fired, compulsory flash mode, return light not detected",
							 | 
						||
| 
								 | 
							
										0x000F : "Flash fired, compulsory flash mode, return light detected",
							 | 
						||
| 
								 | 
							
										0x0010 : "Flash did not fire, compulsory flash mode",
							 | 
						||
| 
								 | 
							
										0x0018 : "Flash did not fire, auto mode",
							 | 
						||
| 
								 | 
							
										0x0019 : "Flash fired, auto mode",
							 | 
						||
| 
								 | 
							
										0x001D : "Flash fired, auto mode, return light not detected",
							 | 
						||
| 
								 | 
							
										0x001F : "Flash fired, auto mode, return light detected",
							 | 
						||
| 
								 | 
							
										0x0020 : "No flash function",
							 | 
						||
| 
								 | 
							
										0x0041 : "Flash fired, red-eye reduction mode",
							 | 
						||
| 
								 | 
							
										0x0045 : "Flash fired, red-eye reduction mode, return light not detected",
							 | 
						||
| 
								 | 
							
										0x0047 : "Flash fired, red-eye reduction mode, return light detected",
							 | 
						||
| 
								 | 
							
										0x0049 : "Flash fired, compulsory flash mode, red-eye reduction mode",
							 | 
						||
| 
								 | 
							
										0x004D : "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
							 | 
						||
| 
								 | 
							
										0x004F : "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
							 | 
						||
| 
								 | 
							
										0x0059 : "Flash fired, auto mode, red-eye reduction mode",
							 | 
						||
| 
								 | 
							
										0x005D : "Flash fired, auto mode, return light not detected, red-eye reduction mode",
							 | 
						||
| 
								 | 
							
										0x005F : "Flash fired, auto mode, return light detected, red-eye reduction mode"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									SensingMethod : {
							 | 
						||
| 
								 | 
							
										1 : "Not defined",
							 | 
						||
| 
								 | 
							
										2 : "One-chip color area sensor",
							 | 
						||
| 
								 | 
							
										3 : "Two-chip color area sensor",
							 | 
						||
| 
								 | 
							
										4 : "Three-chip color area sensor",
							 | 
						||
| 
								 | 
							
										5 : "Color sequential area sensor",
							 | 
						||
| 
								 | 
							
										7 : "Trilinear sensor",
							 | 
						||
| 
								 | 
							
										8 : "Color sequential linear sensor"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									SceneCaptureType : {
							 | 
						||
| 
								 | 
							
										0 : "Standard",
							 | 
						||
| 
								 | 
							
										1 : "Landscape",
							 | 
						||
| 
								 | 
							
										2 : "Portrait",
							 | 
						||
| 
								 | 
							
										3 : "Night scene"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									SceneType : {
							 | 
						||
| 
								 | 
							
										1 : "Directly photographed"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									CustomRendered : {
							 | 
						||
| 
								 | 
							
										0 : "Normal process",
							 | 
						||
| 
								 | 
							
										1 : "Custom process"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									WhiteBalance : {
							 | 
						||
| 
								 | 
							
										0 : "Auto white balance",
							 | 
						||
| 
								 | 
							
										1 : "Manual white balance"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									GainControl : {
							 | 
						||
| 
								 | 
							
										0 : "None",
							 | 
						||
| 
								 | 
							
										1 : "Low gain up",
							 | 
						||
| 
								 | 
							
										2 : "High gain up",
							 | 
						||
| 
								 | 
							
										3 : "Low gain down",
							 | 
						||
| 
								 | 
							
										4 : "High gain down"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									Contrast : {
							 | 
						||
| 
								 | 
							
										0 : "Normal",
							 | 
						||
| 
								 | 
							
										1 : "Soft",
							 | 
						||
| 
								 | 
							
										2 : "Hard"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									Saturation : {
							 | 
						||
| 
								 | 
							
										0 : "Normal",
							 | 
						||
| 
								 | 
							
										1 : "Low saturation",
							 | 
						||
| 
								 | 
							
										2 : "High saturation"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									Sharpness : {
							 | 
						||
| 
								 | 
							
										0 : "Normal",
							 | 
						||
| 
								 | 
							
										1 : "Soft",
							 | 
						||
| 
								 | 
							
										2 : "Hard"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									SubjectDistanceRange : {
							 | 
						||
| 
								 | 
							
										0 : "Unknown",
							 | 
						||
| 
								 | 
							
										1 : "Macro",
							 | 
						||
| 
								 | 
							
										2 : "Close view",
							 | 
						||
| 
								 | 
							
										3 : "Distant view"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									FileSource : {
							 | 
						||
| 
								 | 
							
										3 : "DSC"
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Components : {
							 | 
						||
| 
								 | 
							
										0 : "",
							 | 
						||
| 
								 | 
							
										1 : "Y",
							 | 
						||
| 
								 | 
							
										2 : "Cb",
							 | 
						||
| 
								 | 
							
										3 : "Cr",
							 | 
						||
| 
								 | 
							
										4 : "R",
							 | 
						||
| 
								 | 
							
										5 : "G",
							 | 
						||
| 
								 | 
							
										6 : "B"
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function addEvent(oElement, strEvent, fncHandler) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (oElement.addEventListener) { 
							 | 
						||
| 
								 | 
							
										oElement.addEventListener(strEvent, fncHandler, false); 
							 | 
						||
| 
								 | 
							
									} else if (oElement.attachEvent) { 
							 | 
						||
| 
								 | 
							
										oElement.attachEvent("on" + strEvent, fncHandler); 
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function imageHasData(oImg) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return !!(oImg.exifdata);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function getImageData(oImg, fncCallback) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									BinaryAjax(
							 | 
						||
| 
								 | 
							
										oImg.src,
							 | 
						||
| 
								 | 
							
										function(oHTTP) {
							 | 
						||
| 
								 | 
							
											var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse);
							 | 
						||
| 
								 | 
							
											oImg.exifdata = oEXIF || {};
							 | 
						||
| 
								 | 
							
											if (fncCallback) fncCallback();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function findEXIFinJPEG(oFile) {
							 | 
						||
| 
								 | 
							
									var aMarkers = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {
							 | 
						||
| 
								 | 
							
										return false; // not a valid jpeg
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var iOffset = 2;
							 | 
						||
| 
								 | 
							
									var iLength = oFile.getLength();
							 | 
						||
| 
								 | 
							
									while (iOffset < iLength) {
							 | 
						||
| 
								 | 
							
										if (oFile.getByteAt(iOffset) != 0xFF) {
							 | 
						||
| 
								 | 
							
											if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset));
							 | 
						||
| 
								 | 
							
											return false; // not a valid marker, something is wrong
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var iMarker = oFile.getByteAt(iOffset+1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// we could implement handling for other markers here, 
							 | 
						||
| 
								 | 
							
										// but we're only looking for 0xFFE1 for EXIF data
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (iMarker == 22400) {
							 | 
						||
| 
								 | 
							
											if (bDebug) console.log("Found 0xFFE1 marker");
							 | 
						||
| 
								 | 
							
											return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
							 | 
						||
| 
								 | 
							
											iOffset += 2 + oFile.getShortAt(iOffset+2, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else if (iMarker == 225) {
							 | 
						||
| 
								 | 
							
											// 0xE1 = Application-specific 1 (for EXIF)
							 | 
						||
| 
								 | 
							
											if (bDebug) console.log("Found 0xFFE1 marker");
							 | 
						||
| 
								 | 
							
											return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										} else {
							 | 
						||
| 
								 | 
							
											iOffset += 2 + oFile.getShortAt(iOffset+2, true);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									var iEntries = oFile.getShortAt(iDirStart, bBigEnd);
							 | 
						||
| 
								 | 
							
									var oTags = {};
							 | 
						||
| 
								 | 
							
									for (var i=0;i<iEntries;i++) {
							 | 
						||
| 
								 | 
							
										var iEntryOffset = iDirStart + i*12 + 2;
							 | 
						||
| 
								 | 
							
										var strTag = oStrings[oFile.getShortAt(iEntryOffset, bBigEnd)];
							 | 
						||
| 
								 | 
							
										if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd));
							 | 
						||
| 
								 | 
							
										oTags[strTag] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return oTags;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd);
							 | 
						||
| 
								 | 
							
									var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd);
							 | 
						||
| 
								 | 
							
									var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch (iType) {
							 | 
						||
| 
								 | 
							
										case 1: // byte, 8-bit unsigned int
							 | 
						||
| 
								 | 
							
										case 7: // undefined, 8-bit byte, value depending on field
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getByteAt(iEntryOffset + 8, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getByteAt(iValOffset + n);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case 2: // ascii, 8-bit byte
							 | 
						||
| 
								 | 
							
											var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
							 | 
						||
| 
								 | 
							
											return oFile.getStringAt(iStringOffset, iNumValues-1);
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case 3: // short, 16 bit int
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getShortAt(iEntryOffset + 8, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8);
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getShortAt(iValOffset + 2*n, bBigEnd);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										case 4: // long, 32 bit int
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getLongAt(iEntryOffset + 8, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getLongAt(iValueOffset + 4*n, bBigEnd);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case 5:	// rational = two long values, first is numerator, second is denominator
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8*n, bBigEnd);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case 9: // slong, 32 bit signed int
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getSLongAt(iEntryOffset + 8, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getSLongAt(iValueOffset + 4*n, bBigEnd);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case 10: // signed rational, two slongs, first is numerator, second is denominator
							 | 
						||
| 
								 | 
							
											if (iNumValues == 1) {
							 | 
						||
| 
								 | 
							
												return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var aVals = [];
							 | 
						||
| 
								 | 
							
												for (var n=0;n<iNumValues;n++) {
							 | 
						||
| 
								 | 
							
													aVals[n] = oFile.getSLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8*n, bBigEnd);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return aVals;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function readEXIFData(oFile, iStart, iLength) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (oFile.getStringAt(iStart, 4) != "Exif") {
							 | 
						||
| 
								 | 
							
										if (bDebug) console.log("Not valid EXIF data! " + oFile.getStringAt(iStart, 4));
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var bBigEnd;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var iTIFFOffset = iStart + 6;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// test for TIFF validity and endianness
							 | 
						||
| 
								 | 
							
									if (oFile.getShortAt(iTIFFOffset) == 0x4949) {
							 | 
						||
| 
								 | 
							
										bBigEnd = false;
							 | 
						||
| 
								 | 
							
									} else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) {
							 | 
						||
| 
								 | 
							
										bBigEnd = true;
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										if (bDebug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)");
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) {
							 | 
						||
| 
								 | 
							
										if (bDebug) console.log("Not valid TIFF data! (no 0x002A)");
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) {
							 | 
						||
| 
								 | 
							
										if (bDebug) console.log("Not valid TIFF data! (First offset not 8)", oFile.getShortAt(iTIFFOffset+4, bBigEnd));
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (oTags.ExifIFDPointer) {
							 | 
						||
| 
								 | 
							
										var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd);
							 | 
						||
| 
								 | 
							
										for (var strTag in oEXIFTags) {
							 | 
						||
| 
								 | 
							
											switch (strTag) {
							 | 
						||
| 
								 | 
							
												case "LightSource" :
							 | 
						||
| 
								 | 
							
												case "Flash" :
							 | 
						||
| 
								 | 
							
												case "MeteringMode" :
							 | 
						||
| 
								 | 
							
												case "ExposureProgram" :
							 | 
						||
| 
								 | 
							
												case "SensingMethod" :
							 | 
						||
| 
								 | 
							
												case "SceneCaptureType" :
							 | 
						||
| 
								 | 
							
												case "SceneType" :
							 | 
						||
| 
								 | 
							
												case "CustomRendered" :
							 | 
						||
| 
								 | 
							
												case "WhiteBalance" : 
							 | 
						||
| 
								 | 
							
												case "GainControl" : 
							 | 
						||
| 
								 | 
							
												case "Contrast" :
							 | 
						||
| 
								 | 
							
												case "Saturation" :
							 | 
						||
| 
								 | 
							
												case "Sharpness" : 
							 | 
						||
| 
								 | 
							
												case "SubjectDistanceRange" :
							 | 
						||
| 
								 | 
							
												case "FileSource" :
							 | 
						||
| 
								 | 
							
													oEXIFTags[strTag] = EXIF.StringValues[strTag][oEXIFTags[strTag]];
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
												case "ExifVersion" :
							 | 
						||
| 
								 | 
							
												case "FlashpixVersion" :
							 | 
						||
| 
								 | 
							
													oEXIFTags[strTag] = String.fromCharCode(oEXIFTags[strTag][0], oEXIFTags[strTag][1], oEXIFTags[strTag][2], oEXIFTags[strTag][3]);
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
												case "ComponentsConfiguration" : 
							 | 
						||
| 
								 | 
							
													oEXIFTags[strTag] = 
							 | 
						||
| 
								 | 
							
														EXIF.StringValues.Components[oEXIFTags[strTag][0]]
							 | 
						||
| 
								 | 
							
														+ EXIF.StringValues.Components[oEXIFTags[strTag][1]]
							 | 
						||
| 
								 | 
							
														+ EXIF.StringValues.Components[oEXIFTags[strTag][2]]
							 | 
						||
| 
								 | 
							
														+ EXIF.StringValues.Components[oEXIFTags[strTag][3]];
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											oTags[strTag] = oEXIFTags[strTag];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (oTags.GPSInfoIFDPointer) {
							 | 
						||
| 
								 | 
							
										var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd);
							 | 
						||
| 
								 | 
							
										for (var strTag in oGPSTags) {
							 | 
						||
| 
								 | 
							
											switch (strTag) {
							 | 
						||
| 
								 | 
							
												case "GPSVersionID" : 
							 | 
						||
| 
								 | 
							
													oGPSTags[strTag] = oGPSTags[strTag][0] 
							 | 
						||
| 
								 | 
							
														+ "." + oGPSTags[strTag][1] 
							 | 
						||
| 
								 | 
							
														+ "." + oGPSTags[strTag][2] 
							 | 
						||
| 
								 | 
							
														+ "." + oGPSTags[strTag][3];
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											oTags[strTag] = oGPSTags[strTag];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return oTags;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.getData = function(oImg, fncCallback) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!oImg.complete) return false;
							 | 
						||
| 
								 | 
							
									if (!imageHasData(oImg)) {
							 | 
						||
| 
								 | 
							
										getImageData(oImg, fncCallback);
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										if (fncCallback) fncCallback();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.getTag = function(oImg, strTag) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!imageHasData(oImg)) return;
							 | 
						||
| 
								 | 
							
									return oImg.exifdata[strTag];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.getAllTags = function(oImg) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!imageHasData(oImg)) return {};
							 | 
						||
| 
								 | 
							
									var oData = oImg.exifdata;
							 | 
						||
| 
								 | 
							
									var oAllTags = {};
							 | 
						||
| 
								 | 
							
									for (var a in oData) {
							 | 
						||
| 
								 | 
							
										if (oData.hasOwnProperty(a)) {
							 | 
						||
| 
								 | 
							
											oAllTags[a] = oData[a];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return oAllTags;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.pretty = function(oImg) 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!imageHasData(oImg)) return "";
							 | 
						||
| 
								 | 
							
									var oData = oImg.exifdata;
							 | 
						||
| 
								 | 
							
									var strPretty = "";
							 | 
						||
| 
								 | 
							
									for (var a in oData) {
							 | 
						||
| 
								 | 
							
										if (oData.hasOwnProperty(a)) {
							 | 
						||
| 
								 | 
							
											if (typeof oData[a] == "object") {
							 | 
						||
| 
								 | 
							
												strPretty += a + " : [" + oData[a].length + " values]\r\n";
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												strPretty += a + " : " + oData[a] + "\r\n";
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return strPretty;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								EXIF.readFromBinaryFile = function(oFile) {
							 | 
						||
| 
								 | 
							
									return findEXIFinJPEG(oFile);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function loadAllImages() 
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									var aImages = document.getElementsByTagName("img");
							 | 
						||
| 
								 | 
							
									for (var i=0;i<aImages.length;i++) {
							 | 
						||
| 
								 | 
							
										if (aImages[i].getAttribute("exif") == "true") {
							 | 
						||
| 
								 | 
							
											if (!aImages[i].complete) {
							 | 
						||
| 
								 | 
							
												addEvent(aImages[i], "load", 
							 | 
						||
| 
								 | 
							
													function() {
							 | 
						||
| 
								 | 
							
														EXIF.getData(this);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												); 
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												EXIF.getData(aImages[i]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// automatically load exif data for all images with exif=true when doc is ready
							 | 
						||
| 
								 | 
							
								jQuery(document).ready(loadAllImages);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// load data for images manually
							 | 
						||
| 
								 | 
							
								jQuery.fn.exifLoad = function(fncCallback) {
							 | 
						||
| 
								 | 
							
									return this.each(function() {
							 | 
						||
| 
								 | 
							
										EXIF.getData(this, fncCallback)
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jQuery.fn.exif = function(strTag) {
							 | 
						||
| 
								 | 
							
									var aStrings = [];
							 | 
						||
| 
								 | 
							
									this.each(function() {
							 | 
						||
| 
								 | 
							
										aStrings.push(EXIF.getTag(this, strTag));
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
									return aStrings;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jQuery.fn.exifAll = function() {
							 | 
						||
| 
								 | 
							
									var aStrings = [];
							 | 
						||
| 
								 | 
							
									this.each(function() {
							 | 
						||
| 
								 | 
							
										aStrings.push(EXIF.getAllTags(this));
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
									return aStrings;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								jQuery.fn.exifPretty = function() {
							 | 
						||
| 
								 | 
							
									var aStrings = [];
							 | 
						||
| 
								 | 
							
									this.each(function() {
							 | 
						||
| 
								 | 
							
										aStrings.push(EXIF.pretty(this));
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
									return aStrings;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								})();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								})();
							 |