image_genie 0.2.0 → 0.3.0

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.
data/Manifest CHANGED
@@ -1,12 +1,15 @@
1
1
  Manifest
2
+ README
2
3
  README.rdoc
3
4
  Rakefile
5
+ image_genie.gemspec
4
6
  lib/image_genie.rb
5
7
  lib/image_genie/base.rb
6
8
  lib/image_genie/command.rb
7
9
  lib/image_genie/convert.rb
8
10
  lib/image_genie/identify.rb
9
11
  lib/image_genie/montage.rb
12
+ lib/image_genie/test.rb
10
13
  lib/image_genie/verify.rb
11
14
  test/test_helper.rb
12
15
  test/unit/base_test.rb
data/README ADDED
File without changes
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake'
3
3
  require 'echoe'
4
4
  require 'rake/testtask'
5
5
 
6
- Echoe.new('image_genie', '0.2.0') do |p|
6
+ Echoe.new('image_genie', '0.3.0') do |p|
7
7
  p.description = "ImageGenie - Simple Wrapper for command line ImageMagick"
8
8
  p.url = "https://github.com/bkimble"
9
9
  p.author = "Billy Kimble"
data/image_genie.gemspec CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{image_genie}
5
- s.version = "0.2.0"
5
+ s.version = "0.3.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Billy Kimble"]
9
- s.date = %q{2011-02-08}
9
+ s.date = %q{2011-02-09}
10
10
  s.description = %q{ImageGenie - Simple Wrapper for command line ImageMagick}
11
11
  s.email = %q{basslines@gmail.com}
12
- s.extra_rdoc_files = ["README.rdoc", "lib/image_genie.rb", "lib/image_genie/base.rb", "lib/image_genie/command.rb", "lib/image_genie/convert.rb", "lib/image_genie/identify.rb", "lib/image_genie/montage.rb", "lib/image_genie/verify.rb"]
13
- s.files = ["Manifest", "README.rdoc", "Rakefile", "lib/image_genie.rb", "lib/image_genie/base.rb", "lib/image_genie/command.rb", "lib/image_genie/convert.rb", "lib/image_genie/identify.rb", "lib/image_genie/montage.rb", "lib/image_genie/verify.rb", "test/test_helper.rb", "test/unit/base_test.rb", "image_genie.gemspec"]
12
+ s.extra_rdoc_files = ["README", "README.rdoc", "lib/image_genie.rb", "lib/image_genie/base.rb", "lib/image_genie/command.rb", "lib/image_genie/convert.rb", "lib/image_genie/identify.rb", "lib/image_genie/montage.rb", "lib/image_genie/test.rb", "lib/image_genie/verify.rb"]
13
+ s.files = ["Manifest", "README", "README.rdoc", "Rakefile", "image_genie.gemspec", "lib/image_genie.rb", "lib/image_genie/base.rb", "lib/image_genie/command.rb", "lib/image_genie/convert.rb", "lib/image_genie/identify.rb", "lib/image_genie/montage.rb", "lib/image_genie/test.rb", "lib/image_genie/verify.rb", "test/test_helper.rb", "test/unit/base_test.rb"]
14
14
  s.homepage = %q{https://github.com/bkimble}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Image_genie", "--main", "README"]
16
16
  s.require_paths = ["lib"]
data/lib/image_genie.rb CHANGED
@@ -33,7 +33,7 @@ module ImageGenie
33
33
 
34
34
  module ClassMethods
35
35
  # Make helper methods
36
- [:convert,:montage,:identify,:verify].each do |method|
36
+ [:convert,:montage,:identify,:verify,:test].each do |method|
37
37
  define_method(method) do |*splat|
38
38
  module_name = "#{self.name}::#{method.to_s.capitalize}"
39
39
  target = module_name.constantize
@@ -15,7 +15,6 @@ module ImageGenie
15
15
  @paths
16
16
  end
17
17
 
18
- # Eventually I want this method to accept a model that encapsulates its command execution logic.
19
18
  def self.execute(command)
20
19
  logger.info("Executing #{command}")
21
20
  pid, stdin, stdout, stderr = Open4::popen4(command)
@@ -24,7 +23,7 @@ module ImageGenie
24
23
 
25
24
  def self.path_for(program)
26
25
  paths[program.to_sym]
27
- end
26
+ end
28
27
 
29
28
  def self.make_command(command,*args)
30
29
  command.strip!
@@ -39,19 +38,21 @@ module ImageGenie
39
38
  components.compact.join(' ')
40
39
  end
41
40
 
41
+
42
42
  def self.make_args(args)
43
43
  args = [args] if !args.is_a?(Array)
44
44
  return nil if args.empty?
45
45
  args.join(' ')
46
46
  end
47
47
 
48
+
48
49
  # There is probably a better library to handle creation of command line flags,
49
50
  # but this works for now.
50
51
  def self.make_flags(options={})
51
52
  return nil if options.empty?
52
53
  options.collect{|k,v| "-#{k} #{v}"}.join(' ')
53
54
  end
54
-
55
+
55
56
  def self.logger
56
57
  @log ||= TimestampedBufferedLogger.new(Rails.root.join('log','image_genie.log'))
57
58
  end
@@ -1,5 +1,35 @@
1
1
  module ImageGenie
2
2
  class Command < Base
3
+ attr_accessor :stdin,:stdout,:stderr,:pid,:status
4
+ attr_accessor :exception_class,:caller_obj
5
+ attr_accessor :output_buffer
6
+
7
+ def has_error?
8
+ !self.status.zero?
9
+ end
10
+
11
+ def initialize(obj)
12
+ self.output_buffer = ''
13
+ self.caller_obj = obj
14
+ end
15
+
16
+ def execute(command)
17
+ begin
18
+ caller_obj.pid, caller_obj.stdin, caller_obj.stdout, caller_obj.stderr = Open4::popen4(command)
19
+ caller_obj.input if caller_obj.respond_to?(:input)
20
+ caller_obj.output if caller_obj.respond_to?(:output)
21
+ puts "Waiting"
22
+ ignored, status = Process::waitpid2 caller_obj.pid
23
+ self.status = status.exitstatus
24
+ puts "checking for error now"
25
+ caller_obj.error if caller_obj.respond_to?(:error)
26
+ rescue Exception => e
27
+ raise
28
+ ensure
29
+ caller_obj.cleanup if caller_obj.respond_to?(:cleanup)
30
+ end
31
+ end
32
+
3
33
  def self.handle_errors(stderr,status,exception)
4
34
  unless status.exitstatus.zero?
5
35
  errors = stderr.read.strip
@@ -7,5 +37,57 @@ module ImageGenie
7
37
  raise(exception, errors)
8
38
  end
9
39
  end
40
+
41
+ def path_for(program)
42
+ self.class.paths[program.to_sym]
43
+ end
44
+
45
+ def make_command(command,*args)
46
+ command.strip!
47
+ components = [command]
48
+ args.each do |component|
49
+ components << case (component.class.name)
50
+ when 'Hash': make_flags(component)
51
+ when 'Array': make_args(component)
52
+ else " #{component}"
53
+ end
54
+ end
55
+ components.compact.join(' ')
56
+ end
57
+
58
+ def make_args(args)
59
+ args = [args] if !args.is_a?(Array)
60
+ return nil if args.empty?
61
+ args.join(' ')
62
+ end
63
+
64
+ # There is probably a better library to handle creation of command line flags,
65
+ # but this works for now.
66
+ def make_flags(options={})
67
+ return nil if options.empty?
68
+ options.collect{|k,v| "-#{k} #{v}"}.join(' ')
69
+ end
70
+
71
+
72
+ # define generic error/input/output handlers
73
+ def error
74
+ if has_error?
75
+ errors = stderr.read.strip
76
+ logger.error("#{caller_obj.class.name} #{errors}")
77
+ raise(caller_obj.exception_class, errors)
78
+ end
79
+ end
80
+
81
+ def output
82
+ # Generic output processing -- just read it and store it in a buffer. We may want to restrict the amount of data
83
+ # in here via a configuration directive so we don't eat up all of the available system memory.
84
+ while !stdout.eof?
85
+ self.output_buffer += stdout.readline
86
+ end
87
+ end
88
+
10
89
  end
11
- end
90
+ end
91
+
92
+
93
+
@@ -1,33 +1,28 @@
1
1
  module ImageGenie
2
2
  class ConvertError < StandardError; end;
3
3
  class Convert < Command
4
- def self.run(src, options={})
5
- raise(UnableToLocateBinaryError, 'convert') if path_for(:convert).blank?
4
+ attr_accessor :src, :temp_image_file, :options, :src_format
6
5
 
7
- logger.info("#{self.name} Attempting to convert #{src.path}")
8
-
9
- begin
10
- raise Errno::ENOENT,"#{src.path}" unless File.exists?(src.path)
11
- rescue Errno::ENOENT => e
12
- logger.error("#{self.name} #{e.message}")
13
- raise
6
+ def output
7
+ while line = stdout.gets
8
+ temp_image_file.puts line
14
9
  end
10
+ temp_image_file.rewind
11
+ end
15
12
 
16
- format = File.extname(src.path).downcase.gsub(/\.|\?/,'')
17
-
18
- command = "#{path_for(:convert)} #{make_flags(options)} #{format}:#{src.path} #{format}:-"
19
- temp_image_file = Tempfile.new([src.original_filename,".#{format}"])
20
-
21
- execute(command) do |pid,stdin,stdout,stderr|
22
- while line = stdout.gets
23
- temp_image_file.puts line
24
- end
25
- ignored, status = Process::waitpid2 pid
26
- handle_errors(stderr,status,ConvertError)
27
- end
13
+ def initialize(src,options={})
14
+ self.src = src
15
+ self.options = options
16
+ self.src_format = File.extname(src.path).downcase.gsub(/\.|\?/,'')
17
+ logger.info("#{self.class.name} Attempting to convert #{src.path}")
18
+ raise Errno::ENOENT,"#{src.path}" unless File.exists?(src.path)
19
+ self.temp_image_file = Tempfile.new([src.original_filename,".#{src_format}"])
20
+ super(self)
21
+ end
28
22
 
29
- temp_image_file.rewind
30
- return temp_image_file
23
+ def run
24
+ execute("#{path_for(:convert)} #{make_flags(options)} #{src_format}:#{src.path} #{src_format}:-")
25
+ temp_image_file
31
26
  end
32
27
  end
33
28
  end
@@ -2,32 +2,21 @@
2
2
  module ImageGenie
3
3
  class IdentifyError < StandardError; end;
4
4
  class Identify < Command
5
- def self.run(filename, options={})
5
+ attr_accessor :filename
6
+
7
+ def initialize(filename, options={})
8
+ self.exception_class = IdentifyError
6
9
  raise(UnableToLocateBinaryError, 'identify') if path_for(:identify).blank?
7
-
8
- begin
9
- raise Errno::ENOENT,"#{filename}" unless File.exists?(filename)
10
- rescue Errno::ENOENT => e
11
- logger.error("#{self.name} #{e.message}")
12
- raise
13
- end
14
-
10
+ self.filename = filename
11
+ raise Errno::ENOENT,"#{filename}" unless File.exists?(filename)
12
+ super(self)
13
+ end
14
+
15
+ def run
15
16
  command = "#{path_for(:identify)} #{filename}"
16
- output = ''
17
-
18
- # We test for STDERR content
19
- execute(command) do |pid,stdin,stdout,stderr|
20
- while !stdout.eof?
21
- output += stdout.readline
22
- end
23
-
24
- ignored, status = Process::waitpid2 pid
25
- handle_errors(stderr,status,IdentifyError)
26
- end
27
-
17
+ execute(command)
28
18
  fields = [:filename,:format,:dimensions,:geometry,:bit,:image_class,:colors,:filesize,:usertime,:identify_time]
29
- return Hash[fields.zip(stdout.read.split(' '))]
19
+ return Hash[fields.zip(output_buffer.split(' '))]
30
20
  end
31
21
  end
32
- end
33
-
22
+ end
@@ -1,52 +1,41 @@
1
1
  module ImageGenie
2
2
  class MontageError < StandardError; end;
3
3
  class Montage < Command
4
- attr_accessor :filenames,:filename,:options
4
+ attr_accessor :filenames, :options, :temp_image_file, :temp_image_list_file
5
5
 
6
- def initialize(options={})
7
- self.filenames = []
8
- self.options = options
6
+ def output
7
+ while !stdout.eof?
8
+ temp_image_file.puts stdout.readline
9
+ end
10
+ temp_image_file.rewind
11
+ end
12
+
13
+ def cleanup
14
+ logger.info("#{self.class.name} Cleaning up files")
15
+ temp_image_list_file.close
9
16
  end
10
17
 
11
-
12
- def self.run(filenames, options={})
18
+ def initialize(filenames,options={})
19
+ logger.info("#{self.class.name} Attempting to make montage of #{filenames.count} files")
20
+ self.filenames = filenames
21
+ self.exception_class = MontageError
13
22
  raise(UnableToLocateBinaryError, 'montage') if path_for(:montage).blank?
23
+ self.options = options
14
24
  # Montage hates when you attempt to give it files with a path in it, so we
15
25
  # need to change to the system specified temp directory to do our work.
16
26
  Dir.chdir(Dir::tmpdir)
27
+ self.temp_image_file = Tempfile.new(['montage','.jpg'])
28
+ self.temp_image_list_file = Tempfile.new(['montage_image_filenames','.txt'])
17
29
  # Create a temp file that will be all component files of this montage
18
- temp_image_file = Tempfile.new(['montage','.jpg'])
19
- temp_image_list_file = Tempfile.new(['montage_image_filenames','.txt'])
20
30
  temp_image_list_file.puts filenames.join("\n")
21
31
  temp_image_list_file.rewind
32
+ super(self)
33
+ end
22
34
 
23
- logger.info("#{self.name} Attempting to make a montage of #{filenames.size} files")
24
-
35
+ def run
25
36
  command = make_command(path_for(:montage), "@\"#{File.basename(temp_image_list_file.path)}\"", options, "jpeg:-")
26
-
27
- begin
28
- execute(command) do |pid,stdin,stdout,stderr|
29
- while !stdout.eof?
30
- temp_image_file.puts stdout.readline
31
- end
32
- temp_image_file.rewind
33
-
34
- # Still foggy on if we need to wait until we read from STDOUT before waiting, or if
35
- # we wait until we read STDOUT and STDERR.
36
- ignored, status = Process::waitpid2 pid
37
- handle_errors(stderr,status,MontageError)
38
- end
39
- rescue Exception => e
40
- # Close the tempfile before raising
41
- temp_image_file.close
42
- raise
43
- ensure
44
- logger.info("#{self.name} Cleaning up files")
45
- temp_image_list_file.close
46
- end
47
-
37
+ execute(command)
48
38
  return temp_image_file
49
-
50
39
  end
51
40
  end
52
41
  end
@@ -0,0 +1,43 @@
1
+ module ImageGenie
2
+ class TestError < StandardError; end;
3
+ class Test < Command
4
+ attr_accessor :temp_image_file, :temp_image_list_file
5
+
6
+ def input
7
+ end
8
+
9
+ def output
10
+ while !stdout.eof?
11
+ puts stdout.readline
12
+ # self.temp_image_file.puts stdout.readline
13
+ end
14
+ # temp_image_file.rewind
15
+ end
16
+
17
+
18
+ def error
19
+ if has_error?
20
+ errors = stderr.read.strip
21
+ # logger.error("#{self.name} #{errors}")
22
+ raise(exception_class, errors)
23
+ end
24
+ end
25
+
26
+ def initialize(options={})
27
+ self.exception_class = TestError
28
+ # Dir.chdir(Dir::tmpdir)
29
+ # # Create a temp file that will be all component files of this montage
30
+ # self.temp_image_file = Tempfile.new(['montage','.jpg'])
31
+ # self.temp_image_list_file = Tempfile.new(['montage_image_filenames','.txt'])
32
+ end
33
+
34
+ def run
35
+ execute("ls WERIOWEK",self)
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+
42
+
43
+
@@ -4,24 +4,19 @@ module ImageGenie
4
4
  class VerifyError < StandardError; end;
5
5
  class Verify < Command
6
6
 
7
- def self.run(filename, options={})
8
- raise(UnableToLocateBinaryError, 'identify') if path_for(:identify).blank?
9
-
10
- begin
11
- raise Errno::ENOENT,"#{filename}" unless File.exists?(filename)
12
- rescue Errno::ENOENT => e
13
- logger.error("#{self.name} #{e.message}")
14
- raise
15
- end
7
+ attr_accessor :filename
16
8
 
17
- command = "#{path_for(:identify)} #{filename}"
18
- # We test for STDERR content
19
- execute(command) do |pid,stdin,stdout,stderr|
20
- ignored, status = Process::waitpid2 pid
21
- handle_errors(stderr,status,VerifyError)
22
- end
23
-
24
- return true
9
+ def initialize(filename, options={})
10
+ self.exception_class = VerifyError
11
+ raise(UnableToLocateBinaryError, 'identify') if path_for(:identify).blank?
12
+ self.filename = filename
13
+ raise Errno::ENOENT,"#{filename}" unless File.exists?(filename)
14
+ super(self)
25
15
  end
16
+
17
+ def run
18
+ execute("#{path_for(:identify)} #{filename}")
19
+ return true
20
+ end
26
21
  end
27
22
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_genie
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 0
10
- version: 0.2.0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Billy Kimble
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-08 00:00:00 -08:00
18
+ date: 2011-02-09 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -39,6 +39,7 @@ executables: []
39
39
  extensions: []
40
40
 
41
41
  extra_rdoc_files:
42
+ - README
42
43
  - README.rdoc
43
44
  - lib/image_genie.rb
44
45
  - lib/image_genie/base.rb
@@ -46,21 +47,24 @@ extra_rdoc_files:
46
47
  - lib/image_genie/convert.rb
47
48
  - lib/image_genie/identify.rb
48
49
  - lib/image_genie/montage.rb
50
+ - lib/image_genie/test.rb
49
51
  - lib/image_genie/verify.rb
50
52
  files:
51
53
  - Manifest
54
+ - README
52
55
  - README.rdoc
53
56
  - Rakefile
57
+ - image_genie.gemspec
54
58
  - lib/image_genie.rb
55
59
  - lib/image_genie/base.rb
56
60
  - lib/image_genie/command.rb
57
61
  - lib/image_genie/convert.rb
58
62
  - lib/image_genie/identify.rb
59
63
  - lib/image_genie/montage.rb
64
+ - lib/image_genie/test.rb
60
65
  - lib/image_genie/verify.rb
61
66
  - test/test_helper.rb
62
67
  - test/unit/base_test.rb
63
- - image_genie.gemspec
64
68
  has_rdoc: true
65
69
  homepage: https://github.com/bkimble
66
70
  licenses: []