qttk 0.1.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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +36 -0
  5. data/README.markdown +131 -0
  6. data/Rakefile +17 -0
  7. data/TODO.markdown +236 -0
  8. data/bin/qt +7 -0
  9. data/etc/gutenprint/gp-tool.rb +56 -0
  10. data/etc/gutenprint/gutenprint-filter.c +400 -0
  11. data/etc/gutenprint/gutenprint.rb +86 -0
  12. data/etc/gutenprint/stp-test +326 -0
  13. data/etc/images/3551599565_db282cf840_o.jpg +0 -0
  14. data/etc/images/4843122063_d582c569e9_o.jpg +0 -0
  15. data/etc/images/4843128953_83c1770907_o.jpg +0 -0
  16. data/lib/quadtone.rb +56 -0
  17. data/lib/quadtone/cgats.rb +137 -0
  18. data/lib/quadtone/cluster_calculator.rb +81 -0
  19. data/lib/quadtone/color.rb +83 -0
  20. data/lib/quadtone/color/cmyk.rb +112 -0
  21. data/lib/quadtone/color/device_n.rb +23 -0
  22. data/lib/quadtone/color/gray.rb +46 -0
  23. data/lib/quadtone/color/lab.rb +150 -0
  24. data/lib/quadtone/color/qtr.rb +71 -0
  25. data/lib/quadtone/color/rgb.rb +71 -0
  26. data/lib/quadtone/color/xyz.rb +80 -0
  27. data/lib/quadtone/curve.rb +138 -0
  28. data/lib/quadtone/curve_set.rb +196 -0
  29. data/lib/quadtone/descendants.rb +9 -0
  30. data/lib/quadtone/environment.rb +5 -0
  31. data/lib/quadtone/extensions/math.rb +11 -0
  32. data/lib/quadtone/extensions/pathname3.rb +11 -0
  33. data/lib/quadtone/printer.rb +106 -0
  34. data/lib/quadtone/profile.rb +217 -0
  35. data/lib/quadtone/quad_file.rb +59 -0
  36. data/lib/quadtone/renderer.rb +139 -0
  37. data/lib/quadtone/run.rb +10 -0
  38. data/lib/quadtone/sample.rb +32 -0
  39. data/lib/quadtone/separator.rb +36 -0
  40. data/lib/quadtone/target.rb +277 -0
  41. data/lib/quadtone/tool.rb +61 -0
  42. data/lib/quadtone/tools/add_printer.rb +73 -0
  43. data/lib/quadtone/tools/characterize.rb +43 -0
  44. data/lib/quadtone/tools/chart.rb +31 -0
  45. data/lib/quadtone/tools/check.rb +16 -0
  46. data/lib/quadtone/tools/dir.rb +15 -0
  47. data/lib/quadtone/tools/edit.rb +23 -0
  48. data/lib/quadtone/tools/init.rb +82 -0
  49. data/lib/quadtone/tools/install.rb +15 -0
  50. data/lib/quadtone/tools/linearize.rb +28 -0
  51. data/lib/quadtone/tools/list.rb +19 -0
  52. data/lib/quadtone/tools/print.rb +38 -0
  53. data/lib/quadtone/tools/printer_options.rb +40 -0
  54. data/lib/quadtone/tools/rename.rb +17 -0
  55. data/lib/quadtone/tools/render.rb +43 -0
  56. data/lib/quadtone/tools/rewrite.rb +15 -0
  57. data/lib/quadtone/tools/separate.rb +71 -0
  58. data/lib/quadtone/tools/show.rb +15 -0
  59. data/lib/quadtone/tools/test.rb +26 -0
  60. data/qttk.gemspec +34 -0
  61. metadata +215 -0
@@ -0,0 +1,61 @@
1
+ module Quadtone
2
+
3
+ class ToolUsageError < Exception; end
4
+
5
+ class Tool
6
+
7
+ attr_accessor :profile
8
+ attr_accessor :verbose
9
+
10
+ def self.process_args(args)
11
+ begin
12
+ name = args.shift or raise ToolUsageError, "No subcommand specified"
13
+ klass_name = 'Quadtone::Tools::' + name.split('-').map { |p| p.capitalize }.join
14
+ begin
15
+ klass = Kernel.const_get(klass_name)
16
+ raise NameError unless klass.respond_to?(:process_args)
17
+ rescue NameError => e
18
+ raise ToolUsageError, "Unknown subcommand specified: #{name.inspect} (#{klass_name})"
19
+ end
20
+ tool = klass.new
21
+ tool.process_environment
22
+ tool.load_profile
23
+ while args.first && args.first[0] == '-'
24
+ option = args.shift
25
+ tool.parse_global_option(option, args) or tool.parse_option(option, args) or raise ToolUsageError, "Unknown option for #{name.inspect} tool: #{option}"
26
+ end
27
+ tool.run(*args)
28
+ rescue ToolUsageError => e
29
+ warn e
30
+ exit 1
31
+ end
32
+ end
33
+
34
+ def process_environment
35
+ if (profile_name = ENV['PROFILE'])
36
+ @profile = Profile.load(profile_name)
37
+ end
38
+ end
39
+
40
+ def parse_global_option(option, args)
41
+ case option
42
+ when '--verbose'
43
+ @verbose = true
44
+ when '--profile'
45
+ @profile = Profile.load(args.shift)
46
+ end
47
+ end
48
+
49
+ def parse_option(option, args)
50
+ # overridden by subclass
51
+ end
52
+
53
+ # subclass can override this to avoid requirement of profile being set
54
+
55
+ def load_profile
56
+ raise ToolUsageError, "No profile set" unless @profile
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,73 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class AddPrinter < Tool
6
+
7
+ def load_profile
8
+ false
9
+ end
10
+
11
+ def run(printer)
12
+
13
+ #FIXME: move this into Printer class
14
+
15
+ unless %x{lpstat -v #{printer} 2>/dev/null}.empty?
16
+ raise ToolUsageError, "Printer #{printer.inspect} already exists"
17
+ end
18
+
19
+ curves_dir = Pathname.new('/Library/Printers/QTR/quadtone') + printer
20
+ cups_data_dir = Pathname.new(%x{cups-config --datadir}.chomp)
21
+ cups_serverbin_dir = Pathname.new(%x{cups-config --serverbin}.chomp)
22
+
23
+ model = printer.split(/[-_=]/).first
24
+ model_ppd = "C/#{model}.ppd.gz"
25
+ ppd_file = cups_data_dir + 'model' + model_ppd
26
+
27
+ raise "QuadToneRIP does not support printer model #{model.inspect}" unless ppd_file.exist?
28
+
29
+ uri = loc = nil
30
+
31
+ File.popen(cups_serverbin_dir + 'backend' + 'usb').readlines.each do |line|
32
+ #FIXME: Too fragile -- use 'lpinfo' to find all printers
33
+ if line =~ /(usb:.*EPSON.*#{Regexp.escape(model.sub(/^Quad/, ''))})/
34
+ uri = $1
35
+ loc = "USB Printer"
36
+ break
37
+ end
38
+ end
39
+
40
+ if uri.nil?
41
+ loop do
42
+ print "Enter IP address of IPP printer, or <return> to cancel: "
43
+ ipp = STDIN.gets.chomp
44
+ if ipp.empty?
45
+ warn "Install cancelled."
46
+ return
47
+ end
48
+ if ipp =~ /^\d+\.\d+\.\d+\.\d+$/
49
+ uri = "lpd://#{ipp}"
50
+ loc = "Network Printer IPP = #{ipp}"
51
+ break
52
+ end
53
+ warn "Invalid IPP number: #{ipp.inspect}"
54
+ end
55
+ end
56
+
57
+ warn "Creating printer #{printer.inspect}"
58
+ system('lpadmin',
59
+ '-p', printer,
60
+ '-E',
61
+ '-m', model_ppd,
62
+ '-L', loc,
63
+ '-v', uri)
64
+ raise "Failed to create printer" unless $? == 0
65
+
66
+ curves_dir.mkpath
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,43 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Characterize < Tool
6
+
7
+ attr_accessor :force
8
+ attr_accessor :remeasure
9
+ attr_accessor :channel
10
+
11
+ def parse_option(option, args)
12
+ case option
13
+ when '--force'
14
+ @force = true
15
+ when '--remeasure'
16
+ @remeasure = args.shift.to_i
17
+ when '--channel'
18
+ @channels = args.shift.split(',').map(&:to_sym)
19
+ end
20
+ end
21
+
22
+ def run(*args)
23
+ case (action = args.shift)
24
+ when 'build'
25
+ @profile.characterization_curveset.build_target
26
+ when 'print'
27
+ @profile.characterization_curveset.print_target
28
+ when 'measure'
29
+ @profile.characterization_curveset.measure_target(force: @force, remeasure: @remeasure, channels: @channels)
30
+ when 'process'
31
+ @profile.characterization_curveset.process_target
32
+ when 'chart'
33
+ @profile.characterization_curveset.chart_target
34
+ else
35
+ raise ToolUsageError, "Unknown action: #{action.inspect}"
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,31 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Chart < Tool
6
+
7
+ attr_accessor :open
8
+ attr_accessor :quick_look
9
+
10
+ def parse_option(option, args)
11
+ case option
12
+ when '--open'
13
+ @open = true
14
+ when '--quicklook'
15
+ @quicklook = true
16
+ end
17
+ end
18
+
19
+ def run
20
+ html_path = @profile.html_path
21
+ html_path.open('w') { |io| io.write(profile.to_html) }
22
+ ;;warn "Saved HTML to #{html_path}"
23
+ system 'open', html_path if @open
24
+ system 'qlmanage', '-p', html_path if @quick_look
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,16 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Check < Tool
6
+
7
+ def run
8
+ @profile.check
9
+ ;;warn "Profile checks out okay."
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Dir < Tool
6
+
7
+ def run
8
+ puts @profile.dir_path
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,23 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Edit < Tool
6
+
7
+ def run
8
+ # editor = ENV['EDITOR'] or raise "Can't determine editor"
9
+ editor = 'subl'
10
+ Quadtone.run(editor,
11
+ '--wait',
12
+ @profile.qtr_profile_path)
13
+ @profile = Profile.load(@profile.qtr_profile_path)
14
+ @profile.check
15
+ @profile.save
16
+ @profile.show
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,82 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Init < Tool
6
+
7
+ def load_profile
8
+ false
9
+ end
10
+
11
+ def run(*args)
12
+ get_printer
13
+ get_printer_options
14
+ get_inks
15
+ get_medium
16
+ profile = Profile.new(printer: @printer, printer_options: @printer_options, inks: @inks, medium: @medium)
17
+ profile.save
18
+ ;;warn "Created profile #{profile.name.inspect}"
19
+ end
20
+
21
+ def get_printer
22
+ printers = CupsPrinter.get_all_printer_names.map { |n| Printer.new(n) }.select(&:quadtone?)
23
+ @printer = prompt('Printer', printers, printers[0]) { |p| p.name }
24
+ end
25
+
26
+ def get_printer_options
27
+ @printer_options = {}
28
+ @printer.options.each do |name, option|
29
+ if Printer::ImportantOptions.include?(name)
30
+ choices = option.choices.map { |c| c.choice }
31
+ default = option.choices.find { |c| c.choice == option.default_choice }
32
+ @printer_options[name] = prompt(name, choices, default)
33
+ end
34
+ end
35
+ end
36
+
37
+ def get_medium
38
+ media = [
39
+ 'Epson Velvet Fine Art',
40
+ 'Epson Ultra Premium Presentation',
41
+ 'Epson Premium Presentation',
42
+ 'Epson Premium Luster',
43
+ 'Hahnemuhle Bamboo',
44
+ 'Southworth Antique Laid',
45
+ 'Crane Museo',
46
+ ]
47
+ @medium = prompt('Media', media, media[0])
48
+ end
49
+
50
+ def get_inks
51
+ @inks = prompt('Inks', @printer.inks, @printer.inks.join(','))
52
+ @inks = [@inks] unless @inks.kind_of?(Array)
53
+ end
54
+
55
+ def prompt(label, values, default=nil, &block)
56
+ choices = {}
57
+ values.each_with_index { |value, i| choices[i + 1] = value }
58
+ STDERR.puts
59
+ STDERR.puts "#{label}:"
60
+ choices.each { |i, value| STDERR.puts '%2d. %s' % [i, block_given? ? yield(value) : value] }
61
+ STDERR.print "Choice" + (default ? " [#{block_given? ? yield(default) : default}]" : '') + "? "
62
+ selections = STDIN.gets.chomp
63
+ if selections.empty?
64
+ default
65
+ else
66
+ selections = selections.split(',').map(&:to_i)
67
+ case selections.length
68
+ when 0
69
+ default
70
+ when 1
71
+ choices[selections.first]
72
+ else
73
+ selections.map { |s| choices[s] }
74
+ end
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,15 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Install < Tool
6
+
7
+ def run
8
+ @profile.install
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,28 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Linearize < Tool
6
+
7
+ def run(*args)
8
+ case (action = args.shift)
9
+ when 'build'
10
+ @profile.linearization_curveset.build_target
11
+ when 'print'
12
+ @profile.linearization_curveset.print_target
13
+ when 'measure'
14
+ @profile.linearization_curveset.measure_target
15
+ when 'process'
16
+ @profile.linearization_curveset.process_target
17
+ when 'chart'
18
+ @profile.linearization_curveset.chart_target
19
+ else
20
+ raise ToolUsageError, "Unknown action: #{action.inspect}"
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,19 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class List < Tool
6
+
7
+ def load_profile
8
+ false
9
+ end
10
+
11
+ def run
12
+ Profile.profile_names.each { |name| puts name }
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,38 @@
1
+ module Quadtone
2
+
3
+ module Tools
4
+
5
+ class Print < Tool
6
+
7
+ attr_accessor :calibrate
8
+ attr_accessor :printer_options
9
+
10
+ def initialize
11
+ super
12
+ @printer_options = {}
13
+ end
14
+
15
+ def parse_option(option, args)
16
+ case option
17
+ when '--calibrate'
18
+ @calibrate = true
19
+ when '--option', '--options'
20
+ @printer_options.merge!(
21
+ Hash[
22
+ args.shift.split(',').map { |o| o.split('=') }
23
+ ]
24
+ )
25
+ end
26
+ end
27
+
28
+ def run(*args)
29
+ args.map { |p| Pathname.new(p) }.each do |image_path|
30
+ @profile.print_file(image_path, calibrate: @calibrate, printer_options: @printer_options)
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end