ascii_paint 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/data/block_characters/0.txt +5 -0
  3. data/data/block_characters/1.txt +5 -0
  4. data/data/block_characters/2.txt +5 -0
  5. data/data/block_characters/3.txt +5 -0
  6. data/data/block_characters/4.txt +5 -0
  7. data/data/block_characters/5.txt +5 -0
  8. data/data/block_characters/6.txt +5 -0
  9. data/data/block_characters/7.txt +5 -0
  10. data/data/block_characters/8.txt +5 -0
  11. data/data/block_characters/9.txt +5 -0
  12. data/data/block_characters/A.txt +5 -0
  13. data/data/block_characters/B.txt +5 -0
  14. data/data/block_characters/C.txt +5 -0
  15. data/data/block_characters/D.txt +5 -0
  16. data/data/block_characters/E.txt +5 -0
  17. data/data/block_characters/F.txt +5 -0
  18. data/data/block_characters/G.txt +5 -0
  19. data/data/block_characters/H.txt +5 -0
  20. data/data/block_characters/I.txt +5 -0
  21. data/data/block_characters/J.txt +5 -0
  22. data/data/block_characters/K.txt +5 -0
  23. data/data/block_characters/L.txt +5 -0
  24. data/data/block_characters/M.txt +5 -0
  25. data/data/block_characters/N.txt +5 -0
  26. data/data/block_characters/O.txt +5 -0
  27. data/data/block_characters/P.txt +5 -0
  28. data/data/block_characters/Q.txt +5 -0
  29. data/data/block_characters/R.txt +5 -0
  30. data/data/block_characters/S.txt +5 -0
  31. data/data/block_characters/T.txt +5 -0
  32. data/data/block_characters/U.txt +5 -0
  33. data/data/block_characters/V.txt +5 -0
  34. data/data/block_characters/W.txt +5 -0
  35. data/data/block_characters/X.txt +5 -0
  36. data/data/block_characters/Y.txt +5 -0
  37. data/data/block_characters/Z.txt +5 -0
  38. data/lib/ascii_paint.rb +113 -0
  39. data/lib/ascii_paint/block_character.rb +85 -0
  40. data/lib/ascii_paint/block_string.rb +49 -0
  41. data/lib/ascii_paint/config.rb +197 -0
  42. data/lib/ascii_paint/version.rb +3 -0
  43. data/spec/ascii_paint_spec.rb +108 -0
  44. data/spec/block_string_spec.rb +75 -0
  45. data/spec/fixtures/ascii.txt +2 -0
  46. data/spec/spec_helper.rb +54 -0
  47. metadata +135 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: 07fb319a0666e394fce07cca879a6d3c16cf81c9
4
+ data.tar.gz: 07e594e70ac58ebd656b72dabcbda59f2ae3e03b
5
+ !binary "U0hBNTEy":
6
+ metadata.gz: 5e952740658a8fec7f020877d6d2e66e5bdf4bd5d370a2cd2ce507fa4b3f97179b093bf24894e509a2206377614a384c3488f34e4b98e866ca2a0e53fbb3eb76
7
+ data.tar.gz: 4bef3c9a2cc135a6646c7ce6abd52fdee20cb568828b68ffee032f6ebb6ec4b28f71af91665c81e55b7f04b3b439e2b39b8cd61a003c529a3f4b20cd34bad8a0
@@ -0,0 +1,5 @@
1
+ 000
2
+ 0 00
3
+ 0 0 0
4
+ 00 0
5
+ 000
@@ -0,0 +1,5 @@
1
+ 11
2
+ 1
3
+ 1
4
+ 1
5
+ 1
@@ -0,0 +1,5 @@
1
+ 222
2
+ 2 2
3
+ 2
4
+ 22
5
+ 22222
@@ -0,0 +1,5 @@
1
+ 3333
2
+ 3
3
+ 33
4
+ 3
5
+ 3333
@@ -0,0 +1,5 @@
1
+ 4 4
2
+ 4 4
3
+ 44444
4
+ 4
5
+ 4
@@ -0,0 +1,5 @@
1
+ 55555
2
+ 5
3
+ 5555
4
+ 5
5
+ 5555
@@ -0,0 +1,5 @@
1
+ 66666
2
+ 6
3
+ 66666
4
+ 6 6
5
+ 66666
@@ -0,0 +1,5 @@
1
+ 77777
2
+ 7
3
+ 7
4
+ 7
5
+ 7
@@ -0,0 +1,5 @@
1
+ 888
2
+ 8 8
3
+ 888
4
+ 8 8
5
+ 888
@@ -0,0 +1,5 @@
1
+ 99999
2
+ 9 9
3
+ 99999
4
+ 9
5
+ 9
@@ -0,0 +1,5 @@
1
+ AAAAA
2
+ A A
3
+ AAAAA
4
+ A A
5
+ A A
@@ -0,0 +1,5 @@
1
+ BBBB
2
+ B B
3
+ BBBB
4
+ B B
5
+ BBBB
@@ -0,0 +1,5 @@
1
+ CCCC
2
+ C
3
+ C
4
+ C
5
+ CCCC
@@ -0,0 +1,5 @@
1
+ DDDD
2
+ D D
3
+ D D
4
+ D D
5
+ DDDD
@@ -0,0 +1,5 @@
1
+ EEEEE
2
+ E
3
+ EEEE
4
+ E
5
+ EEEEE
@@ -0,0 +1,5 @@
1
+ FFFFF
2
+ F
3
+ FFFF
4
+ F
5
+ F
@@ -0,0 +1,5 @@
1
+ GGGGG
2
+ G
3
+ G GGG
4
+ G G
5
+ GGGGG
@@ -0,0 +1,5 @@
1
+ H H
2
+ H H
3
+ HHHHH
4
+ H H
5
+ H H
@@ -0,0 +1,5 @@
1
+ IIIII
2
+ I
3
+ I
4
+ I
5
+ IIIII
@@ -0,0 +1,5 @@
1
+ JJJJJ
2
+ J
3
+ J
4
+ J J
5
+ JJJJ
@@ -0,0 +1,5 @@
1
+ K K
2
+ K K
3
+ KKK
4
+ K K
5
+ K K
@@ -0,0 +1,5 @@
1
+ L
2
+ L
3
+ L
4
+ L
5
+ LLLLL
@@ -0,0 +1,5 @@
1
+ MMMMM
2
+ M M M
3
+ M M M
4
+ M M
5
+ M M
@@ -0,0 +1,5 @@
1
+ N N
2
+ NN N
3
+ N N N
4
+ N NN
5
+ N N
@@ -0,0 +1,5 @@
1
+ OOOOO
2
+ O O
3
+ O O
4
+ O O
5
+ OOOOO
@@ -0,0 +1,5 @@
1
+ PPPPP
2
+ P P
3
+ PPPPP
4
+ P
5
+ P
@@ -0,0 +1,5 @@
1
+ QQQQ
2
+ Q Q
3
+ Q Q
4
+ QQQQ
5
+ QQQ
@@ -0,0 +1,5 @@
1
+ RRRR
2
+ R R
3
+ RRRR
4
+ R R
5
+ R R
@@ -0,0 +1,5 @@
1
+ SSSS
2
+ S
3
+ SSS
4
+ S
5
+ SSSS
@@ -0,0 +1,5 @@
1
+ TTTTT
2
+ T
3
+ T
4
+ T
5
+ T
@@ -0,0 +1,5 @@
1
+ U U
2
+ U U
3
+ U U
4
+ U U
5
+ UUU
@@ -0,0 +1,5 @@
1
+ V V
2
+ V V
3
+ V V
4
+ V V
5
+ V
@@ -0,0 +1,5 @@
1
+ W W
2
+ W W
3
+ W W W
4
+ W W W
5
+ W W
@@ -0,0 +1,5 @@
1
+ X X
2
+ X X
3
+ X
4
+ X X
5
+ X X
@@ -0,0 +1,5 @@
1
+ Y Y
2
+ Y Y
3
+ YYY
4
+ Y
5
+ Y
@@ -0,0 +1,5 @@
1
+ ZZZZZ
2
+ Z
3
+ Z
4
+ Z
5
+ ZZZZZ
@@ -0,0 +1,113 @@
1
+ require 'bundler/setup'
2
+ require 'chunky_png'
3
+
4
+ module AsciiPaint
5
+
6
+ # Exception raised when ASCII paint encounters a character without a paint
7
+ # color specified.
8
+ class CharacterNotFound < Exception; end
9
+
10
+ # Paints a PNG based on the given ASCII art.
11
+ #
12
+ # Example:
13
+ # text = "
14
+ # !!!!! @@@@@ $$$$$ %%%%% ^^^^^ @@@@@ $$$$$ %%%%% ^ ^ !!!!!
15
+ # ! ! @ $ % ^ @ @ $ $ % ^^ ^ !
16
+ # !!!!! @@@@@ $ % ^ @@@@@ $$$$$ % ^ ^ ^ !
17
+ # ! ! @ $ % ^ @ $ $ % ^ ^^ !
18
+ # ! ! @@@@@ $$$$$ %%%%% ^^^^^ !!!!! @ $ $ %%%%% ^ ^ !
19
+ # "
20
+ #
21
+ # AsciiPaint.paint(text, 'out.png')
22
+ #
23
+ # @param ascii_art [#to_s, Array<String>]
24
+ # multiline string, string array or filename with the ASCII art to paint
25
+ # @param out_filename [#to_s]
26
+ # the name of the painted PNG file
27
+ # @param conf [Hash<Symbol, value>]
28
+ # configuration settings. Keys should be the names of attributes of
29
+ # {AsciiPaint::Config}, such as +:character_height+.
30
+ # @return [String]
31
+ # the name of the painted PNG file
32
+ def self.paint(ascii_art, out_filename, configuration = {})
33
+ global_configuration = self.config
34
+ local_configuration = global_configuration.dup.set_options(configuration)
35
+
36
+ ascii_array = ascii_art_to_array(ascii_art)
37
+ image = ascii_to_image(ascii_array, local_configuration)
38
+ save_image(image, out_filename, local_configuration)
39
+
40
+ if block_given?
41
+ begin
42
+ yield out_filename
43
+ ensure
44
+ FileUtils.rm(out_filename)
45
+ end
46
+
47
+ true
48
+ else
49
+ out_filename
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def self.ascii_art_to_array(ascii_art)
56
+ return ascii_art if ascii_art.is_a? Array
57
+
58
+ ascii_art = ascii_art.to_s.split("\n")
59
+ if ascii_art.size == 1
60
+ ascii_art = File.open(ascii_art[0], 'r').to_a.map(&:chomp)
61
+ end
62
+ ascii_art
63
+ end
64
+
65
+ def self.ascii_to_image(ascii_array, configuration)
66
+ colors_grid = ascii_to_colors(ascii_array, configuration)
67
+ image = blank_image(ascii_array, configuration)
68
+ painted_image(image, colors_grid, configuration)
69
+ end
70
+
71
+ def self.blank_image(lines, configuration)
72
+ height = lines.size
73
+ width = lines.map(&:size).max
74
+
75
+ width_pixels, height_pixels = configuration.characters_to_pixels(width, height)
76
+ png = ChunkyPNG::Image.new(width_pixels, height_pixels, configuration.color_map[' '])
77
+ end
78
+
79
+ def self.ascii_to_colors(strings, configuration)
80
+ strings.map do |line|
81
+ line.chars.map do |char|
82
+ color = configuration.color_map[char]
83
+ raise AsciiPaint::CharacterNotFound.new "Couldn't find a color mapping for character: #{char}" unless color
84
+ color
85
+ end
86
+ end
87
+ end
88
+
89
+ def self.painted_image(image, color_grid, configuration)
90
+ color_grid.each_with_index do |row, y|
91
+ row.each_with_index do |color, x|
92
+ x_pixels, y_pixels = configuration.characters_to_pixels(x, y)
93
+ width_pixels, height_pixels = configuration.characters_to_pixels(1, 1)
94
+ image.rect(x_pixels, y_pixels, x_pixels + width_pixels, y_pixels + height_pixels, configuration.border_color, color)
95
+ end
96
+ end
97
+
98
+ image
99
+ end
100
+
101
+ def self.save_image(image, filename, _)
102
+ image.save(filename, :interlace => true)
103
+ end
104
+
105
+ def self.root
106
+ Pathname.new(__FILE__).parent.parent
107
+ end
108
+ end
109
+
110
+ require_relative 'ascii_paint/block_character.rb'
111
+ require_relative 'ascii_paint/block_string.rb'
112
+ require_relative 'ascii_paint/config.rb'
113
+ require_relative 'ascii_paint/version.rb'
@@ -0,0 +1,85 @@
1
+ module AsciiPaint
2
+ class BlockCharacter
3
+ attr_reader :ascii
4
+
5
+ # TODO: make customizable
6
+ UNPADDED_HEIGHT = 5
7
+ UNPADDED_WIDTH = 5
8
+ VERTICAL_PADDING = 2
9
+ HORIZONTAL_PADDING = 2
10
+
11
+ def initialize(character)
12
+ raise "Only single characters please! #{character}" unless character.size == 1
13
+
14
+ if character == "\n"
15
+ @newline = true
16
+ return
17
+ end
18
+
19
+ load_ascii(character)
20
+ end
21
+
22
+ def newline?
23
+ !!@newline
24
+ end
25
+
26
+ def to_s
27
+ ascii.join("\n")
28
+ end
29
+
30
+ def self.height
31
+ UNPADDED_HEIGHT + VERTICAL_PADDING
32
+ end
33
+
34
+ def self.width
35
+ UNPADDED_WIDTH + HORIZONTAL_PADDING
36
+ end
37
+
38
+ def self.left_padding
39
+ HORIZONTAL_PADDING / 2
40
+ end
41
+
42
+ def self.right_padding
43
+ (HORIZONTAL_PADDING + 1) / 2
44
+ end
45
+
46
+ def self.top_padding
47
+ VERTICAL_PADDING / 2
48
+ end
49
+
50
+ def self.bottom_padding
51
+ (VERTICAL_PADDING + 1) / 2
52
+ end
53
+
54
+ private
55
+
56
+ # TODO: filename escaping
57
+ def load_ascii(character)
58
+ path = block_characters_dir.join("#{character}.txt")
59
+ if File.exists? path
60
+ @ascii = File.open(path, 'r').to_a.map(&:chomp)
61
+ @ascii = pad_ascii(@ascii)
62
+ else
63
+ raise "Character not supported: #{character}"
64
+ end
65
+ end
66
+
67
+ def pad_ascii(ascii)
68
+ left = " " * self.class.left_padding
69
+ right = " " * self.class.right_padding
70
+ padded = ascii.map do |row|
71
+ "#{left}#{row}#{right}"
72
+ end
73
+
74
+ blank_row = " " * self.class.width
75
+ self.class.top_padding.times { padded.unshift(blank_row) }
76
+ self.class.bottom_padding.times { padded.push(blank_row) }
77
+
78
+ padded
79
+ end
80
+
81
+ def block_characters_dir
82
+ AsciiPaint.root.join('data', 'block_characters')
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,49 @@
1
+ module AsciiPaint
2
+ class BlockString
3
+ attr_reader :block_characters
4
+
5
+ def initialize(string)
6
+ @block_characters = string.chars.map { |char| BlockCharacter.new(char) }
7
+ end
8
+
9
+ def each_row
10
+ return to_enum(:each_row) unless block_given?
11
+
12
+ rows =
13
+ block_characters.chunk do |block_char|
14
+ if block_char.newline?
15
+ nil
16
+ else
17
+ :not_newline
18
+ end
19
+ end.map do |symbol, row|
20
+ row
21
+ end
22
+
23
+ rows.each do |row|
24
+ yield row
25
+ end
26
+ end
27
+
28
+ def to_a
29
+ each_row.flat_map do |block_row|
30
+ (0...BlockCharacter.height).map do |h|
31
+ block_row.inject('') do |string_row, block_char|
32
+ string_row + block_char.ascii[h]
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ module AsciiPaint
41
+ # TODO: support filename arguments
42
+ # TODO: write tests
43
+ # TODO: write docs
44
+ def self.block_paint(block_string, out_filename, conf = {}, &block)
45
+ block_string = block_string.join("\n") if block_string.respond_to? :join
46
+ ascii_art = BlockString.new(block_string).to_a
47
+ paint(ascii_art, out_filename, conf, &block)
48
+ end
49
+ end
@@ -0,0 +1,197 @@
1
+ # An instance of class +AsciiPaint::Config+ is used to set global configuration
2
+ # options for ASCII paint. Pass a block to {AsciiPaint.config} to access this
3
+ # object.
4
+
5
+ module AsciiPaint
6
+ class Config
7
+
8
+ TRANSPARENT = ChunkyPNG::Color::TRANSPARENT
9
+ SPECIAL_SYMBOL_MAP = {
10
+ transparent: TRANSPARENT
11
+ }
12
+ private_constant :TRANSPARENT, :SPECIAL_SYMBOL_MAP
13
+
14
+ # The horizontal size in pixels of the rectangle that replaces a single
15
+ # character during painting.
16
+ attr_accessor :character_width
17
+
18
+ # The vertical size in pixels of the rectangle that replaces a single
19
+ # character during painting.
20
+ attr_accessor :character_height
21
+
22
+ attr_accessor :color_map
23
+
24
+ def initialize(settings = {})
25
+ reset!
26
+ set_options(settings)
27
+ end
28
+
29
+ class << self
30
+ alias_method :default, :new
31
+ end
32
+
33
+ # Merge new mappings into the color map.
34
+ #
35
+ # The color map specifies which color paints over each character. For example,
36
+ # config.color_map = { 'a' => :blue }
37
+ # tells ASCII paint to replace the character 'a' with the color blue.
38
+ #
39
+ # @param hash [Hash<String, Symbol>]
40
+ # the new mappings to be merged into the color map.
41
+ # @return [void]
42
+ def color_map=(hash)
43
+ replace_special_symbols!(hash)
44
+ @color_map = color_map.merge(hash)
45
+ end
46
+
47
+ # Set the color to paint over characters whose color hasn't been defined by
48
+ # the color map.
49
+ #
50
+ # @param default_color [Symbol]
51
+ # the default color to replace characters without a specified color.
52
+ # @return [void]
53
+ def color_for_undefined_character=(default_color)
54
+ color_map.default = replacement_for_special_symbol(default_color)
55
+ end
56
+
57
+ def characters_to_pixels(x, y)
58
+ [x * character_width, y * character_height]
59
+ end
60
+
61
+ # Set configuration options using a hash instead of using method calls. For
62
+ # example,
63
+ # config.set_options({character_width: 10})
64
+ # is equivalent to
65
+ # config.character_width = 10
66
+ #
67
+ # @param options [Hash<Symbol, value>]
68
+ # settings mapping from attribute name to value.
69
+ # @return self
70
+ def set_options(options)
71
+ options.each do |key, value|
72
+ mutator_name = "#{key}="
73
+ self.send(mutator_name, value)
74
+ end
75
+ self
76
+ end
77
+
78
+ def border_color
79
+ TRANSPARENT
80
+ end
81
+
82
+ def reset!
83
+ @character_height = Default::CHARACTER_HEIGHT
84
+ @character_width = Default::CHARACTER_WIDTH
85
+ @color_map =
86
+ begin
87
+ map = Default::COLOR_MAP.dup
88
+ map.default = Default::COLOR_FOR_UNDEFINED_CHARACTER
89
+ replace_special_symbols!(map)
90
+ map
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def replace_special_symbols!(hash)
97
+ hash.each do |char, color_sym|
98
+ hash[char] = replacement_for_special_symbol(color_sym)
99
+ end
100
+ end
101
+
102
+ def replacement_for_special_symbol(symbol)
103
+ SPECIAL_SYMBOL_MAP[symbol] || symbol
104
+ end
105
+
106
+ public
107
+
108
+ # Default values for configuration settings.
109
+ module Default
110
+ private
111
+
112
+ def self.rainbow_mapping(characters)
113
+ # Thanks jbum (http://krazydad.com/tutorials/makecolors.php)
114
+ hash = {}
115
+ period = Math::PI * 2
116
+ frequency = period / characters.count
117
+ characters.each_with_index do |char, index|
118
+ r = Math.cos(frequency * index + 0) * 127 + 128;
119
+ g = Math.cos(frequency * index + period / 3) * 127 + 128;
120
+ b = Math.cos(frequency * index + period * 2 / 3) * 127 + 128;
121
+ color = ChunkyPNG::Color.rgb(r.to_i, g.to_i, b.to_i)
122
+ hash[char] = color
123
+ end
124
+ hash
125
+ end
126
+
127
+ public
128
+
129
+ CHARACTER_HEIGHT = 16
130
+ CHARACTER_WIDTH = 8
131
+ COLOR_FOR_UNDEFINED_CHARACTER = :black
132
+ COLOR_MAP =
133
+ begin
134
+ map = {
135
+ ' ' => :transparent,
136
+
137
+ '!' => :red,
138
+ '@' => :orange,
139
+ '#' => :yellow,
140
+ '$' => :green,
141
+ '%' => :blue,
142
+ '^' => :purple,
143
+
144
+ '_' => :white,
145
+ '~' => :black,
146
+
147
+ '<' => :lightgrey,
148
+ '>' => :grey,
149
+ '?' => :darkgrey,
150
+ ',' => :lightslategrey,
151
+ '.' => :slategrey,
152
+ '/' => :darkslategrey,
153
+ '\\' => :dimgrey,
154
+
155
+ ':' => :chocolate,
156
+ ';' => :blanchedalmond,
157
+ '\'' => :coral,
158
+ '"' => :deepskyblue,
159
+ '{' => :indigo,
160
+ '}' => :ivory,
161
+ '[' => :khaki,
162
+ ']' => :lavender,
163
+ '|' => :hotpink,
164
+ '&' => :darksalmon,
165
+ '*' => :lime,
166
+ '(' => :lightyellow,
167
+ ')' => :honeydew,
168
+ '-' => :azure,
169
+ '+' => :crimson,
170
+ '=' => :antiquewhite,
171
+ '`' => :cornsilk
172
+ }
173
+
174
+ letters = ('a'..'z').zip('A'..'Z').flatten # ['a', 'A', 'b', 'B', ...]
175
+ map.merge! rainbow_mapping(letters)
176
+
177
+ numbers = ('0'..'9')
178
+ map.merge! rainbow_mapping(numbers)
179
+
180
+ map
181
+ end
182
+ end
183
+
184
+ end
185
+ end
186
+
187
+ module AsciiPaint
188
+ # Passes an instance of {AsciiPaint::Config} to the given block. Used to set
189
+ # global configuration.
190
+ #
191
+ # @return [Config] the global configuration
192
+ def self.config
193
+ @configuration ||= Config.default
194
+ yield(@configuration) if block_given?
195
+ @configuration
196
+ end
197
+ end
@@ -0,0 +1,3 @@
1
+ module AsciiPaint
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,108 @@
1
+ require 'ascii_paint'
2
+ require 'pry'
3
+
4
+ describe AsciiPaint do
5
+
6
+ let(:input_filename) { Helpers.fixtures_directory.join('ascii.txt') }
7
+
8
+ before(:each) do
9
+ Helpers.cd_work_directory
10
+ end
11
+
12
+ after(:each) do
13
+ Helpers.rm_rf_work_directory
14
+ AsciiPaint.config.reset!
15
+ end
16
+
17
+ it "does math good" do
18
+ (1 + 1).should eq(2)
19
+ end
20
+
21
+ it "writes a file" do
22
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME)
23
+ File.should be_a_file OUTPUT_FILENAME
24
+ end
25
+
26
+ it "paints the correct dimensions" do
27
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME, character_width: 10, character_height: 10)
28
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
29
+ result.height.should eq(2 * 10)
30
+ result.width.should eq(5 * 10)
31
+ end
32
+
33
+ it "paints the correct colors" do
34
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME, character_width: 10, color_map: {'S' => :blue})
35
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
36
+ color = result.get_pixel(15, 0)
37
+ red = ChunkyPNG::Color.r(color)
38
+ green = ChunkyPNG::Color.g(color)
39
+ blue = ChunkyPNG::Color.b(color)
40
+ [red, green, blue].should eq([0, 0, 255])
41
+ end
42
+
43
+ it "accepts a multiline string input" do
44
+ multiline_string = "ASCII\npaint"
45
+ AsciiPaint.paint(multiline_string, OUTPUT_FILENAME, character_width: 10, character_height: 10)
46
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
47
+ result.height.should eq(2 * 10)
48
+ result.width.should eq(5 * 10)
49
+ end
50
+
51
+ it "accepts a string array input" do
52
+ string_array = ["ASCII", "paint"]
53
+ AsciiPaint.paint(string_array, OUTPUT_FILENAME, character_width: 10, character_height: 10)
54
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
55
+ result.height.should eq(2 * 10)
56
+ result.width.should eq(5 * 10)
57
+ end
58
+
59
+ it "accepts a filename input" do
60
+ AsciiPaint.paint(input_filename, OUTPUT_FILENAME, character_width: 10, character_height: 10)
61
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
62
+ result.height.should eq(2 * 10)
63
+ result.width.should eq(5 * 10)
64
+ end
65
+
66
+ it "obeys AsciiPaint.config configuration" do
67
+ AsciiPaint.config do |config|
68
+ config.character_height = 100
69
+ end
70
+
71
+ AsciiPaint.paint(input_filename, OUTPUT_FILENAME)
72
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
73
+ result.height.should eq(2 * 100)
74
+ end
75
+
76
+ it "obeys per-method-call configuration" do
77
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME, character_width: 10, character_height: 10)
78
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
79
+ result.height.should eq(2 * 10)
80
+ result.width.should eq(5 * 10)
81
+ end
82
+
83
+ it "overrides global config with local config" do
84
+ AsciiPaint.config do |config|
85
+ config.character_height = 100
86
+ end
87
+
88
+ AsciiPaint.paint(input_filename, OUTPUT_FILENAME, character_height: 77)
89
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
90
+ result.height.should eq(2 * 77)
91
+ end
92
+
93
+ it "paints transparent paint" do
94
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME, character_width: 10, color_map: {'S' => :transparent})
95
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
96
+ color = result.get_pixel(15, 0)
97
+ alpha = ChunkyPNG::Color.a(color)
98
+ alpha.should eq(0)
99
+ end
100
+
101
+ it "deletes temporary files" do
102
+ AsciiPaint.paint("ASCII\npaint", OUTPUT_FILENAME) do |f|
103
+ File.should be_a_file OUTPUT_FILENAME
104
+ end
105
+
106
+ File.should_not be_a_file OUTPUT_FILENAME
107
+ end
108
+ end
@@ -0,0 +1,75 @@
1
+ require 'ascii_paint'
2
+ require 'pry'
3
+
4
+ describe AsciiPaint::BlockString do
5
+
6
+ before(:each) do
7
+ Helpers.cd_work_directory
8
+ end
9
+
10
+ after(:each) do
11
+ Helpers.rm_rf_work_directory
12
+ AsciiPaint.config.reset!
13
+ end
14
+
15
+ it "writes a file" do
16
+ AsciiPaint.block_paint("ASCII", OUTPUT_FILENAME)
17
+ File.should be_a_file OUTPUT_FILENAME
18
+ end
19
+
20
+ it "obeys local configuration" do
21
+ AsciiPaint.block_paint("ASCII", OUTPUT_FILENAME, character_height: 100)
22
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
23
+ result.height.should eq(100 * AsciiPaint::BlockCharacter.height)
24
+ end
25
+
26
+ it "obeys global configuration" do
27
+ AsciiPaint.config do |config|
28
+ config.character_height = 100
29
+ end
30
+
31
+ AsciiPaint.block_paint("ASCII", OUTPUT_FILENAME)
32
+ result = ChunkyPNG::Image.from_file(OUTPUT_FILENAME)
33
+ result.height.should eq(100 * AsciiPaint::BlockCharacter.height)
34
+ end
35
+
36
+ it "deletes temporary files" do
37
+ AsciiPaint.block_paint("ASCII\npaint", OUTPUT_FILENAME) do |f|
38
+ File.should be_a_file OUTPUT_FILENAME
39
+ end
40
+
41
+ File.should_not be_a_file OUTPUT_FILENAME
42
+ end
43
+
44
+ context "data directory" do
45
+ it "has character files of the correct width" do
46
+ Helpers.each_block_character_path do |path|
47
+ File.open(path, 'r') do |file|
48
+ file.each_line do |line|
49
+ line.chomp.size.should eq(AsciiPaint::BlockCharacter::UNPADDED_WIDTH), file.path
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ it "has character files of the correct height" do
56
+ Helpers.each_block_character_path do |path|
57
+ File.open(path, 'r') do |file|
58
+ file.each_line.count.should eq(AsciiPaint::BlockCharacter::UNPADDED_HEIGHT), file.path
59
+ end
60
+ end
61
+ end
62
+
63
+ it "has character files for all alphanumeric characters" do
64
+ desired_characters = ('A'..'Z').to_a + ('0'..'9').to_a
65
+ found_characters = []
66
+
67
+ Helpers.each_block_character_path do |path|
68
+ character = path.to_s.match(/\/(.)\.txt/)[1]
69
+ found_characters << character
70
+ end
71
+
72
+ found_characters.should =~ desired_characters
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,2 @@
1
+ ASCII
2
+ paint
@@ -0,0 +1,54 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
18
+
19
+ require 'ascii_paint'
20
+
21
+ OUTPUT_FILENAME = 'painted.png'
22
+
23
+ module Helpers
24
+ def self.cd_work_directory
25
+ create_work_directory
26
+ Dir.chdir(Helpers.work_directory)
27
+ end
28
+
29
+ def self.rm_rf_work_directory
30
+ Dir.chdir(work_directory.parent)
31
+ FileUtils.rm_rf(Helpers.work_directory)
32
+ end
33
+
34
+ def self.create_work_directory
35
+ FileUtils.mkdir_p(work_directory)
36
+ end
37
+
38
+ def self.work_directory
39
+ AsciiPaint.root.join('tmp', 'spec')
40
+ end
41
+
42
+ def self.fixtures_directory
43
+ AsciiPaint.root.join('spec', 'fixtures')
44
+ end
45
+
46
+ # TODO: split into separate helper
47
+ def self.each_block_character_path
48
+ block_characters_dir = AsciiPaint.root.join('data', 'block_characters')
49
+ block_characters_dir.each_child(false) do |path|
50
+ full_path = block_characters_dir.join(path)
51
+ yield full_path
52
+ end
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ascii_paint
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Nate Sullivan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chunky_png
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.2.9
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.14.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.14.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Convert ASCII art to PNGs in pure Ruby.
56
+ email: nathanielsullivan00+ascii_paint@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/ascii_paint/block_character.rb
62
+ - lib/ascii_paint/block_string.rb
63
+ - lib/ascii_paint/config.rb
64
+ - lib/ascii_paint/version.rb
65
+ - lib/ascii_paint.rb
66
+ - data/block_characters/0.txt
67
+ - data/block_characters/1.txt
68
+ - data/block_characters/2.txt
69
+ - data/block_characters/3.txt
70
+ - data/block_characters/4.txt
71
+ - data/block_characters/5.txt
72
+ - data/block_characters/6.txt
73
+ - data/block_characters/7.txt
74
+ - data/block_characters/8.txt
75
+ - data/block_characters/9.txt
76
+ - data/block_characters/A.txt
77
+ - data/block_characters/B.txt
78
+ - data/block_characters/C.txt
79
+ - data/block_characters/D.txt
80
+ - data/block_characters/E.txt
81
+ - data/block_characters/F.txt
82
+ - data/block_characters/G.txt
83
+ - data/block_characters/H.txt
84
+ - data/block_characters/I.txt
85
+ - data/block_characters/J.txt
86
+ - data/block_characters/K.txt
87
+ - data/block_characters/L.txt
88
+ - data/block_characters/M.txt
89
+ - data/block_characters/N.txt
90
+ - data/block_characters/O.txt
91
+ - data/block_characters/P.txt
92
+ - data/block_characters/Q.txt
93
+ - data/block_characters/R.txt
94
+ - data/block_characters/S.txt
95
+ - data/block_characters/T.txt
96
+ - data/block_characters/U.txt
97
+ - data/block_characters/V.txt
98
+ - data/block_characters/W.txt
99
+ - data/block_characters/X.txt
100
+ - data/block_characters/Y.txt
101
+ - data/block_characters/Z.txt
102
+ - spec/ascii_paint_spec.rb
103
+ - spec/block_string_spec.rb
104
+ - spec/fixtures/ascii.txt
105
+ - spec/spec_helper.rb
106
+ homepage: https://github.com/nate00/ascii_paint
107
+ licenses:
108
+ - MIT
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.0.3
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Paint in ASCII!
130
+ test_files:
131
+ - spec/ascii_paint_spec.rb
132
+ - spec/block_string_spec.rb
133
+ - spec/fixtures/ascii.txt
134
+ - spec/spec_helper.rb
135
+ has_rdoc: