pixelart 0.2.2 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c2b93e1779a1c06ff0b13dbfcae471648cd2f2dc153b17da3fd864615f6f6c1
4
- data.tar.gz: cef870177214b37eb902a99a41410dc8c080b613fed7c48cccd801290392fd28
3
+ metadata.gz: 798a4eb7b61556c0c79889d01d404a499598286779e009fa71304986f4d68c31
4
+ data.tar.gz: 9b17446fe914c1b62135c1e1432bc2debf74037ca9e602feb25e71ec7088b117
5
5
  SHA512:
6
- metadata.gz: 8ac5ad9fd3e16d9d490d7c43c38fa2b95ee6318a7c0f319e142fc59084ab70315ebb3d0e800d4536a098214768cab3adae99b1ec2c482ce93a4ab1e902d36cc5
7
- data.tar.gz: 67e9e1214ae9f614a2694d30a9b63ce5aa2c83dad17a98dac141913b86cb4375ea22fc0630e2e3160f6b768b4b79ab2236555d0467471fd6a127f477ca48f6db
6
+ metadata.gz: 8073e67ffd10361088fd66b768d4aa5927c2f65cdd54389615b980c2181ec8cde2a2ad21eced1fe7a756af7ce2e7c681b2aea4a89aed2c869ad04a956388d54a
7
+ data.tar.gz: b69918e012f6270a9aa0817d69e094bb52cd12ed05399ac566872efdd2174af9c9534ef2e72f4f34f4d3f1bbe4d5062aedcbb42deb67ff55c52a005965b2d969
data/Manifest.txt CHANGED
@@ -4,6 +4,7 @@ README.md
4
4
  Rakefile
5
5
  lib/pixelart.rb
6
6
  lib/pixelart/base.rb
7
+ lib/pixelart/blur.rb
7
8
  lib/pixelart/color.rb
8
9
  lib/pixelart/composite.rb
9
10
  lib/pixelart/gradient.rb
@@ -12,4 +13,7 @@ lib/pixelart/led.rb
12
13
  lib/pixelart/misc.rb
13
14
  lib/pixelart/palette.rb
14
15
  lib/pixelart/pixelator.rb
16
+ lib/pixelart/sketch.rb
17
+ lib/pixelart/spots.rb
18
+ lib/pixelart/vector.rb
15
19
  lib/pixelart/version.rb
data/Rakefile CHANGED
@@ -19,6 +19,7 @@ Hoe.spec 'pixelart' do
19
19
 
20
20
  self.extra_deps = [
21
21
  ['chunky_png'],
22
+ ['mini_magick'],
22
23
  ]
23
24
 
24
25
  self.licenses = ['Public Domain']
data/lib/pixelart/base.rb CHANGED
@@ -1,12 +1,24 @@
1
- ## 3rd party
1
+ ###############
2
+ # 3rd party
2
3
  require 'chunky_png'
3
4
 
5
+ # optional
6
+ # note: requires installed imagemagick command line installed for usage
7
+ require 'mini_magick'
8
+
9
+
10
+
4
11
  ## stdlib
5
12
  require 'pp'
6
13
  require 'time'
7
14
  require 'date'
8
15
  require 'fileutils'
9
16
 
17
+ require 'json'
18
+ require 'yaml'
19
+
20
+
21
+
10
22
 
11
23
  ## our own code
12
24
  require 'pixelart/version' # note: let version always go first
@@ -16,11 +28,34 @@ require 'pixelart/palette'
16
28
  require 'pixelart/image'
17
29
  require 'pixelart/composite'
18
30
 
31
+
19
32
  require 'pixelart/pixelator'
20
33
 
21
34
  require 'pixelart/misc' ## misc helpers
22
35
 
23
- require 'pixelart/led' ## (special) effects / filters
36
+ #########################
37
+ # (special) effects / filters
38
+ require 'pixelart/led'
39
+ require 'pixelart/sketch'
40
+
41
+ ## (special) effects / filters that require imagemagick
42
+
43
+
44
+ ## todo/check - use a config block or such - why? why not?
45
+ module Pixelart
46
+ MAGICK_SCRIPT = './tmp/magick_script.txt'
47
+ MAGICK_INPUT = './tmp/magick_input.png'
48
+ MAGICK_OUTPUT = './tmp/magick_output.png'
49
+ end
50
+
51
+ require 'pixelart/vector' ## vector graphics helpers
52
+
53
+
54
+ require 'pixelart/spots'
55
+ require 'pixelart/blur'
56
+
57
+
58
+
24
59
 
25
60
 
26
61
 
@@ -0,0 +1,19 @@
1
+ module Pixelart
2
+
3
+ class Image
4
+
5
+ def blur( blur=2 )
6
+ @img.save( MAGICK_INPUT )
7
+
8
+ MiniMagick::Tool::Magick.new do |magick|
9
+ magick << MAGICK_INPUT
10
+ magick.blur( "#{blur}x#{blur}" )
11
+ magick << MAGICK_OUTPUT
12
+ end
13
+
14
+ Image.read( MAGICK_OUTPUT )
15
+ end
16
+
17
+ end # class Image
18
+ end # class Pixelart
19
+
@@ -7,6 +7,13 @@ class ImageComposite < Image # check: (re)name to Collage, Sheet, Sprites, or s
7
7
  TILE_HEIGHT = 24
8
8
 
9
9
 
10
+ def self.read( path, width: TILE_WIDTH, height: TILE_WIDTH ) ## convenience helper
11
+ img = ChunkyPNG::Image.from_file( path )
12
+ new( img, width: width,
13
+ height: width )
14
+ end
15
+
16
+
10
17
  def initialize( *args, **kwargs )
11
18
  @tile_width = kwargs[:width] || kwargs[:tile_width] || TILE_WIDTH
12
19
  @tile_height = kwargs[:height] || kwargs[:tile_height] || TILE_HEIGHT
@@ -73,5 +80,21 @@ class ImageComposite < Image # check: (re)name to Collage, Sheet, Sprites, or s
73
80
  super ## e.g [x,y] --- get pixel
74
81
  end
75
82
  end
83
+
84
+
85
+ ## convenience helpers to loop over composite
86
+ def each( &block )
87
+ count.times do |i|
88
+ block.call( tile( i ) )
89
+ end
90
+ end
91
+
92
+ def each_with_index( &block )
93
+ count.times do |i|
94
+ block.call( tile( i ), i )
95
+ end
96
+ end
97
+
98
+
76
99
  end # class ImageComposite
77
100
  end # module Pixelart
@@ -94,12 +94,25 @@ def grayscale
94
94
  img = @img.grayscale
95
95
  Image.new( img.width, img.height, img )
96
96
  end
97
+ alias_method :greyscale, :grayscale
98
+
99
+
100
+
101
+ def flip
102
+ img = @img.flip
103
+ Image.new( img.width, img.height, img )
104
+ end
105
+ alias_method :flip_horizontally, :flip
97
106
 
98
107
  def mirror
99
108
  img = @img.mirror
100
109
  Image.new( img.width, img.height, img )
101
110
  end
102
111
  alias_method :flip_vertically, :mirror
112
+ alias_method :flop, :mirror
113
+
114
+
115
+
103
116
 
104
117
 
105
118
  ## add replace_colors alias too? - why? why not?
@@ -0,0 +1,69 @@
1
+ module Pixelart
2
+
3
+
4
+
5
+ class Image
6
+ def sketch( sketch=4, line: 1 )
7
+ # todo: line - find a better name eg. line_strenght/width or such?
8
+ width = @img.width*sketch + (@img.width+1)*line
9
+ height = @img.height*sketch + (@img.height+1)*line
10
+
11
+ puts " #{width}x#{height}"
12
+
13
+ img = Image.new( width, height, Color::WHITE )
14
+
15
+ @img.width.times do |x|
16
+ @img.height.times do |y|
17
+ pixel = @img[x,y]
18
+
19
+ ## get surrounding pixels - if "out-of-bound" use transparent (0)
20
+ left = x == 0 ? Color::TRANSPARENT : @img[x-1,y]
21
+ top = y == 0 ? Color::TRANSPARENT : @img[x ,y-1]
22
+
23
+ if pixel != left ## draw vertical line
24
+ (sketch+line*2).times do |n|
25
+ line.times do |m|
26
+ img[ x*sketch + line*x + m,
27
+ n + y*sketch + line*y] = Color::BLACK
28
+ end
29
+ end
30
+ end
31
+
32
+ if pixel != top ## draw horizontal line
33
+ (sketch+line*2).times do |n|
34
+ line.times do |m|
35
+ img[n + x*sketch + line*x,
36
+ y*sketch + line*y + m] = Color::BLACK
37
+ end
38
+ end
39
+ end
40
+
41
+
42
+ ## check special edge case for x and y to add "finish-up" right and bottom line
43
+ if x == @img.width-1 && pixel != Color::TRANSPARENT
44
+ ## draw vertical line
45
+ (sketch+line*2).times do |n|
46
+ line.times do |m|
47
+ img[ (x+1)*sketch + line*(x+1) + m,
48
+ n + y*sketch + line*y] = Color::BLACK
49
+ end
50
+ end
51
+ end
52
+
53
+ if y== @img.height-1 && pixel != Color::TRANSPARENT
54
+ ## draw horizontal line
55
+ (sketch+line*2).times do |n|
56
+ line.times do |m|
57
+ img[n + x*sketch + line*x,
58
+ (y+1)*sketch + line*(y+1) + m] = Color::BLACK
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ img
66
+ end
67
+ end # class Image
68
+ end # module Pixelart
69
+
@@ -0,0 +1,146 @@
1
+ module Pixelart
2
+
3
+ class Image
4
+
5
+
6
+ def spots_hidef( spot=10,
7
+ spacing: 0,
8
+ center: nil,
9
+ radius: nil,
10
+ background: nil,
11
+ lightness: nil,
12
+ odd: false )
13
+
14
+ width = @img.width*spot+(@img.width-1)*spacing
15
+ height = @img.height*spot+(@img.height-1)*spacing
16
+
17
+ ## puts " #{width}x#{height}"
18
+
19
+ ## settings in a hash for "pretty printing" in comments
20
+ settings = { spot: spot
21
+ }
22
+
23
+ settings[ :spacing ] = spacing if spacing
24
+ settings[ :center ] = center if center
25
+ settings[ :radius ] = radius if radius
26
+ settings[ :background ] = background if background
27
+ settings[ :lightness ] = lightness if lightness
28
+ settings[ :odd ] = odd if odd
29
+
30
+
31
+ v = Vector.new( width, height, header: <<TXT )
32
+ generated by pixelart/v#{VERSION} on #{Time.now.utc}
33
+
34
+ spots_hidef with settings:
35
+ #{settings.to_json}
36
+ TXT
37
+
38
+
39
+ min_center, max_center = center ? center : [0,0]
40
+ min_radius, max_radius = radius ? radius : [0,0]
41
+
42
+ ## note: allow passing in array of colors (will get randomally picked)
43
+ background_colors = if background
44
+ ## check for array; otherwise assume single color passed in
45
+ background_ary = background.is_a?( Array) ? background : [background]
46
+ background_ary.map { |background| Color.parse( background ) }
47
+ else
48
+ [0] # transparent (default - no background)
49
+ end
50
+
51
+
52
+ min_lightness, max_lightness = lightness ? lightness : [0.0,0.0]
53
+
54
+
55
+ @img.width.times do |x|
56
+ @img.height.times do |y|
57
+ color = @img[ x, y ]
58
+
59
+ if color == 0 ## transparent
60
+ next if background.nil?
61
+
62
+ color = if background_colors.size == 1
63
+ background_colors[0]
64
+ else ## pick random background color
65
+ background_colors[ rand( background_colors.size ) ]
66
+ end
67
+ end
68
+
69
+
70
+ if lightness
71
+ ## todo/check: make it work with alpha too
72
+ h,s,l = Color.to_hsl( color, include_alpha: false )
73
+
74
+ h = h % 360 ## make sure h(ue) is always positive!!!
75
+
76
+ ## note: rand() return between 0.0 and 1.0
77
+ l_diff = min_lightness +
78
+ (max_lightness-min_lightness)*rand()
79
+
80
+ lnew = [1.0, l+l_diff].min
81
+ lnew = [0.0, lnew].max
82
+
83
+ ## print " #{l}+#{l_diff}=#{lnew} "
84
+
85
+ color = Color.from_hsl( h,
86
+ [1.0, s].min,
87
+ lnew )
88
+ end
89
+
90
+ ## note: return hexstring with leading #
91
+ # e.g. 0 becomes #00000000
92
+ # and so on
93
+ color_hex = Color.to_hex( color, include_alpha: true )
94
+
95
+ cx_offset,
96
+ cy_offset = if center ## randomize (offset off center +/-)
97
+ [(spot/2 + min_center) + rand( max_center-min_center ),
98
+ (spot/2 + min_center) + rand( max_center-min_center )]
99
+ else
100
+ [spot/2, ## center
101
+ spot/2]
102
+ end
103
+
104
+ cx = x*spot + x*spacing + cx_offset
105
+ cy = y*spot + y*spacing + cx_offset
106
+
107
+ r = if radius ## randomize (radius +/-)
108
+ min_radius + rand( max_radius-min_radius )
109
+ else
110
+ spot/2
111
+ end
112
+
113
+ cx += spot/2 if odd && (y % 2 == 1) ## add odd offset
114
+
115
+
116
+ v.circle( cx: cx, cy: cy, r: r, fill: color_hex)
117
+ end
118
+ end
119
+ v
120
+ end ## method spots_hidef
121
+ alias_method :spots_hd, :spots_hidef
122
+
123
+
124
+ def spots( spot=10,
125
+ spacing: 0,
126
+ center: nil,
127
+ radius: nil,
128
+ background: nil,
129
+ lightness: nil,
130
+ odd: false )
131
+
132
+ v = spots_hidef( spot,
133
+ spacing: spacing,
134
+ center: center,
135
+ radius: radius,
136
+ background: background,
137
+ lightness: lightness,
138
+ odd: odd )
139
+
140
+ v.to_image
141
+ end
142
+
143
+
144
+ end # class Image
145
+ end # class Pixelart
146
+
@@ -0,0 +1,108 @@
1
+ module Pixelart
2
+
3
+
4
+ class Vector # holds a vector graphics image (in source)
5
+
6
+ class Shape; end
7
+ class Circle < Shape
8
+ def initialize( cx, cy, r, fill: )
9
+ @cx = cx
10
+ @cy = cy
11
+ @r = r
12
+ @fill = fill
13
+ end
14
+
15
+ def to_svg
16
+ %Q{<circle cx="#{@cx}" cy="#{@cy}" r="#{@r}" fill="#{@fill}" />}
17
+ end
18
+
19
+ def to_magick
20
+ ## circle
21
+ ## give the center and any point on the perimeter (boundary)
22
+ px = @cx+@r
23
+ py = @cy
24
+ "-fill '#{@fill}' -draw 'circle #{@cx},#{@cy},#{px},#{py}'"
25
+ end
26
+ end # class Circle
27
+
28
+
29
+
30
+ def initialize( width, height, header: nil )
31
+ @width = width
32
+ @height = height
33
+
34
+ @header = header
35
+ @shapes = []
36
+ end
37
+
38
+ def circle( cx:, cy:, r:, fill: )
39
+ @shapes << Circle.new( cx, cy, r, fill: fill )
40
+ end
41
+
42
+
43
+
44
+ def to_image
45
+ ## use an empty image (canvas) with transparent background
46
+ ## as magick input image
47
+ canvas = Image.new( @width, @height )
48
+ canvas.save( MAGICK_INPUT )
49
+
50
+ ## note: magick command line might get way too long, thus,
51
+ ## save commands to a script
52
+ ## note: save magick input first (see above) before save script
53
+ ## will (auto-)create missing directories in path (if missing)
54
+
55
+ File.open( MAGICK_SCRIPT, 'w:utf-8' ) do |f|
56
+ f.write( "#{MAGICK_INPUT} \\\n" )
57
+ @shapes.each do |shape|
58
+ f.write( "#{shape.to_magick} \\\n" )
59
+ end
60
+ f.write( "-write #{MAGICK_OUTPUT}\n" )
61
+ end
62
+
63
+ MiniMagick::Tool::Magick.new do |magick|
64
+ magick.script( MAGICK_SCRIPT )
65
+ end
66
+
67
+ Image.read( MAGICK_OUTPUT )
68
+ end
69
+
70
+
71
+ def to_svg
72
+ buf = String.new('')
73
+
74
+ if @header
75
+ buf << "<!--\n"
76
+ ## auto-indent lines by five (5) spaces for now
77
+ @header.each_line do |line|
78
+ buf << " #{line}"
79
+ end
80
+ buf << "\n-->\n\n"
81
+ end
82
+
83
+ buf << %Q{<svg version="1.1" width="#{@width}" height="#{@height}" xmlns="http://www.w3.org/2000/svg">\n}
84
+ @shapes.each do |shape|
85
+ buf << " #{shape.to_svg}\n"
86
+ end
87
+ buf << "</svg>"
88
+ buf
89
+ end
90
+
91
+
92
+ def save( path, format: nil )
93
+ if format && format.downcase == 'png' ## support png with image magick
94
+ img = to_image
95
+ img.save( path )
96
+ else
97
+ # make sure outdir exits
98
+ outdir = File.dirname( path )
99
+ FileUtils.mkdir_p( outdir ) unless Dir.exist?( outdir )
100
+ File.open( path, 'w:utf-8' ) do |f|
101
+ f.write( to_svg )
102
+ end
103
+ end
104
+ end
105
+ alias_method :write, :save
106
+
107
+ end # class Vector
108
+ end # module Pixelart
@@ -1,9 +1,9 @@
1
1
 
2
2
  module Pixelart
3
3
 
4
- MAJOR = 0
4
+ MAJOR = 1
5
5
  MINOR = 2
6
- PATCH = 2
6
+ PATCH = 0
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pixelart
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-16 00:00:00.000000000 Z
11
+ date: 2021-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mini_magick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rdoc
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +88,7 @@ files:
74
88
  - Rakefile
75
89
  - lib/pixelart.rb
76
90
  - lib/pixelart/base.rb
91
+ - lib/pixelart/blur.rb
77
92
  - lib/pixelart/color.rb
78
93
  - lib/pixelart/composite.rb
79
94
  - lib/pixelart/gradient.rb
@@ -82,6 +97,9 @@ files:
82
97
  - lib/pixelart/misc.rb
83
98
  - lib/pixelart/palette.rb
84
99
  - lib/pixelart/pixelator.rb
100
+ - lib/pixelart/sketch.rb
101
+ - lib/pixelart/spots.rb
102
+ - lib/pixelart/vector.rb
85
103
  - lib/pixelart/version.rb
86
104
  homepage: https://github.com/rubycoco/pixel
87
105
  licenses: