blueimp-load-image-rails 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8133cf8c64435ad3168dd29b095059df333d32a3
4
+ data.tar.gz: 5f1f05730295c1ffdd58a47ebe3693e2399f25a6
5
+ SHA512:
6
+ metadata.gz: b27c7863a034c4bd3de0b52279f0db569800586daf10db97cc5ff63102ce7f5215883650ac0db4c01b50251e6b2d065df4d68f0fc0bb6516f230bc217b56a25b
7
+ data.tar.gz: 647256f48a2a63c9a90ad98d06bd7e6fb42eab3b2f8d8becaf54362788837f46a4852a314ff321eb4c1a850c420284e8c473f1a280e6f4bb1aa196bb51c534db
@@ -0,0 +1,11 @@
1
+ # This is a generated file.
2
+ require "blueimp-load-image-rails/version"
3
+
4
+ module Blueimp
5
+ module LoadImage
6
+ module Rails
7
+ class Engine < ::Rails::Engine
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ # This is a generated file.
2
+ module Blueimp
3
+ module LoadImage
4
+ module Rails
5
+ class Version
6
+ class << self
7
+ def to_s
8
+ "1.8.0"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ //= require load-image
2
+ //= require load-image-ios
3
+ //= require load-image-meta
4
+ //= require load-image-exif
5
+ //= require load-image-exif-map
@@ -0,0 +1,385 @@
1
+ /*
2
+ * JavaScript Load Image Exif Map 1.0.1
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2013, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Exif tags mapping based on
9
+ * https://github.com/jseidelin/exif-js
10
+ *
11
+ * Licensed under the MIT license:
12
+ * http://www.opensource.org/licenses/MIT
13
+ */
14
+
15
+ /*global define, window */
16
+
17
+ (function (factory) {
18
+ 'use strict';
19
+ if (typeof define === 'function' && define.amd) {
20
+ // Register as an anonymous AMD module:
21
+ define(['load-image', 'load-image-exif'], factory);
22
+ } else {
23
+ // Browser globals:
24
+ factory(window.loadImage);
25
+ }
26
+ }(function (loadImage) {
27
+ 'use strict';
28
+
29
+ var tags,
30
+ map,
31
+ prop;
32
+
33
+ loadImage.ExifMap.prototype.tags = {
34
+ // =================
35
+ // TIFF tags (IFD0):
36
+ // =================
37
+ 0x0100: 'ImageWidth',
38
+ 0x0101: 'ImageHeight',
39
+ 0x8769: 'ExifIFDPointer',
40
+ 0x8825: 'GPSInfoIFDPointer',
41
+ 0xA005: 'InteroperabilityIFDPointer',
42
+ 0x0102: 'BitsPerSample',
43
+ 0x0103: 'Compression',
44
+ 0x0106: 'PhotometricInterpretation',
45
+ 0x0112: 'Orientation',
46
+ 0x0115: 'SamplesPerPixel',
47
+ 0x011C: 'PlanarConfiguration',
48
+ 0x0212: 'YCbCrSubSampling',
49
+ 0x0213: 'YCbCrPositioning',
50
+ 0x011A: 'XResolution',
51
+ 0x011B: 'YResolution',
52
+ 0x0128: 'ResolutionUnit',
53
+ 0x0111: 'StripOffsets',
54
+ 0x0116: 'RowsPerStrip',
55
+ 0x0117: 'StripByteCounts',
56
+ 0x0201: 'JPEGInterchangeFormat',
57
+ 0x0202: 'JPEGInterchangeFormatLength',
58
+ 0x012D: 'TransferFunction',
59
+ 0x013E: 'WhitePoint',
60
+ 0x013F: 'PrimaryChromaticities',
61
+ 0x0211: 'YCbCrCoefficients',
62
+ 0x0214: 'ReferenceBlackWhite',
63
+ 0x0132: 'DateTime',
64
+ 0x010E: 'ImageDescription',
65
+ 0x010F: 'Make',
66
+ 0x0110: 'Model',
67
+ 0x0131: 'Software',
68
+ 0x013B: 'Artist',
69
+ 0x8298: 'Copyright',
70
+ // ==================
71
+ // Exif Sub IFD tags:
72
+ // ==================
73
+ 0x9000: 'ExifVersion', // EXIF version
74
+ 0xA000: 'FlashpixVersion', // Flashpix format version
75
+ 0xA001: 'ColorSpace', // Color space information tag
76
+ 0xA002: 'PixelXDimension', // Valid width of meaningful image
77
+ 0xA003: 'PixelYDimension', // Valid height of meaningful image
78
+ 0xA500: 'Gamma',
79
+ 0x9101: 'ComponentsConfiguration', // Information about channels
80
+ 0x9102: 'CompressedBitsPerPixel', // Compressed bits per pixel
81
+ 0x927C: 'MakerNote', // Any desired information written by the manufacturer
82
+ 0x9286: 'UserComment', // Comments by user
83
+ 0xA004: 'RelatedSoundFile', // Name of related sound file
84
+ 0x9003: 'DateTimeOriginal', // Date and time when the original image was generated
85
+ 0x9004: 'DateTimeDigitized', // Date and time when the image was stored digitally
86
+ 0x9290: 'SubSecTime', // Fractions of seconds for DateTime
87
+ 0x9291: 'SubSecTimeOriginal', // Fractions of seconds for DateTimeOriginal
88
+ 0x9292: 'SubSecTimeDigitized', // Fractions of seconds for DateTimeDigitized
89
+ 0x829A: 'ExposureTime', // Exposure time (in seconds)
90
+ 0x829D: 'FNumber',
91
+ 0x8822: 'ExposureProgram', // Exposure program
92
+ 0x8824: 'SpectralSensitivity', // Spectral sensitivity
93
+ 0x8827: 'PhotographicSensitivity', // EXIF 2.3, ISOSpeedRatings in EXIF 2.2
94
+ 0x8828: 'OECF', // Optoelectric conversion factor
95
+ 0x8830: 'SensitivityType',
96
+ 0x8831: 'StandardOutputSensitivity',
97
+ 0x8832: 'RecommendedExposureIndex',
98
+ 0x8833: 'ISOSpeed',
99
+ 0x8834: 'ISOSpeedLatitudeyyy',
100
+ 0x8835: 'ISOSpeedLatitudezzz',
101
+ 0x9201: 'ShutterSpeedValue', // Shutter speed
102
+ 0x9202: 'ApertureValue', // Lens aperture
103
+ 0x9203: 'BrightnessValue', // Value of brightness
104
+ 0x9204: 'ExposureBias', // Exposure bias
105
+ 0x9205: 'MaxApertureValue', // Smallest F number of lens
106
+ 0x9206: 'SubjectDistance', // Distance to subject in meters
107
+ 0x9207: 'MeteringMode', // Metering mode
108
+ 0x9208: 'LightSource', // Kind of light source
109
+ 0x9209: 'Flash', // Flash status
110
+ 0x9214: 'SubjectArea', // Location and area of main subject
111
+ 0x920A: 'FocalLength', // Focal length of the lens in mm
112
+ 0xA20B: 'FlashEnergy', // Strobe energy in BCPS
113
+ 0xA20C: 'SpatialFrequencyResponse',
114
+ 0xA20E: 'FocalPlaneXResolution', // Number of pixels in width direction per FPRUnit
115
+ 0xA20F: 'FocalPlaneYResolution', // Number of pixels in height direction per FPRUnit
116
+ 0xA210: 'FocalPlaneResolutionUnit', // Unit for measuring the focal plane resolution
117
+ 0xA214: 'SubjectLocation', // Location of subject in image
118
+ 0xA215: 'ExposureIndex', // Exposure index selected on camera
119
+ 0xA217: 'SensingMethod', // Image sensor type
120
+ 0xA300: 'FileSource', // Image source (3 == DSC)
121
+ 0xA301: 'SceneType', // Scene type (1 == directly photographed)
122
+ 0xA302: 'CFAPattern', // Color filter array geometric pattern
123
+ 0xA401: 'CustomRendered', // Special processing
124
+ 0xA402: 'ExposureMode', // Exposure mode
125
+ 0xA403: 'WhiteBalance', // 1 = auto white balance, 2 = manual
126
+ 0xA404: 'DigitalZoomRatio', // Digital zoom ratio
127
+ 0xA405: 'FocalLengthIn35mmFilm',
128
+ 0xA406: 'SceneCaptureType', // Type of scene
129
+ 0xA407: 'GainControl', // Degree of overall image gain adjustment
130
+ 0xA408: 'Contrast', // Direction of contrast processing applied by camera
131
+ 0xA409: 'Saturation', // Direction of saturation processing applied by camera
132
+ 0xA40A: 'Sharpness', // Direction of sharpness processing applied by camera
133
+ 0xA40B: 'DeviceSettingDescription',
134
+ 0xA40C: 'SubjectDistanceRange', // Distance to subject
135
+ 0xA420: 'ImageUniqueID', // Identifier assigned uniquely to each image
136
+ 0xA430: 'CameraOwnerName',
137
+ 0xA431: 'BodySerialNumber',
138
+ 0xA432: 'LensSpecification',
139
+ 0xA433: 'LensMake',
140
+ 0xA434: 'LensModel',
141
+ 0xA435: 'LensSerialNumber',
142
+ // ==============
143
+ // GPS Info tags:
144
+ // ==============
145
+ 0x0000: 'GPSVersionID',
146
+ 0x0001: 'GPSLatitudeRef',
147
+ 0x0002: 'GPSLatitude',
148
+ 0x0003: 'GPSLongitudeRef',
149
+ 0x0004: 'GPSLongitude',
150
+ 0x0005: 'GPSAltitudeRef',
151
+ 0x0006: 'GPSAltitude',
152
+ 0x0007: 'GPSTimeStamp',
153
+ 0x0008: 'GPSSatellites',
154
+ 0x0009: 'GPSStatus',
155
+ 0x000A: 'GPSMeasureMode',
156
+ 0x000B: 'GPSDOP',
157
+ 0x000C: 'GPSSpeedRef',
158
+ 0x000D: 'GPSSpeed',
159
+ 0x000E: 'GPSTrackRef',
160
+ 0x000F: 'GPSTrack',
161
+ 0x0010: 'GPSImgDirectionRef',
162
+ 0x0011: 'GPSImgDirection',
163
+ 0x0012: 'GPSMapDatum',
164
+ 0x0013: 'GPSDestLatitudeRef',
165
+ 0x0014: 'GPSDestLatitude',
166
+ 0x0015: 'GPSDestLongitudeRef',
167
+ 0x0016: 'GPSDestLongitude',
168
+ 0x0017: 'GPSDestBearingRef',
169
+ 0x0018: 'GPSDestBearing',
170
+ 0x0019: 'GPSDestDistanceRef',
171
+ 0x001A: 'GPSDestDistance',
172
+ 0x001B: 'GPSProcessingMethod',
173
+ 0x001C: 'GPSAreaInformation',
174
+ 0x001D: 'GPSDateStamp',
175
+ 0x001E: 'GPSDifferential',
176
+ 0x001F: 'GPSHPositioningError'
177
+ };
178
+
179
+ loadImage.ExifMap.prototype.stringValues = {
180
+ ExposureProgram: {
181
+ 0: 'Undefined',
182
+ 1: 'Manual',
183
+ 2: 'Normal program',
184
+ 3: 'Aperture priority',
185
+ 4: 'Shutter priority',
186
+ 5: 'Creative program',
187
+ 6: 'Action program',
188
+ 7: 'Portrait mode',
189
+ 8: 'Landscape mode'
190
+ },
191
+ MeteringMode: {
192
+ 0: 'Unknown',
193
+ 1: 'Average',
194
+ 2: 'CenterWeightedAverage',
195
+ 3: 'Spot',
196
+ 4: 'MultiSpot',
197
+ 5: 'Pattern',
198
+ 6: 'Partial',
199
+ 255: 'Other'
200
+ },
201
+ LightSource: {
202
+ 0: 'Unknown',
203
+ 1: 'Daylight',
204
+ 2: 'Fluorescent',
205
+ 3: 'Tungsten (incandescent light)',
206
+ 4: 'Flash',
207
+ 9: 'Fine weather',
208
+ 10: 'Cloudy weather',
209
+ 11: 'Shade',
210
+ 12: 'Daylight fluorescent (D 5700 - 7100K)',
211
+ 13: 'Day white fluorescent (N 4600 - 5400K)',
212
+ 14: 'Cool white fluorescent (W 3900 - 4500K)',
213
+ 15: 'White fluorescent (WW 3200 - 3700K)',
214
+ 17: 'Standard light A',
215
+ 18: 'Standard light B',
216
+ 19: 'Standard light C',
217
+ 20: 'D55',
218
+ 21: 'D65',
219
+ 22: 'D75',
220
+ 23: 'D50',
221
+ 24: 'ISO studio tungsten',
222
+ 255: 'Other'
223
+ },
224
+ Flash: {
225
+ 0x0000: 'Flash did not fire',
226
+ 0x0001: 'Flash fired',
227
+ 0x0005: 'Strobe return light not detected',
228
+ 0x0007: 'Strobe return light detected',
229
+ 0x0009: 'Flash fired, compulsory flash mode',
230
+ 0x000D: 'Flash fired, compulsory flash mode, return light not detected',
231
+ 0x000F: 'Flash fired, compulsory flash mode, return light detected',
232
+ 0x0010: 'Flash did not fire, compulsory flash mode',
233
+ 0x0018: 'Flash did not fire, auto mode',
234
+ 0x0019: 'Flash fired, auto mode',
235
+ 0x001D: 'Flash fired, auto mode, return light not detected',
236
+ 0x001F: 'Flash fired, auto mode, return light detected',
237
+ 0x0020: 'No flash function',
238
+ 0x0041: 'Flash fired, red-eye reduction mode',
239
+ 0x0045: 'Flash fired, red-eye reduction mode, return light not detected',
240
+ 0x0047: 'Flash fired, red-eye reduction mode, return light detected',
241
+ 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode',
242
+ 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected',
243
+ 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected',
244
+ 0x0059: 'Flash fired, auto mode, red-eye reduction mode',
245
+ 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode',
246
+ 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode'
247
+ },
248
+ SensingMethod: {
249
+ 1: 'Undefined',
250
+ 2: 'One-chip color area sensor',
251
+ 3: 'Two-chip color area sensor',
252
+ 4: 'Three-chip color area sensor',
253
+ 5: 'Color sequential area sensor',
254
+ 7: 'Trilinear sensor',
255
+ 8: 'Color sequential linear sensor'
256
+ },
257
+ SceneCaptureType: {
258
+ 0: 'Standard',
259
+ 1: 'Landscape',
260
+ 2: 'Portrait',
261
+ 3: 'Night scene'
262
+ },
263
+ SceneType: {
264
+ 1: 'Directly photographed'
265
+ },
266
+ CustomRendered: {
267
+ 0: 'Normal process',
268
+ 1: 'Custom process'
269
+ },
270
+ WhiteBalance: {
271
+ 0: 'Auto white balance',
272
+ 1: 'Manual white balance'
273
+ },
274
+ GainControl: {
275
+ 0: 'None',
276
+ 1: 'Low gain up',
277
+ 2: 'High gain up',
278
+ 3: 'Low gain down',
279
+ 4: 'High gain down'
280
+ },
281
+ Contrast: {
282
+ 0: 'Normal',
283
+ 1: 'Soft',
284
+ 2: 'Hard'
285
+ },
286
+ Saturation: {
287
+ 0: 'Normal',
288
+ 1: 'Low saturation',
289
+ 2: 'High saturation'
290
+ },
291
+ Sharpness: {
292
+ 0: 'Normal',
293
+ 1: 'Soft',
294
+ 2: 'Hard'
295
+ },
296
+ SubjectDistanceRange: {
297
+ 0: 'Unknown',
298
+ 1: 'Macro',
299
+ 2: 'Close view',
300
+ 3: 'Distant view'
301
+ },
302
+ FileSource: {
303
+ 3: 'DSC'
304
+ },
305
+ ComponentsConfiguration: {
306
+ 0: '',
307
+ 1: 'Y',
308
+ 2: 'Cb',
309
+ 3: 'Cr',
310
+ 4: 'R',
311
+ 5: 'G',
312
+ 6: 'B'
313
+ },
314
+ Orientation: {
315
+ 1: 'top-left',
316
+ 2: 'top-right',
317
+ 3: 'bottom-right',
318
+ 4: 'bottom-left',
319
+ 5: 'left-top',
320
+ 6: 'right-top',
321
+ 7: 'right-bottom',
322
+ 8: 'left-bottom'
323
+ }
324
+ };
325
+
326
+ loadImage.ExifMap.prototype.getText = function (id) {
327
+ var value = this.get(id);
328
+ switch (id) {
329
+ case 'LightSource':
330
+ case 'Flash':
331
+ case 'MeteringMode':
332
+ case 'ExposureProgram':
333
+ case 'SensingMethod':
334
+ case 'SceneCaptureType':
335
+ case 'SceneType':
336
+ case 'CustomRendered':
337
+ case 'WhiteBalance':
338
+ case 'GainControl':
339
+ case 'Contrast':
340
+ case 'Saturation':
341
+ case 'Sharpness':
342
+ case 'SubjectDistanceRange':
343
+ case 'FileSource':
344
+ case 'Orientation':
345
+ return this.stringValues[id][value];
346
+ case 'ExifVersion':
347
+ case 'FlashpixVersion':
348
+ return String.fromCharCode(value[0], value[1], value[2], value[3]);
349
+ case 'ComponentsConfiguration':
350
+ return this.stringValues[id][value[0]]
351
+ + this.stringValues[id][value[1]]
352
+ + this.stringValues[id][value[2]]
353
+ + this.stringValues[id][value[3]];
354
+ case 'GPSVersionID':
355
+ return value[0] + '.' + value[1] + '.' + value[2] + '.' + value[3];
356
+ }
357
+ return String(value);
358
+ };
359
+
360
+ tags = loadImage.ExifMap.prototype.tags;
361
+ map = loadImage.ExifMap.prototype.map;
362
+
363
+ // Map the tag names to tags:
364
+ for (prop in tags) {
365
+ if (tags.hasOwnProperty(prop)) {
366
+ map[tags[prop]] = prop;
367
+ }
368
+ }
369
+
370
+ loadImage.ExifMap.prototype.getAll = function () {
371
+ var map = {},
372
+ prop,
373
+ id;
374
+ for (prop in this) {
375
+ if (this.hasOwnProperty(prop)) {
376
+ id = tags[prop];
377
+ if (id) {
378
+ map[id] = this.getText(id);
379
+ }
380
+ }
381
+ }
382
+ return map;
383
+ };
384
+
385
+ }));
@@ -0,0 +1,299 @@
1
+ /*
2
+ * JavaScript Load Image Exif Parser 1.0.0
3
+ * https://github.com/blueimp/JavaScript-Load-Image
4
+ *
5
+ * Copyright 2013, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /*jslint unparam: true */
13
+ /*global define, window, console */
14
+
15
+ (function (factory) {
16
+ 'use strict';
17
+ if (typeof define === 'function' && define.amd) {
18
+ // Register as an anonymous AMD module:
19
+ define(['load-image', 'load-image-meta'], factory);
20
+ } else {
21
+ // Browser globals:
22
+ factory(window.loadImage);
23
+ }
24
+ }(function (loadImage) {
25
+ 'use strict';
26
+
27
+ loadImage.ExifMap = function () {
28
+ return this;
29
+ };
30
+
31
+ loadImage.ExifMap.prototype.map = {
32
+ 'Orientation': 0x0112
33
+ };
34
+
35
+ loadImage.ExifMap.prototype.get = function (id) {
36
+ return this[id] || this[this.map[id]];
37
+ };
38
+
39
+ loadImage.getExifThumbnail = function (dataView, offset, length) {
40
+ var hexData,
41
+ i,
42
+ b;
43
+ if (!length || offset + length > dataView.byteLength) {
44
+ console.log('Invalid Exif data: Invalid thumbnail data.');
45
+ return;
46
+ }
47
+ hexData = [];
48
+ for (i = 0; i < length; i += 1) {
49
+ b = dataView.getUint8(offset + i);
50
+ hexData.push((b < 16 ? '0' : '') + b.toString(16));
51
+ }
52
+ return 'data:image/jpeg,%' + hexData.join('%');
53
+ };
54
+
55
+ loadImage.exifTagTypes = {
56
+ // byte, 8-bit unsigned int:
57
+ 1: {
58
+ getValue: function (dataView, dataOffset) {
59
+ return dataView.getUint8(dataOffset);
60
+ },
61
+ size: 1
62
+ },
63
+ // ascii, 8-bit byte:
64
+ 2: {
65
+ getValue: function (dataView, dataOffset) {
66
+ return String.fromCharCode(dataView.getUint8(dataOffset));
67
+ },
68
+ size: 1,
69
+ ascii: true
70
+ },
71
+ // short, 16 bit int:
72
+ 3: {
73
+ getValue: function (dataView, dataOffset, littleEndian) {
74
+ return dataView.getUint16(dataOffset, littleEndian);
75
+ },
76
+ size: 2
77
+ },
78
+ // long, 32 bit int:
79
+ 4: {
80
+ getValue: function (dataView, dataOffset, littleEndian) {
81
+ return dataView.getUint32(dataOffset, littleEndian);
82
+ },
83
+ size: 4
84
+ },
85
+ // rational = two long values, first is numerator, second is denominator:
86
+ 5: {
87
+ getValue: function (dataView, dataOffset, littleEndian) {
88
+ return dataView.getUint32(dataOffset, littleEndian) /
89
+ dataView.getUint32(dataOffset + 4, littleEndian);
90
+ },
91
+ size: 8
92
+ },
93
+ // slong, 32 bit signed int:
94
+ 9: {
95
+ getValue: function (dataView, dataOffset, littleEndian) {
96
+ return dataView.getInt32(dataOffset, littleEndian);
97
+ },
98
+ size: 4
99
+ },
100
+ // srational, two slongs, first is numerator, second is denominator:
101
+ 10: {
102
+ getValue: function (dataView, dataOffset, littleEndian) {
103
+ return dataView.getInt32(dataOffset, littleEndian) /
104
+ dataView.getInt32(dataOffset + 4, littleEndian);
105
+ },
106
+ size: 8
107
+ }
108
+ };
109
+ // undefined, 8-bit byte, value depending on field:
110
+ loadImage.exifTagTypes[7] = loadImage.exifTagTypes[1];
111
+
112
+ loadImage.getExifValue = function (dataView, tiffOffset, offset, type, length, littleEndian) {
113
+ var tagType = loadImage.exifTagTypes[type],
114
+ tagSize,
115
+ dataOffset,
116
+ values,
117
+ i,
118
+ str,
119
+ c;
120
+ if (!tagType) {
121
+ console.log('Invalid Exif data: Invalid tag type.');
122
+ return;
123
+ }
124
+ tagSize = tagType.size * length;
125
+ // Determine if the value is contained in the dataOffset bytes,
126
+ // or if the value at the dataOffset is a pointer to the actual data:
127
+ dataOffset = tagSize > 4 ?
128
+ tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
129
+ if (dataOffset + tagSize > dataView.byteLength) {
130
+ console.log('Invalid Exif data: Invalid data offset.');
131
+ return;
132
+ }
133
+ if (length === 1) {
134
+ return tagType.getValue(dataView, dataOffset, littleEndian);
135
+ }
136
+ values = [];
137
+ for (i = 0; i < length; i += 1) {
138
+ values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
139
+ }
140
+ if (tagType.ascii) {
141
+ str = '';
142
+ // Concatenate the chars:
143
+ for (i = 0; i < values.length; i += 1) {
144
+ c = values[i];
145
+ // Ignore the terminating NULL byte(s):
146
+ if (c === '\u0000') {
147
+ break;
148
+ }
149
+ str += c;
150
+ }
151
+ return str;
152
+ }
153
+ return values;
154
+ };
155
+
156
+ loadImage.parseExifTag = function (dataView, tiffOffset, offset, littleEndian, data) {
157
+ var tag = dataView.getUint16(offset, littleEndian);
158
+ data.exif[tag] = loadImage.getExifValue(
159
+ dataView,
160
+ tiffOffset,
161
+ offset,
162
+ dataView.getUint16(offset + 2, littleEndian), // tag type
163
+ dataView.getUint32(offset + 4, littleEndian), // tag length
164
+ littleEndian
165
+ );
166
+ };
167
+
168
+ loadImage.parseExifTags = function (dataView, tiffOffset, dirOffset, littleEndian, data) {
169
+ var tagsNumber,
170
+ dirEndOffset,
171
+ i;
172
+ if (dirOffset + 6 > dataView.byteLength) {
173
+ console.log('Invalid Exif data: Invalid directory offset.');
174
+ return;
175
+ }
176
+ tagsNumber = dataView.getUint16(dirOffset, littleEndian);
177
+ dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
178
+ if (dirEndOffset + 4 > dataView.byteLength) {
179
+ console.log('Invalid Exif data: Invalid directory size.');
180
+ return;
181
+ }
182
+ for (i = 0; i < tagsNumber; i += 1) {
183
+ this.parseExifTag(
184
+ dataView,
185
+ tiffOffset,
186
+ dirOffset + 2 + 12 * i, // tag offset
187
+ littleEndian,
188
+ data
189
+ );
190
+ }
191
+ // Return the offset to the next directory:
192
+ return dataView.getUint32(dirEndOffset, littleEndian);
193
+ };
194
+
195
+ loadImage.parseExifData = function (dataView, offset, length, data, options) {
196
+ if (options.disableExif) {
197
+ return;
198
+ }
199
+ var tiffOffset = offset + 10,
200
+ littleEndian,
201
+ dirOffset,
202
+ thumbnailData;
203
+ // Check for the ASCII code for "Exif" (0x45786966):
204
+ if (dataView.getUint32(offset + 4) !== 0x45786966) {
205
+ // No Exif data, might be XMP data instead
206
+ return;
207
+ }
208
+ if (tiffOffset + 8 > dataView.byteLength) {
209
+ console.log('Invalid Exif data: Invalid segment size.');
210
+ return;
211
+ }
212
+ // Check for the two null bytes:
213
+ if (dataView.getUint16(offset + 8) !== 0x0000) {
214
+ console.log('Invalid Exif data: Missing byte alignment offset.');
215
+ return;
216
+ }
217
+ // Check the byte alignment:
218
+ switch (dataView.getUint16(tiffOffset)) {
219
+ case 0x4949:
220
+ littleEndian = true;
221
+ break;
222
+ case 0x4D4D:
223
+ littleEndian = false;
224
+ break;
225
+ default:
226
+ console.log('Invalid Exif data: Invalid byte alignment marker.');
227
+ return;
228
+ }
229
+ // Check for the TIFF tag marker (0x002A):
230
+ if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
231
+ console.log('Invalid Exif data: Missing TIFF marker.');
232
+ return;
233
+ }
234
+ // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
235
+ dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
236
+ // Create the exif object to store the tags:
237
+ data.exif = new loadImage.ExifMap();
238
+ // Parse the tags of the main image directory and retrieve the
239
+ // offset to the next directory, usually the thumbnail directory:
240
+ dirOffset = loadImage.parseExifTags(
241
+ dataView,
242
+ tiffOffset,
243
+ tiffOffset + dirOffset,
244
+ littleEndian,
245
+ data
246
+ );
247
+ if (dirOffset && !options.disableExifThumbnail) {
248
+ thumbnailData = {exif: {}};
249
+ dirOffset = loadImage.parseExifTags(
250
+ dataView,
251
+ tiffOffset,
252
+ tiffOffset + dirOffset,
253
+ littleEndian,
254
+ thumbnailData
255
+ );
256
+ // Check for JPEG Thumbnail offset:
257
+ if (thumbnailData.exif[0x0201]) {
258
+ data.exif.Thumbnail = loadImage.getExifThumbnail(
259
+ dataView,
260
+ tiffOffset + thumbnailData.exif[0x0201],
261
+ thumbnailData.exif[0x0202] // Thumbnail data length
262
+ );
263
+ }
264
+ }
265
+ // Check for Exif Sub IFD Pointer:
266
+ if (data.exif[0x8769] && !options.disableExifSub) {
267
+ loadImage.parseExifTags(
268
+ dataView,
269
+ tiffOffset,
270
+ tiffOffset + data.exif[0x8769], // directory offset
271
+ littleEndian,
272
+ data
273
+ );
274
+ }
275
+ // Check for GPS Info IFD Pointer:
276
+ if (data.exif[0x8825] && !options.disableExifGps) {
277
+ loadImage.parseExifTags(
278
+ dataView,
279
+ tiffOffset,
280
+ tiffOffset + data.exif[0x8825], // directory offset
281
+ littleEndian,
282
+ data
283
+ );
284
+ }
285
+ };
286
+
287
+ // Registers the Exif parser for the APP1 JPEG meta data segment:
288
+ loadImage.metaDataParsers.jpeg[0xffe1].push(loadImage.parseExifData);
289
+
290
+ // Adds the following properties to the parseMetaData callback data:
291
+ // * exif: The exif tags, parsed by the parseExifData method
292
+
293
+ // Adds the following options to the parseMetaData method:
294
+ // * disableExif: Disables Exif parsing.
295
+ // * disableExifThumbnail: Disables parsing of the Exif Thumbnail.
296
+ // * disableExifSub: Disables parsing of the Exif Sub IFD.
297
+ // * disableExifGps: Disables parsing of the Exif GPS Info IFD.
298
+
299
+ }));