gps_extractor 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 33ef2db79a9d06cdf6eca32b2935ad45025cd8dfbffcf643f775474255eaa589
4
+ data.tar.gz: f6c57166e7b36b9db3ec3e797a8877daa90fa8c4b5c5228f33a71daeedc81d64
5
+ SHA512:
6
+ metadata.gz: a4b81d7f134ecab31bd578b8457d9cdfa2ad9cade505833e71f560b361d7062fe281c30ee3aa70efc343748042729051d9ae8a981223e966b10323abfc9135f2
7
+ data.tar.gz: aa239b760f08ff5f09da50861f4558bfbc5fa9c3bc5bd62fe208f40404b75862cc86188043b29738b2acc562d8d9f18bddcd7dc1a6da8dd2c4bf5ab03d95a141
@@ -0,0 +1,78 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'pathname'
4
+ require 'template'
5
+ require 'file_scanner'
6
+
7
+ class Extractor
8
+ def perform(options, args)
9
+ show_throughput('Setting directory', options[:verbose])
10
+ dir = get_directory(args)
11
+
12
+ show_throughput('Create output file', options[:verbose])
13
+ output_file = op_file(dir, options)
14
+
15
+ begin
16
+ show_throughput('Scan Started', options[:verbose])
17
+ FileScanner.new(dir, output_file, options[:verbose]).begin_scan
18
+ rescue SystemCallError => e
19
+ show_error('Unable to scan this directory', e)
20
+ rescue StandardError => e
21
+ show_error('', e)
22
+ end
23
+ show_throughput('Scan Completed', options[:verbose])
24
+
25
+ show_throughput('Finalising O/P File', options[:verbose])
26
+ output_file.close
27
+
28
+ show_throughput('Exit', options[:verbose])
29
+ show_throughput("OutPut Recorded in file: #{output_file.file_name}", true)
30
+ exit
31
+ end
32
+
33
+ def get_directory(args)
34
+ begin
35
+ case args.count
36
+ when 0
37
+ Dir.pwd
38
+ when 1
39
+ File.absolute_path(args.first)
40
+ else
41
+ raise ArgumentError, 'Arguments limit breached'
42
+ end
43
+ rescue ArgumentError => e
44
+ show_error('Unable to set directory', e)
45
+ end
46
+ end
47
+
48
+ def op_file(dir,options)
49
+ begin
50
+ attr_labels = %w[directory file_name latitude longitude]
51
+ dir_name = File.basename(dir)
52
+ if options[:html]
53
+ Template::Html.new(dir_name, attr_labels)
54
+ else
55
+ Template::Csv.new(dir_name, attr_labels)
56
+ end
57
+
58
+ rescue SystemCallError => e
59
+ STDERR.puts 'Unable to initialize the output file'
60
+ STDERR.puts 'Make sure you have write permission to your pwd'
61
+ if options[:html]
62
+ STDERR.puts 'If you have not installed the gem, check your config file'
63
+ end
64
+ STDERR.puts e.message
65
+ exit
66
+ end
67
+ end
68
+
69
+ def show_throughput(msg, verbose)
70
+ puts msg if verbose
71
+ end
72
+
73
+ def show_error(msg, e)
74
+ STDERR.puts msg
75
+ STDERR.puts e.message
76
+ exit
77
+ end
78
+ end
@@ -0,0 +1,46 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'pathname'
4
+ require 'image_reader'
5
+ require 'extractor'
6
+
7
+ class FileScanner
8
+ def initialize(directory, output_file, verbose)
9
+ @directory = Pathname.new(directory)
10
+ @output_file = output_file
11
+ @verbose = verbose
12
+ @allowed_formats = %w{.jpg .jpeg}
13
+ end
14
+
15
+ def begin_scan
16
+ directory_scanning(@directory)
17
+ end
18
+
19
+ private
20
+
21
+ # Recursively scans directory searching for image files
22
+ def directory_scanning(dir)
23
+ Extractor.new.show_throughput("scanning path: #{dir}", @verbose)
24
+
25
+ dir.children.each do |child|
26
+ if child.file? && @allowed_formats.include?(File.extname(child).downcase)
27
+ begin
28
+ @output_file.insert(ImageReader.new(child.to_path).restructure)
29
+ rescue EXIFR::MalformedJPEG => e
30
+ Extractor.new.show_throughput("Unprocessable image: #{child.to_path}", @verbose)
31
+ Extractor.new.show_throughput(e.message, @verbose)
32
+ rescue SystemCallError => e
33
+ Extractor.new.show_throughput("An error occurred while processing image: #{child.to_path}", @verbose)
34
+ raise SystemCallError, "The error received was: #{e}"
35
+ end
36
+ elsif child.directory?
37
+ begin
38
+ directory_scanning(child)
39
+ rescue SystemCallError => e
40
+ Extractor.new.show_throughput("Unable to scan sub directory: #{child.to_path}", @verbose)
41
+ Extractor.new.show_throughput(e.message, @verbose)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+ require "gps_extractor/version"
3
+ require 'optparse'
4
+ require 'extractor'
5
+
6
+ options = {}
7
+ parser = OptionParser.new do |opts|
8
+ opts.on('-html', 'Output HTML file') do
9
+ options[:html] = true
10
+ end
11
+
12
+ opts.on('-v', '--verbose', 'Run verbosely') do |v|
13
+ options[:verbose] = v
14
+ end
15
+ end
16
+
17
+ begin
18
+ parser.parse!
19
+ rescue OptionParser::InvalidOption => e
20
+ STDERR.puts e.message
21
+ STDERR.puts parser
22
+ exit
23
+ end
24
+
25
+ Extractor.new.perform(options, ARGV)
@@ -0,0 +1,3 @@
1
+ module GpsExtractor
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,83 @@
1
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'erb'
4
+ require 'gps_extractor/version'
5
+
6
+ module Template
7
+
8
+
9
+ # handles creating and writing CSV output files
10
+ class Csv
11
+ attr_reader :file_name
12
+
13
+ # dir: basename of root directory
14
+ # attr_labels: array of attributes labels as strings
15
+ def initialize(dir, attr_labels)
16
+ @file_name = "tmp/output/#{dir}_#{Time.now.to_i}.csv"
17
+ @file = File.new(@file_name, 'w')
18
+ @file.puts(attr_labels.join(','))
19
+ end
20
+
21
+ # Writes data row to file
22
+ def insert(img_attrs)
23
+ @file.puts(img_attrs.join(','))
24
+ end
25
+
26
+ def close
27
+ @file.close
28
+ end
29
+ end
30
+
31
+
32
+ # This Class handles creating and writing HTML output files
33
+ class Html
34
+ attr_reader :file_name
35
+
36
+ # dir: basename of root directory
37
+ # attr_labels: array of attributes labels as strings
38
+ def initialize(dir, attr_labels)
39
+ @file_name = "tmp/output/#{dir}_#{Time.now.to_i}.html"
40
+ @file = File.new(@file_name, 'w')
41
+ @template_path = set_template_path
42
+ append_header(dir, attr_labels)
43
+ end
44
+
45
+ # Writes data row to file
46
+ def insert(img_attrs)
47
+ @img_attrs = img_attrs
48
+ row = File.read("#{@template_path}_row.html.erb")
49
+ partial = ERB.new(row, nil, '-').result(binding)
50
+ @file.write(partial)
51
+ end
52
+
53
+ # Writes footer to file and closes it
54
+ def close
55
+ footer = File.read("#{@template_path}_footer.html.erb")
56
+ partial = ERB.new(footer).result(binding)
57
+ @file.write(partial)
58
+ @file.close
59
+ end
60
+
61
+ private
62
+
63
+ # locate path to templates
64
+ def set_template_path
65
+ template_path = 'lib/templates/html/'
66
+ gem_path = "#{Gem.dir}/gems/gps_extractor-#{GpsExtractor::VERSION}/"
67
+ if File.exists?(gem_path)
68
+ return File.join(gem_path, template_path)
69
+ else
70
+ template_path
71
+ end
72
+ end
73
+
74
+ # Writes the header component of the HTML file
75
+ def append_header(dir, attr_labels)
76
+ @title = "Image GPS Scan for: #{dir}"
77
+ @attr_labels = attr_labels
78
+ header = File.read("#{@template_path}_header.html.erb")
79
+ partial = ERB.new(header, nil, '-').result(binding)
80
+ @file.write(partial)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,4 @@
1
+ </tbody>
2
+ </table>
3
+ </body>
4
+ </html>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= @title %></title>
5
+ </head>
6
+ <body>
7
+ <h1><%= @title %></h1>
8
+ <table>
9
+ <thead>
10
+ <tr>
11
+ <%- @attr_labels.each do |label| -%>
12
+ <th><%= label %></th>
13
+ <%- end -%>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
@@ -0,0 +1,5 @@
1
+ <tr>
2
+ <% @img_attrs.each do |attribute| %>
3
+ <td><%= attribute %></td>
4
+ <% end %>
5
+ </tr>
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gps_extractor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Aashish Saini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-12-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: exifr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.3.4
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '1.3'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 1.3.4
75
+ description: "\n A command line application that recursively reads all of the images
76
+ from the supplied directory of images,\n extracts their EXIF GPS data (longitude
77
+ and latitude), and then writes the name of that image and any\n GPS co-ordinates
78
+ it finds to a CSV file.\n\n Results are written to a file in the pwd as the scan
79
+ runs. CSV files will be\n produced by default, use -html for HTML files instead.
80
+ If the app is not\n installed as a gem, HTML output requires configuration.\n
81
+ \ "
82
+ email:
83
+ - aashusaini2684@gmail.com
84
+ executables: []
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - lib/extractor.rb
89
+ - lib/file_scanner.rb
90
+ - lib/gps_extractor.rb
91
+ - lib/gps_extractor/version.rb
92
+ - lib/template.rb
93
+ - lib/templates/html/_footer.html.erb
94
+ - lib/templates/html/_header.html.erb
95
+ - lib/templates/html/_row.html.erb
96
+ homepage: https://github.com/aashishsaini/
97
+ licenses:
98
+ - MIT
99
+ metadata:
100
+ homepage_uri: https://github.com/aashishsaini/
101
+ source_code_uri: https://github.com/aashishsaini/gps_extractor
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.7.6
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: CL app to find JPEGs and extract their GPS coordinates
122
+ test_files: []