asset_host_core 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +138 -0
  3. data/Rakefile +11 -0
  4. data/app/assets/images/asset_host_core/alert-overlay.png +0 -0
  5. data/app/assets/images/asset_host_core/arrow-left.gif +0 -0
  6. data/app/assets/images/asset_host_core/arrow-right.gif +0 -0
  7. data/app/assets/images/asset_host_core/fallback-img-rect.png +0 -0
  8. data/app/assets/images/asset_host_core/videoplayer-play.png +0 -0
  9. data/app/assets/images/asset_host_core/x.png +0 -0
  10. data/app/assets/javascripts/asset_host_core/admin/assets.js.coffee +221 -0
  11. data/app/assets/javascripts/asset_host_core/application.js +20 -0
  12. data/app/assets/javascripts/asset_host_core/assetadmin.js.coffee +56 -0
  13. data/app/assets/javascripts/asset_host_core/assethost.js.coffee.erb +17 -0
  14. data/app/assets/javascripts/asset_host_core/browserui.js.coffee +139 -0
  15. data/app/assets/javascripts/asset_host_core/chooserui.js.coffee +381 -0
  16. data/app/assets/javascripts/asset_host_core/client.js.coffee +29 -0
  17. data/app/assets/javascripts/asset_host_core/clients/BrightcoveVideo.js.coffee +64 -0
  18. data/app/assets/javascripts/asset_host_core/clients/templates/brightcove_embed.jst.eco +18 -0
  19. data/app/assets/javascripts/asset_host_core/clients/templates/vimeo_embed.jst.eco +1 -0
  20. data/app/assets/javascripts/asset_host_core/clients/templates/youtube_embed.jst.eco +1 -0
  21. data/app/assets/javascripts/asset_host_core/clients/vimeo_video.js.coffee +21 -0
  22. data/app/assets/javascripts/asset_host_core/clients/youtube_video.js.coffee +21 -0
  23. data/app/assets/javascripts/asset_host_core/cmsplugin.js.coffee +235 -0
  24. data/app/assets/javascripts/asset_host_core/models.js.coffee +586 -0
  25. data/app/assets/javascripts/asset_host_core/railsCMS.js.coffee +141 -0
  26. data/app/assets/javascripts/asset_host_core/slideshow.js.coffee +428 -0
  27. data/app/assets/javascripts/asset_host_core/templates/after_upload_button.jst.eco +3 -0
  28. data/app/assets/javascripts/asset_host_core/templates/asset_drop_asset.jst.eco +4 -0
  29. data/app/assets/javascripts/asset_host_core/templates/asset_modal.jst.eco +13 -0
  30. data/app/assets/javascripts/asset_host_core/templates/asset_preview.jst.eco +35 -0
  31. data/app/assets/javascripts/asset_host_core/templates/asset_search.jst.eco +2 -0
  32. data/app/assets/javascripts/asset_host_core/templates/browser_asset.jst.eco +1 -0
  33. data/app/assets/javascripts/asset_host_core/templates/browser_asset_tip.jst.eco +3 -0
  34. data/app/assets/javascripts/asset_host_core/templates/edit_modal.jst.eco +40 -0
  35. data/app/assets/javascripts/asset_host_core/templates/import_help.jst.eco +59 -0
  36. data/app/assets/javascripts/asset_host_core/templates/pagination_link.jst.eco +1 -0
  37. data/app/assets/javascripts/asset_host_core/templates/pagination_links.jst.eco +13 -0
  38. data/app/assets/javascripts/asset_host_core/templates/queued_file.jst.eco +11 -0
  39. data/app/assets/javascripts/asset_host_core/templates/save_and_close_view.jst.eco +4 -0
  40. data/app/assets/javascripts/asset_host_core/templates/upload_all_button.jst.eco +4 -0
  41. data/app/assets/javascripts/asset_host_core/templates/url_input.jst.eco +8 -0
  42. data/app/assets/stylesheets/asset_host_core/application.css.scss +384 -0
  43. data/app/assets/stylesheets/asset_host_core/jquery-ui.css +105 -0
  44. data/app/assets/stylesheets/asset_host_core/public.css.scss +204 -0
  45. data/app/assets/stylesheets/asset_host_core/slidetest.css.scss +93 -0
  46. data/app/controllers/asset_host_core/admin/api_users_controller.rb +72 -0
  47. data/app/controllers/asset_host_core/admin/assets_controller.rb +140 -0
  48. data/app/controllers/asset_host_core/admin/base_controller.rb +36 -0
  49. data/app/controllers/asset_host_core/admin/home_controller.rb +13 -0
  50. data/app/controllers/asset_host_core/admin/outputs_controller.rb +55 -0
  51. data/app/controllers/asset_host_core/api/assets_controller.rb +110 -0
  52. data/app/controllers/asset_host_core/api/base_controller.rb +43 -0
  53. data/app/controllers/asset_host_core/api/outputs_controller.rb +33 -0
  54. data/app/controllers/asset_host_core/application_controller.rb +43 -0
  55. data/app/controllers/asset_host_core/public_controller.rb +104 -0
  56. data/app/models/asset_host_core/api_user.rb +44 -0
  57. data/app/models/asset_host_core/api_user_permission.rb +6 -0
  58. data/app/models/asset_host_core/asset.rb +265 -0
  59. data/app/models/asset_host_core/asset_output.rb +69 -0
  60. data/app/models/asset_host_core/brightcove_video.rb +20 -0
  61. data/app/models/asset_host_core/output.rb +52 -0
  62. data/app/models/asset_host_core/permission.rb +19 -0
  63. data/app/models/asset_host_core/video.rb +8 -0
  64. data/app/models/asset_host_core/vimeo_video.rb +17 -0
  65. data/app/models/asset_host_core/youtube_video.rb +17 -0
  66. data/app/views/asset_host_core/admin/api_users/_form_fields.html.erb +5 -0
  67. data/app/views/asset_host_core/admin/api_users/edit.html.erb +26 -0
  68. data/app/views/asset_host_core/admin/api_users/index.html.erb +31 -0
  69. data/app/views/asset_host_core/admin/api_users/new.html.erb +17 -0
  70. data/app/views/asset_host_core/admin/api_users/show.html.erb +23 -0
  71. data/app/views/asset_host_core/admin/assets/index.html.erb +19 -0
  72. data/app/views/asset_host_core/admin/assets/metadata.html.erb +24 -0
  73. data/app/views/asset_host_core/admin/assets/show.html.erb +86 -0
  74. data/app/views/asset_host_core/admin/home/chooser.html.erb +49 -0
  75. data/app/views/asset_host_core/admin/outputs/_form_fields.html.erb +5 -0
  76. data/app/views/asset_host_core/admin/outputs/edit.html.erb +26 -0
  77. data/app/views/asset_host_core/admin/outputs/index.html.erb +27 -0
  78. data/app/views/asset_host_core/admin/outputs/new.html.erb +13 -0
  79. data/app/views/asset_host_core/admin/outputs/show.html.erb +17 -0
  80. data/app/views/asset_host_core/shared/_footerjs.html.erb +3 -0
  81. data/app/views/asset_host_core/shared/_navbar.html.erb +28 -0
  82. data/app/views/kaminari/_first_page.html.erb +3 -0
  83. data/app/views/kaminari/_gap.html.erb +3 -0
  84. data/app/views/kaminari/_last_page.html.erb +3 -0
  85. data/app/views/kaminari/_next_page.html.erb +3 -0
  86. data/app/views/kaminari/_page.html.erb +3 -0
  87. data/app/views/kaminari/_paginator.html.erb +17 -0
  88. data/app/views/kaminari/_prev_page.html.erb +3 -0
  89. data/app/views/layouts/asset_host_core/application.html.erb +54 -0
  90. data/app/views/layouts/asset_host_core/full_width.html.erb +32 -0
  91. data/app/views/layouts/asset_host_core/minimal.html.erb +45 -0
  92. data/config/initializers/simple_form.rb +142 -0
  93. data/config/initializers/simple_form_bootstrap.rb +45 -0
  94. data/config/locales/simple_form.en.yml +26 -0
  95. data/config/routes.rb +49 -0
  96. data/lib/asset_host_core.rb +38 -0
  97. data/lib/asset_host_core/config.rb +39 -0
  98. data/lib/asset_host_core/engine.rb +94 -0
  99. data/lib/asset_host_core/loaders.rb +34 -0
  100. data/lib/asset_host_core/loaders/asset_host.rb +30 -0
  101. data/lib/asset_host_core/loaders/base.rb +22 -0
  102. data/lib/asset_host_core/loaders/brightcove.rb +67 -0
  103. data/lib/asset_host_core/loaders/flickr.rb +114 -0
  104. data/lib/asset_host_core/loaders/url.rb +59 -0
  105. data/lib/asset_host_core/loaders/vimeo.rb +76 -0
  106. data/lib/asset_host_core/loaders/youtube.rb +90 -0
  107. data/lib/asset_host_core/model_methods.rb +61 -0
  108. data/lib/asset_host_core/paperclip.rb +4 -0
  109. data/lib/asset_host_core/paperclip/asset_thumbnail.rb +92 -0
  110. data/lib/asset_host_core/paperclip/attachment.rb +206 -0
  111. data/lib/asset_host_core/paperclip/trimmer.rb +33 -0
  112. data/lib/asset_host_core/resque_job.rb +13 -0
  113. data/lib/asset_host_core/version.rb +3 -0
  114. data/lib/tasks/asset_host_core_tasks.rake +4 -0
  115. data/spec/controllers/admin/api_users_controller_spec.rb +21 -0
  116. data/spec/controllers/admin/assets_controller_spec.rb +59 -0
  117. data/spec/controllers/admin/home_controller_spec.rb +4 -0
  118. data/spec/controllers/admin/outputs_controller_spec.rb +4 -0
  119. data/spec/controllers/api/assets_controller_spec.rb +133 -0
  120. data/spec/controllers/api/outputs_controller_spec.rb +51 -0
  121. data/spec/controllers/public_controller_spec.rb +4 -0
  122. data/spec/factories.rb +39 -0
  123. data/spec/features/api_users_spec.rb +78 -0
  124. data/spec/fixtures/api/brightcove/video.json +137 -0
  125. data/spec/fixtures/api/flickr/photos_getInfo.json +78 -0
  126. data/spec/fixtures/api/flickr/photos_getSizes.json +82 -0
  127. data/spec/fixtures/api/flickr/photos_licenses_getInfo.json +52 -0
  128. data/spec/fixtures/api/vimeo/video.json +28 -0
  129. data/spec/fixtures/api/youtube/discovery.json +5190 -0
  130. data/spec/fixtures/api/youtube/video.json +44 -0
  131. data/spec/fixtures/images/chipmunk.jpg +0 -0
  132. data/spec/fixtures/images/dude.jpg +0 -0
  133. data/spec/fixtures/images/ernie.jpg +0 -0
  134. data/spec/fixtures/images/fry.png +0 -0
  135. data/spec/fixtures/images/hat.jpg +0 -0
  136. data/spec/fixtures/images/spongebob.png +0 -0
  137. data/spec/fixtures/images/stars.jpg +0 -0
  138. data/spec/internal/app/controllers/application_controller.rb +16 -0
  139. data/spec/internal/app/controllers/sessions_controller.rb +24 -0
  140. data/spec/internal/app/models/user.rb +10 -0
  141. data/spec/internal/app/views/sessions/new.html.erb +14 -0
  142. data/spec/internal/config/database.yml +3 -0
  143. data/spec/internal/config/initializers/assethost_config.rb +57 -0
  144. data/spec/internal/config/routes.rb +7 -0
  145. data/spec/internal/db/combustion_test.sqlite +0 -0
  146. data/spec/internal/db/schema.rb +106 -0
  147. data/spec/internal/log/test.log +14769 -0
  148. data/spec/internal/public/favicon.ico +0 -0
  149. data/spec/internal/public/images/1_27f7745237849975ca90591c1fba5934_original. +0 -0
  150. data/spec/internal/public/images/1_7d33319deca787d5bb3f62ff06563ad2_original. +0 -0
  151. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original. +0 -0
  152. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.jpg +0 -0
  153. data/spec/internal/public/images/1_b6d48c8b1286104ce76649731e09645f_original.txt +0 -0
  154. data/spec/internal/public/images/1_e179cbd27e07cb55042d0db36cdac095_original. +0 -0
  155. data/spec/internal/public/images/1_e669edd3dfd74be66fc38416e82e3a37_original. +0 -0
  156. data/spec/lib/asset_host_core/loaders/asset_host_spec.rb +33 -0
  157. data/spec/lib/asset_host_core/loaders/brightcove_spec.rb +51 -0
  158. data/spec/lib/asset_host_core/loaders/flickr_spec.rb +72 -0
  159. data/spec/lib/asset_host_core/loaders/url_spec.rb +42 -0
  160. data/spec/lib/asset_host_core/loaders/vimeo_spec.rb +51 -0
  161. data/spec/lib/asset_host_core/loaders/youtube_spec.rb +73 -0
  162. data/spec/lib/asset_host_core/loaders_spec.rb +4 -0
  163. data/spec/lib/asset_host_core/model_methods_spec.rb +4 -0
  164. data/spec/lib/asset_host_core/paperclip/asset_thumbnail_spec.rb +4 -0
  165. data/spec/lib/asset_host_core/paperclip/attachment_spec.rb +4 -0
  166. data/spec/lib/asset_host_core/resque_job_spec.rb +4 -0
  167. data/spec/lib/asset_host_core_spec.rb +4 -0
  168. data/spec/models/api_user_spec.rb +58 -0
  169. data/spec/models/asset_output_spec.rb +4 -0
  170. data/spec/models/asset_spec.rb +4 -0
  171. data/spec/models/output_spec.rb +4 -0
  172. data/spec/models/permission_spec.rb +4 -0
  173. data/spec/spec_helper.rb +30 -0
  174. data/spec/support/fixture_loader.rb +9 -0
  175. data/spec/support/param_helper.rb +14 -0
  176. data/spec/support/permission_matcher.rb +17 -0
  177. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  178. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  179. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  180. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  181. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  182. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  183. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  184. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  185. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  186. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  187. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  188. data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  189. data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  190. data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  191. data/vendor/assets/javascripts/backbone.js +1158 -0
  192. data/vendor/assets/javascripts/backbone.modelbinding.js +475 -0
  193. data/vendor/assets/javascripts/exif.js +695 -0
  194. data/vendor/assets/javascripts/jquery-ui.js +5614 -0
  195. data/vendor/assets/javascripts/simplemodal.js +698 -0
  196. data/vendor/assets/javascripts/spin.jquery.js +81 -0
  197. data/vendor/assets/javascripts/spin.min.js +1 -0
  198. data/vendor/assets/javascripts/underscore.min.js +1 -0
  199. metadata +658 -0
@@ -0,0 +1,695 @@
1
+ /*
2
+ * Javascript EXIF Reader 0.1.4
3
+ * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/
4
+ * Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt]
5
+ */
6
+
7
+
8
+ var EXIF = {};
9
+
10
+ (function() {
11
+
12
+ EXIF.BinaryFile = function(strData, iDataOffset, iDataLength) {
13
+ var data = strData;
14
+ var dataOffset = iDataOffset || 0;
15
+ var dataLength = 0;
16
+
17
+ this.getRawData = function() {
18
+ return data;
19
+ }
20
+
21
+ if (typeof strData == "string") {
22
+ dataLength = iDataLength || data.length;
23
+
24
+ this.getByteAt = function(iOffset) {
25
+ return data.charCodeAt(iOffset + dataOffset) & 0xFF;
26
+ }
27
+ } else if (typeof strData == "unknown") {
28
+ dataLength = iDataLength || IEBinary_getLength(data);
29
+
30
+ this.getByteAt = function(iOffset) {
31
+ return IEBinary_getByteAt(data, iOffset + dataOffset);
32
+ }
33
+ }
34
+
35
+ this.getLength = function() {
36
+ return dataLength;
37
+ }
38
+
39
+ this.getSByteAt = function(iOffset) {
40
+ var iByte = this.getByteAt(iOffset);
41
+ if (iByte > 127)
42
+ return iByte - 256;
43
+ else
44
+ return iByte;
45
+ }
46
+
47
+ this.getShortAt = function(iOffset, bBigEndian) {
48
+ var iShort = bBigEndian ?
49
+ (this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1)
50
+ : (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset)
51
+ if (iShort < 0) iShort += 65536;
52
+ return iShort;
53
+ }
54
+ this.getSShortAt = function(iOffset, bBigEndian) {
55
+ var iUShort = this.getShortAt(iOffset, bBigEndian);
56
+ if (iUShort > 32767)
57
+ return iUShort - 65536;
58
+ else
59
+ return iUShort;
60
+ }
61
+ this.getLongAt = function(iOffset, bBigEndian) {
62
+ var iByte1 = this.getByteAt(iOffset),
63
+ iByte2 = this.getByteAt(iOffset + 1),
64
+ iByte3 = this.getByteAt(iOffset + 2),
65
+ iByte4 = this.getByteAt(iOffset + 3);
66
+
67
+ var iLong = bBigEndian ?
68
+ (((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4
69
+ : (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;
70
+ if (iLong < 0) iLong += 4294967296;
71
+ return iLong;
72
+ }
73
+ this.getSLongAt = function(iOffset, bBigEndian) {
74
+ var iULong = this.getLongAt(iOffset, bBigEndian);
75
+ if (iULong > 2147483647)
76
+ return iULong - 4294967296;
77
+ else
78
+ return iULong;
79
+ }
80
+ this.getStringAt = function(iOffset, iLength) {
81
+ var aStr = [];
82
+ for (var i=iOffset,j=0;i<iOffset+iLength;i++,j++) {
83
+ aStr[j] = String.fromCharCode(this.getByteAt(i));
84
+ }
85
+ return aStr.join("");
86
+ }
87
+
88
+ this.getCharAt = function(iOffset) {
89
+ return String.fromCharCode(this.getByteAt(iOffset));
90
+ }
91
+ this.toBase64 = function() {
92
+ return window.btoa(data);
93
+ }
94
+ this.fromBase64 = function(strBase64) {
95
+ data = window.atob(strBase64);
96
+ }
97
+ }
98
+
99
+ var bDebug = false;
100
+
101
+ EXIF.Tags = {
102
+
103
+ // version tags
104
+ 0x9000 : "ExifVersion", // EXIF version
105
+ 0xA000 : "FlashpixVersion", // Flashpix format version
106
+
107
+ // colorspace tags
108
+ 0xA001 : "ColorSpace", // Color space information tag
109
+
110
+ // image configuration
111
+ 0xA002 : "PixelXDimension", // Valid width of meaningful image
112
+ 0xA003 : "PixelYDimension", // Valid height of meaningful image
113
+ 0x9101 : "ComponentsConfiguration", // Information about channels
114
+ 0x9102 : "CompressedBitsPerPixel", // Compressed bits per pixel
115
+
116
+ // user information
117
+ 0x927C : "MakerNote", // Any desired information written by the manufacturer
118
+ 0x9286 : "UserComment", // Comments by user
119
+
120
+ // related file
121
+ 0xA004 : "RelatedSoundFile", // Name of related sound file
122
+
123
+ // date and time
124
+ 0x9003 : "DateTimeOriginal", // Date and time when the original image was generated
125
+ 0x9004 : "DateTimeDigitized", // Date and time when the image was stored digitally
126
+ 0x9290 : "SubsecTime", // Fractions of seconds for DateTime
127
+ 0x9291 : "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal
128
+ 0x9292 : "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized
129
+
130
+ // picture-taking conditions
131
+ 0x829A : "ExposureTime", // Exposure time (in seconds)
132
+ 0x829D : "FNumber", // F number
133
+ 0x8822 : "ExposureProgram", // Exposure program
134
+ 0x8824 : "SpectralSensitivity", // Spectral sensitivity
135
+ 0x8827 : "ISOSpeedRatings", // ISO speed rating
136
+ 0x8828 : "OECF", // Optoelectric conversion factor
137
+ 0x9201 : "ShutterSpeedValue", // Shutter speed
138
+ 0x9202 : "ApertureValue", // Lens aperture
139
+ 0x9203 : "BrightnessValue", // Value of brightness
140
+ 0x9204 : "ExposureBias", // Exposure bias
141
+ 0x9205 : "MaxApertureValue", // Smallest F number of lens
142
+ 0x9206 : "SubjectDistance", // Distance to subject in meters
143
+ 0x9207 : "MeteringMode", // Metering mode
144
+ 0x9208 : "LightSource", // Kind of light source
145
+ 0x9209 : "Flash", // Flash status
146
+ 0x9214 : "SubjectArea", // Location and area of main subject
147
+ 0x920A : "FocalLength", // Focal length of the lens in mm
148
+ 0xA20B : "FlashEnergy", // Strobe energy in BCPS
149
+ 0xA20C : "SpatialFrequencyResponse", //
150
+ 0xA20E : "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit
151
+ 0xA20F : "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit
152
+ 0xA210 : "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution
153
+ 0xA214 : "SubjectLocation", // Location of subject in image
154
+ 0xA215 : "ExposureIndex", // Exposure index selected on camera
155
+ 0xA217 : "SensingMethod", // Image sensor type
156
+ 0xA300 : "FileSource", // Image source (3 == DSC)
157
+ 0xA301 : "SceneType", // Scene type (1 == directly photographed)
158
+ 0xA302 : "CFAPattern", // Color filter array geometric pattern
159
+ 0xA401 : "CustomRendered", // Special processing
160
+ 0xA402 : "ExposureMode", // Exposure mode
161
+ 0xA403 : "WhiteBalance", // 1 = auto white balance, 2 = manual
162
+ 0xA404 : "DigitalZoomRation", // Digital zoom ratio
163
+ 0xA405 : "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm)
164
+ 0xA406 : "SceneCaptureType", // Type of scene
165
+ 0xA407 : "GainControl", // Degree of overall image gain adjustment
166
+ 0xA408 : "Contrast", // Direction of contrast processing applied by camera
167
+ 0xA409 : "Saturation", // Direction of saturation processing applied by camera
168
+ 0xA40A : "Sharpness", // Direction of sharpness processing applied by camera
169
+ 0xA40B : "DeviceSettingDescription", //
170
+ 0xA40C : "SubjectDistanceRange", // Distance to subject
171
+
172
+ // other tags
173
+ 0xA005 : "InteroperabilityIFDPointer",
174
+ 0xA420 : "ImageUniqueID" // Identifier assigned uniquely to each image
175
+ };
176
+
177
+ EXIF.TiffTags = {
178
+ 0x0100 : "ImageWidth",
179
+ 0x0101 : "ImageHeight",
180
+ 0x8769 : "ExifIFDPointer",
181
+ 0x8825 : "GPSInfoIFDPointer",
182
+ 0xA005 : "InteroperabilityIFDPointer",
183
+ 0x0102 : "BitsPerSample",
184
+ 0x0103 : "Compression",
185
+ 0x0106 : "PhotometricInterpretation",
186
+ 0x0112 : "Orientation",
187
+ 0x0115 : "SamplesPerPixel",
188
+ 0x011C : "PlanarConfiguration",
189
+ 0x0212 : "YCbCrSubSampling",
190
+ 0x0213 : "YCbCrPositioning",
191
+ 0x011A : "XResolution",
192
+ 0x011B : "YResolution",
193
+ 0x0128 : "ResolutionUnit",
194
+ 0x0111 : "StripOffsets",
195
+ 0x0116 : "RowsPerStrip",
196
+ 0x0117 : "StripByteCounts",
197
+ 0x0201 : "JPEGInterchangeFormat",
198
+ 0x0202 : "JPEGInterchangeFormatLength",
199
+ 0x012D : "TransferFunction",
200
+ 0x013E : "WhitePoint",
201
+ 0x013F : "PrimaryChromaticities",
202
+ 0x0211 : "YCbCrCoefficients",
203
+ 0x0214 : "ReferenceBlackWhite",
204
+ 0x0132 : "DateTime",
205
+ 0x010E : "ImageDescription",
206
+ 0x010F : "Make",
207
+ 0x0110 : "Model",
208
+ 0x0131 : "Software",
209
+ 0x013B : "Artist",
210
+ 0x8298 : "Copyright"
211
+ }
212
+
213
+ EXIF.GPSTags = {
214
+ 0x0000 : "GPSVersionID",
215
+ 0x0001 : "GPSLatitudeRef",
216
+ 0x0002 : "GPSLatitude",
217
+ 0x0003 : "GPSLongitudeRef",
218
+ 0x0004 : "GPSLongitude",
219
+ 0x0005 : "GPSAltitudeRef",
220
+ 0x0006 : "GPSAltitude",
221
+ 0x0007 : "GPSTimeStamp",
222
+ 0x0008 : "GPSSatellites",
223
+ 0x0009 : "GPSStatus",
224
+ 0x000A : "GPSMeasureMode",
225
+ 0x000B : "GPSDOP",
226
+ 0x000C : "GPSSpeedRef",
227
+ 0x000D : "GPSSpeed",
228
+ 0x000E : "GPSTrackRef",
229
+ 0x000F : "GPSTrack",
230
+ 0x0010 : "GPSImgDirectionRef",
231
+ 0x0011 : "GPSImgDirection",
232
+ 0x0012 : "GPSMapDatum",
233
+ 0x0013 : "GPSDestLatitudeRef",
234
+ 0x0014 : "GPSDestLatitude",
235
+ 0x0015 : "GPSDestLongitudeRef",
236
+ 0x0016 : "GPSDestLongitude",
237
+ 0x0017 : "GPSDestBearingRef",
238
+ 0x0018 : "GPSDestBearing",
239
+ 0x0019 : "GPSDestDistanceRef",
240
+ 0x001A : "GPSDestDistance",
241
+ 0x001B : "GPSProcessingMethod",
242
+ 0x001C : "GPSAreaInformation",
243
+ 0x001D : "GPSDateStamp",
244
+ 0x001E : "GPSDifferential"
245
+ }
246
+
247
+ EXIF.StringValues = {
248
+ ExposureProgram : {
249
+ 0 : "Not defined",
250
+ 1 : "Manual",
251
+ 2 : "Normal program",
252
+ 3 : "Aperture priority",
253
+ 4 : "Shutter priority",
254
+ 5 : "Creative program",
255
+ 6 : "Action program",
256
+ 7 : "Portrait mode",
257
+ 8 : "Landscape mode"
258
+ },
259
+ MeteringMode : {
260
+ 0 : "Unknown",
261
+ 1 : "Average",
262
+ 2 : "CenterWeightedAverage",
263
+ 3 : "Spot",
264
+ 4 : "MultiSpot",
265
+ 5 : "Pattern",
266
+ 6 : "Partial",
267
+ 255 : "Other"
268
+ },
269
+ LightSource : {
270
+ 0 : "Unknown",
271
+ 1 : "Daylight",
272
+ 2 : "Fluorescent",
273
+ 3 : "Tungsten (incandescent light)",
274
+ 4 : "Flash",
275
+ 9 : "Fine weather",
276
+ 10 : "Cloudy weather",
277
+ 11 : "Shade",
278
+ 12 : "Daylight fluorescent (D 5700 - 7100K)",
279
+ 13 : "Day white fluorescent (N 4600 - 5400K)",
280
+ 14 : "Cool white fluorescent (W 3900 - 4500K)",
281
+ 15 : "White fluorescent (WW 3200 - 3700K)",
282
+ 17 : "Standard light A",
283
+ 18 : "Standard light B",
284
+ 19 : "Standard light C",
285
+ 20 : "D55",
286
+ 21 : "D65",
287
+ 22 : "D75",
288
+ 23 : "D50",
289
+ 24 : "ISO studio tungsten",
290
+ 255 : "Other"
291
+ },
292
+ Flash : {
293
+ 0x0000 : "Flash did not fire",
294
+ 0x0001 : "Flash fired",
295
+ 0x0005 : "Strobe return light not detected",
296
+ 0x0007 : "Strobe return light detected",
297
+ 0x0009 : "Flash fired, compulsory flash mode",
298
+ 0x000D : "Flash fired, compulsory flash mode, return light not detected",
299
+ 0x000F : "Flash fired, compulsory flash mode, return light detected",
300
+ 0x0010 : "Flash did not fire, compulsory flash mode",
301
+ 0x0018 : "Flash did not fire, auto mode",
302
+ 0x0019 : "Flash fired, auto mode",
303
+ 0x001D : "Flash fired, auto mode, return light not detected",
304
+ 0x001F : "Flash fired, auto mode, return light detected",
305
+ 0x0020 : "No flash function",
306
+ 0x0041 : "Flash fired, red-eye reduction mode",
307
+ 0x0045 : "Flash fired, red-eye reduction mode, return light not detected",
308
+ 0x0047 : "Flash fired, red-eye reduction mode, return light detected",
309
+ 0x0049 : "Flash fired, compulsory flash mode, red-eye reduction mode",
310
+ 0x004D : "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",
311
+ 0x004F : "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",
312
+ 0x0059 : "Flash fired, auto mode, red-eye reduction mode",
313
+ 0x005D : "Flash fired, auto mode, return light not detected, red-eye reduction mode",
314
+ 0x005F : "Flash fired, auto mode, return light detected, red-eye reduction mode"
315
+ },
316
+ SensingMethod : {
317
+ 1 : "Not defined",
318
+ 2 : "One-chip color area sensor",
319
+ 3 : "Two-chip color area sensor",
320
+ 4 : "Three-chip color area sensor",
321
+ 5 : "Color sequential area sensor",
322
+ 7 : "Trilinear sensor",
323
+ 8 : "Color sequential linear sensor"
324
+ },
325
+ SceneCaptureType : {
326
+ 0 : "Standard",
327
+ 1 : "Landscape",
328
+ 2 : "Portrait",
329
+ 3 : "Night scene"
330
+ },
331
+ SceneType : {
332
+ 1 : "Directly photographed"
333
+ },
334
+ CustomRendered : {
335
+ 0 : "Normal process",
336
+ 1 : "Custom process"
337
+ },
338
+ WhiteBalance : {
339
+ 0 : "Auto white balance",
340
+ 1 : "Manual white balance"
341
+ },
342
+ GainControl : {
343
+ 0 : "None",
344
+ 1 : "Low gain up",
345
+ 2 : "High gain up",
346
+ 3 : "Low gain down",
347
+ 4 : "High gain down"
348
+ },
349
+ Contrast : {
350
+ 0 : "Normal",
351
+ 1 : "Soft",
352
+ 2 : "Hard"
353
+ },
354
+ Saturation : {
355
+ 0 : "Normal",
356
+ 1 : "Low saturation",
357
+ 2 : "High saturation"
358
+ },
359
+ Sharpness : {
360
+ 0 : "Normal",
361
+ 1 : "Soft",
362
+ 2 : "Hard"
363
+ },
364
+ SubjectDistanceRange : {
365
+ 0 : "Unknown",
366
+ 1 : "Macro",
367
+ 2 : "Close view",
368
+ 3 : "Distant view"
369
+ },
370
+ FileSource : {
371
+ 3 : "DSC"
372
+ },
373
+
374
+ Components : {
375
+ 0 : "",
376
+ 1 : "Y",
377
+ 2 : "Cb",
378
+ 3 : "Cr",
379
+ 4 : "R",
380
+ 5 : "G",
381
+ 6 : "B"
382
+ }
383
+ }
384
+
385
+ function addEvent(oElement, strEvent, fncHandler)
386
+ {
387
+ if (oElement.addEventListener) {
388
+ oElement.addEventListener(strEvent, fncHandler, false);
389
+ } else if (oElement.attachEvent) {
390
+ oElement.attachEvent("on" + strEvent, fncHandler);
391
+ }
392
+ }
393
+
394
+
395
+ function imageHasData(oImg)
396
+ {
397
+ return !!(oImg.exifdata);
398
+ }
399
+
400
+ function getImageData(oImg, fncCallback)
401
+ {
402
+ BinaryAjax(
403
+ oImg.src,
404
+ function(oHTTP) {
405
+ var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse);
406
+ oImg.exifdata = oEXIF || {};
407
+ if (fncCallback) fncCallback();
408
+ }
409
+ )
410
+ }
411
+
412
+ function findEXIFinJPEG(oFile) {
413
+ var aMarkers = [];
414
+
415
+ if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {
416
+ return false; // not a valid jpeg
417
+ }
418
+
419
+ var iOffset = 2;
420
+ var iLength = oFile.getLength();
421
+ while (iOffset < iLength) {
422
+ if (oFile.getByteAt(iOffset) != 0xFF) {
423
+ if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset));
424
+ return false; // not a valid marker, something is wrong
425
+ }
426
+
427
+ var iMarker = oFile.getByteAt(iOffset+1);
428
+
429
+ // we could implement handling for other markers here,
430
+ // but we're only looking for 0xFFE1 for EXIF data
431
+
432
+ if (iMarker == 22400) {
433
+ if (bDebug) console.log("Found 0xFFE1 marker");
434
+ return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
435
+ iOffset += 2 + oFile.getShortAt(iOffset+2, true);
436
+
437
+ } else if (iMarker == 225) {
438
+ // 0xE1 = Application-specific 1 (for EXIF)
439
+ if (bDebug) console.log("Found 0xFFE1 marker");
440
+ return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);
441
+
442
+ } else {
443
+ iOffset += 2 + oFile.getShortAt(iOffset+2, true);
444
+ }
445
+
446
+ }
447
+
448
+ }
449
+
450
+
451
+ function readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd)
452
+ {
453
+ var iEntries = oFile.getShortAt(iDirStart, bBigEnd);
454
+ var oTags = {};
455
+ for (var i=0;i<iEntries;i++) {
456
+ var iEntryOffset = iDirStart + i*12 + 2;
457
+ var strTag = oStrings[oFile.getShortAt(iEntryOffset, bBigEnd)];
458
+ if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd));
459
+ oTags[strTag] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);
460
+ }
461
+ return oTags;
462
+ }
463
+
464
+
465
+ function readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd)
466
+ {
467
+ var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd);
468
+ var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd);
469
+ var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart;
470
+
471
+ switch (iType) {
472
+ case 1: // byte, 8-bit unsigned int
473
+ case 7: // undefined, 8-bit byte, value depending on field
474
+ if (iNumValues == 1) {
475
+ return oFile.getByteAt(iEntryOffset + 8, bBigEnd);
476
+ } else {
477
+ var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
478
+ var aVals = [];
479
+ for (var n=0;n<iNumValues;n++) {
480
+ aVals[n] = oFile.getByteAt(iValOffset + n);
481
+ }
482
+ return aVals;
483
+ }
484
+ break;
485
+
486
+ case 2: // ascii, 8-bit byte
487
+ var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);
488
+ return oFile.getStringAt(iStringOffset, iNumValues-1);
489
+ break;
490
+
491
+ case 3: // short, 16 bit int
492
+ if (iNumValues == 1) {
493
+ return oFile.getShortAt(iEntryOffset + 8, bBigEnd);
494
+ } else {
495
+ var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8);
496
+ var aVals = [];
497
+ for (var n=0;n<iNumValues;n++) {
498
+ aVals[n] = oFile.getShortAt(iValOffset + 2*n, bBigEnd);
499
+ }
500
+ return aVals;
501
+ }
502
+ break;
503
+
504
+ case 4: // long, 32 bit int
505
+ if (iNumValues == 1) {
506
+ return oFile.getLongAt(iEntryOffset + 8, bBigEnd);
507
+ } else {
508
+ var aVals = [];
509
+ for (var n=0;n<iNumValues;n++) {
510
+ aVals[n] = oFile.getLongAt(iValueOffset + 4*n, bBigEnd);
511
+ }
512
+ return aVals;
513
+ }
514
+ break;
515
+ case 5: // rational = two long values, first is numerator, second is denominator
516
+ if (iNumValues == 1) {
517
+ return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd);
518
+ } else {
519
+ var aVals = [];
520
+ for (var n=0;n<iNumValues;n++) {
521
+ aVals[n] = oFile.getLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8*n, bBigEnd);
522
+ }
523
+ return aVals;
524
+ }
525
+ break;
526
+ case 9: // slong, 32 bit signed int
527
+ if (iNumValues == 1) {
528
+ return oFile.getSLongAt(iEntryOffset + 8, bBigEnd);
529
+ } else {
530
+ var aVals = [];
531
+ for (var n=0;n<iNumValues;n++) {
532
+ aVals[n] = oFile.getSLongAt(iValueOffset + 4*n, bBigEnd);
533
+ }
534
+ return aVals;
535
+ }
536
+ break;
537
+ case 10: // signed rational, two slongs, first is numerator, second is denominator
538
+ if (iNumValues == 1) {
539
+ return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd);
540
+ } else {
541
+ var aVals = [];
542
+ for (var n=0;n<iNumValues;n++) {
543
+ aVals[n] = oFile.getSLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8*n, bBigEnd);
544
+ }
545
+ return aVals;
546
+ }
547
+ break;
548
+ }
549
+ }
550
+
551
+
552
+ function readEXIFData(oFile, iStart, iLength)
553
+ {
554
+ if (oFile.getStringAt(iStart, 4) != "Exif") {
555
+ if (bDebug) console.log("Not valid EXIF data! " + oFile.getStringAt(iStart, 4));
556
+ return false;
557
+ }
558
+
559
+ var bBigEnd;
560
+
561
+ var iTIFFOffset = iStart + 6;
562
+
563
+ // test for TIFF validity and endianness
564
+ if (oFile.getShortAt(iTIFFOffset) == 0x4949) {
565
+ bBigEnd = false;
566
+ } else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) {
567
+ bBigEnd = true;
568
+ } else {
569
+ if (bDebug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)");
570
+ return false;
571
+ }
572
+
573
+ if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) {
574
+ if (bDebug) console.log("Not valid TIFF data! (no 0x002A)");
575
+ return false;
576
+ }
577
+
578
+ if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) {
579
+ if (bDebug) console.log("Not valid TIFF data! (First offset not 8)", oFile.getShortAt(iTIFFOffset+4, bBigEnd));
580
+ return false;
581
+ }
582
+
583
+ var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd);
584
+
585
+ if (oTags.ExifIFDPointer) {
586
+ var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd);
587
+ for (var strTag in oEXIFTags) {
588
+ switch (strTag) {
589
+ case "LightSource" :
590
+ case "Flash" :
591
+ case "MeteringMode" :
592
+ case "ExposureProgram" :
593
+ case "SensingMethod" :
594
+ case "SceneCaptureType" :
595
+ case "SceneType" :
596
+ case "CustomRendered" :
597
+ case "WhiteBalance" :
598
+ case "GainControl" :
599
+ case "Contrast" :
600
+ case "Saturation" :
601
+ case "Sharpness" :
602
+ case "SubjectDistanceRange" :
603
+ case "FileSource" :
604
+ oEXIFTags[strTag] = EXIF.StringValues[strTag][oEXIFTags[strTag]];
605
+ break;
606
+
607
+ case "ExifVersion" :
608
+ case "FlashpixVersion" :
609
+ oEXIFTags[strTag] = String.fromCharCode(oEXIFTags[strTag][0], oEXIFTags[strTag][1], oEXIFTags[strTag][2], oEXIFTags[strTag][3]);
610
+ break;
611
+
612
+ case "ComponentsConfiguration" :
613
+ oEXIFTags[strTag] =
614
+ EXIF.StringValues.Components[oEXIFTags[strTag][0]]
615
+ + EXIF.StringValues.Components[oEXIFTags[strTag][1]]
616
+ + EXIF.StringValues.Components[oEXIFTags[strTag][2]]
617
+ + EXIF.StringValues.Components[oEXIFTags[strTag][3]];
618
+ break;
619
+ }
620
+ oTags[strTag] = oEXIFTags[strTag];
621
+ }
622
+ }
623
+
624
+ if (oTags.GPSInfoIFDPointer) {
625
+ var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd);
626
+ for (var strTag in oGPSTags) {
627
+ switch (strTag) {
628
+ case "GPSVersionID" :
629
+ oGPSTags[strTag] = oGPSTags[strTag][0]
630
+ + "." + oGPSTags[strTag][1]
631
+ + "." + oGPSTags[strTag][2]
632
+ + "." + oGPSTags[strTag][3];
633
+ break;
634
+ }
635
+ oTags[strTag] = oGPSTags[strTag];
636
+ }
637
+ }
638
+
639
+ return oTags;
640
+ }
641
+
642
+
643
+ EXIF.getData = function(oImg, fncCallback)
644
+ {
645
+ if (!oImg.complete) return false;
646
+ if (!imageHasData(oImg)) {
647
+ getImageData(oImg, fncCallback);
648
+ } else {
649
+ if (fncCallback) fncCallback();
650
+ }
651
+ return true;
652
+ }
653
+
654
+ EXIF.getTag = function(oImg, strTag)
655
+ {
656
+ if (!imageHasData(oImg)) return;
657
+ return oImg.exifdata[strTag];
658
+ }
659
+
660
+ EXIF.getAllTags = function(oImg)
661
+ {
662
+ if (!imageHasData(oImg)) return {};
663
+ var oData = oImg.exifdata;
664
+ var oAllTags = {};
665
+ for (var a in oData) {
666
+ if (oData.hasOwnProperty(a)) {
667
+ oAllTags[a] = oData[a];
668
+ }
669
+ }
670
+ return oAllTags;
671
+ }
672
+
673
+
674
+ EXIF.pretty = function(oImg)
675
+ {
676
+ if (!imageHasData(oImg)) return "";
677
+ var oData = oImg.exifdata;
678
+ var strPretty = "";
679
+ for (var a in oData) {
680
+ if (oData.hasOwnProperty(a)) {
681
+ if (typeof oData[a] == "object") {
682
+ strPretty += a + " : [" + oData[a].length + " values]\r\n";
683
+ } else {
684
+ strPretty += a + " : " + oData[a] + "\r\n";
685
+ }
686
+ }
687
+ }
688
+ return strPretty;
689
+ }
690
+
691
+ EXIF.readFromBinaryFile = function(oFile) {
692
+ return findEXIFinJPEG(new EXIF.BinaryFile(oFile));
693
+ }
694
+
695
+ })();