file_data 5.2.3 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 441d9a1d1481ac066af3b8c0bcd2bae00e7b54b88c322ef251a7579ee79f270b
4
- data.tar.gz: af5797dd26aefac7eddee225a81012b7942283bee76e5add1911d67cb5158d4b
3
+ metadata.gz: 4f9ac51b8c0f2d6388b07ab1f6614de4a1fac558c21689fa61d198d70c18a8b4
4
+ data.tar.gz: 4da0fada39336b0346d0846ee6c04a6962c0c4f34909463ded2c0aa2c97511fe
5
5
  SHA512:
6
- metadata.gz: ea6f2869ffa5b4f2a54d5767b7affc853c546e65866d55d6b655a6ddfddb00f732370abeea3e431cc3a951fb8cf4789d155d9321974181b84cefe8619591db3d
7
- data.tar.gz: efb5a79f2b6297ef5b1f85a7acd6f6d33e8b313a47e6c3cfc0b69080819d6fca5d116158341ede91c5e6b3e0a34c7f641fc27f1fd63c08c9bf28ec11f89ce15b
6
+ metadata.gz: 74284cdbc2af387ad6e0b058d25ec38ade9bb5021eaec62be513b923ad6a38398ae199698d1aa78226306e3a60856a1c1658b59fe4d460fe7e600345ef555dba
7
+ data.tar.gz: 3f7a040e99bc6a47da21c759c687f831014ba7e1823f7b63d8e8af2bfb1ab79fb8abbfd5f49059fdb9ad77aa0c0358585f1a935204104597ea580786a46ee6ec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- file_data (5.2.3)
4
+ file_data (6.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -34,7 +34,6 @@ GEM
34
34
  docile (1.1.5)
35
35
  fakefs (0.10.2)
36
36
  ffi (1.9.25)
37
- ffi (1.9.25-x64-mingw32)
38
37
  highline (2.0.0)
39
38
  json (2.6.0)
40
39
  method_source (0.9.0)
data/README.md CHANGED
@@ -8,69 +8,42 @@ file_data
8
8
 
9
9
  Ruby library that reads file metadata.
10
10
 
11
- The api provides a basic usage and an advanced usage. The basic usage will reopen and reparse the file every time it is called which is no problem when reading a single value but can be a performance drain for multiple values. The advanced usage allows the user to grab more than one value without having to read the file more than once.
12
-
13
- ## Basic Usage
11
+ ## Basic Usage for an Exif File
14
12
 
15
13
  ```ruby
16
- filepath = '...' # Path to a jpeg or mpeg4 file
17
-
18
- # Get the date when the file content originated. When a photo was taken, when a movie was recorded, etc
19
- FileData::FileInfo.origin_date(filepath)
20
-
21
- # Get the date when the file was considered to be created. This is usually tied in some way to when the file itself was created on a disk somewhere (not usually as useful as origin date)
22
- FileData::FileInfo.creation_date(filepath)
23
- ```
24
-
25
- ## Advanced Usage
14
+ require 'file_data'
26
15
 
27
- Varies by file format type. Currently there are low level classes for parsing exif and mpeg4 metadata
16
+ ## Step 1: Read in the exif data using either a file path or a stream
28
17
 
29
- ## Exif documentation
18
+ # Using a file path...
19
+ file_path = '/home/user/desktop/my_file.jpg' # Path to an exif file
20
+ exif_data = FileData::Exif.all_data(file_path) # read in all of the exif data from the file path
30
21
 
31
- Exif data is hierarchical and consists of tag/value pairs. The first level is whether or not the tag applies to the image or the image's thumbnail. Next a tag may be one of several sections and within the section it will have a unique numeric value. So given this terminology a unique key for an exif tag would be something like image/section1/123 for a tag that applies to the image in section 1 with a tag id of 123.
32
-
33
- To read exif data a stream of the jpeg data should be used as input. For performance reasons all of the data that is desired should be extracted in a single method from FileData::Exif. All methods will manipulate the stream position after they are called and the user should not count on the stream position being at a specific location after a FileData::Exif method call.
22
+ # Or using a stream...
23
+ exif_data = File.open(file_path, 'rb') do |f|
24
+ FileData::Exif.all_data(f)
25
+ end
34
26
 
35
- Examples:
27
+ ## Step 2: Data is divided into image data and thumbnail data. Pick which you want to work with.
36
28
 
37
- ```ruby
38
- ## Get Exif data from a file path or stream
29
+ # Both objects are hash-like and should respond to all hash method except .length which instead will return the value of :Image_Structure_Length,
30
+ image_data = exif_data.image
31
+ thumbnail_data = exif_data.thumbnail
39
32
 
40
- # The file path or stream is passed as a parameter to class methods on FileData::Exif
41
- # rather than having the file path or stream set in the constructor and the methods
42
- # be instance methods to ensure that the user falls into a "pit of success" by only
43
- # opening the file once to get tag values rather than potentially multiple times
33
+ ## Step 3: Extract the tag values
44
34
 
45
- # Get image exif data from a file path...
46
- hash = FileData::Exif.image_data_only('/path/to/file.jpg')
47
-
48
- # Get thumbnail exif data from a file stream...
49
- File.open('/path/to/file.jpg', 'rb') do |f|
50
- hash = FileData::Exif.thumbnail_data_only(f)
51
- end
35
+ ### Step 3A: Extract tags with a known name (ones that are listed in the "Known Tag Keys" section below)
52
36
 
53
- ## Extract values depending on how much data is returned
37
+ # Convenience methods are added for the names after the last underscore in the known tag names (casing and underscores are ignored in the convenince method names)
54
38
 
55
- # Image and thumbnail data are returned as a hash with keys
56
- # being the full tag name if it exists in FileData::ExifTags (see below listing)
57
- # or "#{ifd_id}-#{tag_id}" if there is no existing name for the tag in FileData::ExifTags
58
- image_hash = FileData::Exif.image_data_only(file_path_or_stream)
59
- image_description_value = image_hash[:Other_ImageDescription]
60
- unknown_gps_tag_value = image_hash["34853-99999"]
39
+ bits_per_sample = image_data.BitsPerSample # Gets :Image_Structure_BitsPerSample from the :Tiff section
40
+ bits_per_sample = image_data.bits_per_sample # Also gets :Image_Structure_BitsPerSample from the :Tiff section
61
41
 
62
- thumbnail_hash = FileData::Exif.thumbnail_data_only(file_path_or_stream)
63
- image_width_tag_value = thumbnail_hash[:Image_Structure_Width]
64
- unknown_gps_tag_value = thumbnail_hash["Tiff-99999"]
42
+ ### Step 3B: Extract tags without a known name (ones NOT listed in the "Known Tag Keys" section below)
65
43
 
66
- all_data = FileData::Exif.all_data(file_path_or_stream)
67
- image_hash = all_data.image
68
- thumbnail_hash = all_data.thumbnail
44
+ # Use the format "#{ifd_id}-#{tag_id}" for the unknown tag to key into the data
45
+ unknown_gps_tag_value = image_data["34853-99999"]
69
46
 
70
- # For extracting only a specific tag the value is returned and the search key must be
71
- # an array matching the keys needed to get traverse FileData:ExifTags (see below listing)
72
- image_description_value = FileData::Exif.only_image_tag(file_path_or_stream, [:Tiff, 270])
73
- unknown_exif_tag_value = FileData::Exif.only_thumbnail_tag(file_path_or_stream, [34665, 2])
74
47
  ```
75
48
 
76
49
  ## Known Tag Keys
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  module FileData
2
4
  # Container for Exif tag values
3
5
  class ExifData
@@ -5,12 +7,52 @@ module FileData
5
7
  SECTIONS.each { |section| define_method(section[1]) { @hash[section[0]] } }
6
8
 
7
9
  def initialize
8
- @hash = SECTIONS.each_with_object({}) { |pair, hash| hash[pair[0]] = {} }
10
+ @hash = SECTIONS.each_with_object({}) { |pair, hash| hash[pair[0]] = ExifHash.new }
9
11
  end
10
12
 
11
13
  def add_tag(index, ifd_id, tag_id, tag_value)
12
- name = ExifTags.get_tag_name(ifd_id, tag_id)
13
- @hash[index][name] = tag_value
14
+ name_info = ExifTags.get_tag_name(ifd_id, tag_id)
15
+ @hash[index][name_info.name] = tag_value
16
+ end
17
+ end
18
+
19
+ # Hash with convenience methods for accessing known Exif tag values by name
20
+ class ExifHash < BasicObject
21
+ all_tags = ExifTags.tag_groups.values.map{|x| x.values}.flatten
22
+ tags_map = all_tags.each_with_object({}) do |tag, hash|
23
+ hash[tag.to_s.split('_').last.upcase] = tag
24
+ end
25
+
26
+ define_method(:method_missing) do |method_name, *args, &block|
27
+ known_name = tags_map[method_name.to_s.tr('_', '').upcase]
28
+
29
+ if known_name.nil?
30
+ @hash.send(method_name, *args, &block)
31
+ else
32
+ @hash[known_name]
33
+ end
34
+ end
35
+
36
+ define_method(:respond_to_missing?) do |method_name, include_private|
37
+ known_name = tags_map[method_name.to_s.tr('_', '').upcase]
38
+
39
+ if known_name.nil?
40
+ @hash.respond_to?(known_name) || super
41
+ else
42
+ true
43
+ end
44
+ end
45
+
46
+ def initialize
47
+ @hash = {}
48
+ end
49
+
50
+ def [](key)
51
+ @hash[key]
52
+ end
53
+
54
+ def []=(key, value)
55
+ @hash[key] = value
14
56
  end
15
57
  end
16
58
  end
@@ -1,11 +1,14 @@
1
1
  module FileData
2
+ TagNameInfo = Struct.new(:name, :is_known);
3
+
2
4
  # Contains tag number to name information taken from the exif spec
3
5
  class ExifTags
4
6
  singleton_class.class_eval { attr_accessor :tag_groups }
5
7
  @tag_groups = {}
6
8
 
7
9
  def self.get_tag_name(ifd_id, tag_id)
8
- get_known_name(ifd_id, tag_id) || "#{ifd_id}-#{tag_id}".to_sym
10
+ known_name = get_known_name(ifd_id, tag_id)
11
+ TagNameInfo.new(known_name || "#{ifd_id}-#{tag_id}".to_sym, known_name != nil)
9
12
  end
10
13
 
11
14
  def self.get_known_name(ifd_id, tag_id)
@@ -1,3 +1,3 @@
1
1
  module FileData
2
- VERSION = '5.2.3'.freeze
2
+ VERSION = '6.0.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: file_data
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.3
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-21 00:00:00.000000000 Z
11
+ date: 2021-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler