rubyshop 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006, Corban Riley
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+ * Neither the name of the Corban Riley nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
12
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
13
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
14
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
15
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
16
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
17
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
18
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
19
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
20
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/lib/rubyshop.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'rmagick'
2
+
3
+ require 'rubyshop/canvas'
4
+ require 'rubyshop/layerset'
5
+ require 'rubyshop/layer'
6
+ require 'rubyshop/filllayer'
7
+ require 'rubyshop/adjustmentlayer'
8
+
9
+ module Rubyshop
10
+ # Layer mode constants
11
+ # some of photoshops layer modes are directly equvilent to RMagick
12
+ # some are not, and some arent supported at all.
13
+
14
+ Normal = Magick::OverCompositeOp # PS equivilent
15
+ Dissolve = Magick::DissolveCompositeOp
16
+ Darken = Magick::DarkenCompositeOp # PS equivilent
17
+ Multiply = Magick::MultiplyCompositeOp # PS equivilent
18
+ #ColorBurn
19
+ #LinearBurn
20
+ Lighten = Magick::LightenCompositeOp # PS equivilent
21
+ Screen = Magick::ScreenCompositeOp # PS equivilent
22
+ #ColorDodge
23
+ #LinearDodge
24
+ Overlay = Magick::OverlayCompositeOp # PS equivilent
25
+ #SoftLight
26
+ #HardLight
27
+ #VividLight
28
+ #LinearLight
29
+ #PinLight
30
+ #HardMix
31
+ Difference = Magick::DifferenceCompositeOp # PS equivilent
32
+ #Exclusion
33
+ Hue = Magick::HueCompositeOp
34
+ Saturation = Magick::SaturateCompositeOp
35
+ Color = Magick::ColorizeCompositeOp
36
+ Luminosity = Magick::LuminizeCompositeOp
37
+ end
@@ -0,0 +1,4 @@
1
+ module Rubyshop
2
+ class AdjustmentLayer < Layer
3
+ end
4
+ end
@@ -0,0 +1,78 @@
1
+ module Rubyshop
2
+ class Canvas
3
+ attr_reader :width, :height
4
+
5
+ def initialize(width, height, &block)
6
+ @image = Magick::Image.new width, height
7
+ @width = width
8
+ @height = height
9
+ @layers = []
10
+ @sets = {}
11
+
12
+ self.instance_eval &block if block_given?
13
+ end
14
+
15
+ def layer_set(name, &block)
16
+ if name.is_a? Rubyshop::LayerSet
17
+ set = name
18
+ @layers << set
19
+ @sets[set.name] = set
20
+ elsif @sets[name]
21
+ set = @sets[name]
22
+ else
23
+ set = LayerSet.new name
24
+ @layers << set
25
+ @sets[name] = set
26
+ end
27
+
28
+ set.instance_eval &block if block_given?
29
+
30
+ return set
31
+ end
32
+
33
+ def layer(filename, &block)
34
+ layer = Layer.new filename
35
+ @layers << layer
36
+
37
+ layer.instace_eval &block if block_given?
38
+
39
+ return layer
40
+ end
41
+
42
+ def flatten
43
+ layers = @layers
44
+ layers.reverse.each do |layer|
45
+ if layer.is_a? Rubyshop::Layer
46
+ @image.composite!(layer.image, layer.offset_x, layer.offset_y, layer.mode)
47
+ elsif layer.is_a? Rubyshop::LayerSet
48
+ layer.layers.reverse.each do |set_layer|
49
+ image.composite!(set_layer.image, set_layer.offset_x, set_layer.offset_y, set_layer.mode)
50
+ end
51
+ end
52
+ @layers.delete(layer)
53
+ end
54
+ end
55
+
56
+ def render
57
+ image = @image
58
+ @layers.reverse.each do |layer|
59
+ if layer.is_a? Rubyshop::Layer
60
+ image.composite!(layer.image, layer.offset_x, layer.offset_y, layer.mode)
61
+ elsif layer.is_a? Rubyshop::LayerSet
62
+ layer.layers.reverse.each do |set_layer|
63
+ image.composite!(set_layer.image, set_layer.offset_x, set_layer.offset_y, set_layer.mode)
64
+ end
65
+ elsif layer.is_a? Rubyshop::AdjustmentLayer
66
+ # nothing to do
67
+ elsif layer.is_a? Rubyshop::FillLayer
68
+ # nother to do
69
+ end
70
+ end
71
+ return image
72
+ end
73
+
74
+ def save_as(filename)
75
+ render.write(filename)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,4 @@
1
+ module Rubyshop
2
+ class FillLayer < Layer
3
+ end
4
+ end
@@ -0,0 +1,59 @@
1
+ module Rubyshop
2
+ class Layer
3
+ attr_accessor :image, :name
4
+ attr_reader :offset_x, :offset_y
5
+
6
+ def initialize(filename)
7
+ @image = Magick::Image.read(filename).first
8
+ @image.background_color = 'transparent'
9
+ @image.matte = true
10
+ @mode = Normal
11
+ @offset_x = 0
12
+ @offset_y = 0
13
+ @opacity_percent = 100
14
+ @name = filename
15
+ end
16
+
17
+ def width
18
+ @image.columns
19
+ end
20
+
21
+ def height
22
+ @image.rows
23
+ end
24
+
25
+ def offset(x, y)
26
+ @offset_x = x
27
+ @offset_y = y
28
+ end
29
+
30
+ def opacity(percent)
31
+ @opacity_percent = percent
32
+ # intercept original alpha channel with pixel intensity
33
+ alpha_channel = @image.channel(Magick::AlphaChannel).negate
34
+ intensity = (Magick::MaxRGB * (percent/100.0)).round
35
+ alpha_channel.composite!(Magick::Image.new(width, height) { self.background_color = Magick::Pixel.new(intensity,intensity,intensity) }, Magick::CenterGravity, Multiply)
36
+ alpha_channel.matte = false
37
+
38
+ @image.composite!(alpha_channel, Magick::CenterGravity, Magick::CopyOpacityCompositeOp)
39
+ return true
40
+ end
41
+
42
+ def mode(mode = nil)
43
+ return @mode if mode.nil?
44
+ @mode = mode
45
+ end
46
+
47
+ def save_as(filename)
48
+ @image.write(filename)
49
+ end
50
+
51
+ def join_set(set)
52
+ set.add_layer(self)
53
+ end
54
+
55
+ def leave_set(set)
56
+ set.remove_layer(self)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,108 @@
1
+ module Rubyshop
2
+ class LayerSet
3
+ attr_accessor :layers
4
+ attr_reader :min_x, :min_y, :max_x, :max_y, :bounding_width, :bounding_height, :name
5
+
6
+ def initialize(name)
7
+ @layers = []
8
+ bounding_box
9
+ @name = name
10
+ yield self if block_given?
11
+ end
12
+
13
+ def layer(filename, &block)
14
+ layer = Layer.new(filename)
15
+ @layers << layer
16
+
17
+ layer.instance_eval &block
18
+
19
+ return layer
20
+ end
21
+
22
+ def add_layer(layer)
23
+ @layers << layer
24
+ bounding_box
25
+ end
26
+
27
+ def remove_layer(layer)
28
+ @layers.delete(layer)
29
+ bounding_box
30
+ end
31
+
32
+ def bounding_box
33
+ if @layers.size > 0
34
+ x1 = []
35
+ y1 = []
36
+ x2 = []
37
+ y2 = []
38
+ @layers.each do |layer|
39
+ x1 << layer.offset_x
40
+ y1 << layer.offset_y
41
+ x2 << layer.width + layer.offset_x
42
+ y2 << layer.height + layer.offset_y
43
+ end
44
+
45
+ @min_x = x1.min
46
+ @min_y = y1.min
47
+ @max_x = x2.max
48
+ @max_y = y2.max
49
+ @bounding_width = @max_x - @min_x
50
+ @bounding_height = @max_y - @min_y
51
+ else
52
+ @min_x = 0
53
+ @min_y = 0
54
+ @max_x = 0
55
+ @max_y = 0
56
+ @bounding_width = 0
57
+ @boudning_height = 0
58
+ end
59
+ end
60
+
61
+ def offset(x, y)
62
+ bounding_box # recalculate bounding box
63
+ shift_x = x - @min_x
64
+ shift_y = y - @min_y
65
+ @layers.each do |layer|
66
+ layer.offset(layer.offset_x + shift_x, layer.offset_y + shift_y)
67
+ end
68
+ bounding_box
69
+ end
70
+
71
+ def scale(width, height)
72
+ bounding_box # recalculate bounding box
73
+ width_scale = width.to_f / bounding_width.to_f
74
+ height_scale = height.to_f / bounding_height.to_f
75
+ @layers.each do |layer|
76
+ layer.image.scale!((layer.width * width_scale).round, (layer.height * height_scale).round)
77
+ layer.offset(((layer.offset_x - @min_x) * width_scale).round + @min_x, ((layer.offset_y - @min_y) * height_scale).round + @min_y)
78
+ end
79
+ bounding_box
80
+ end
81
+
82
+ def rotate(degrees)
83
+ bounding_box # recalculate bounding box
84
+ bounding_mid_x = @bounding_width / 2
85
+ bounding_mid_y = @bounding_height / 2
86
+ @layers.each do |layer|
87
+ layer_mid_x = (layer.width/2.0).round + layer.offset_x - @min_x - bounding_mid_x
88
+ layer_mid_y = ((layer.height/2.0).round + layer.offset_y - @min_y - bounding_mid_y) * -1
89
+
90
+ radians = (degrees * -1) / (180 / Math::PI)
91
+
92
+ cos = Math.cos(radians)
93
+ sin = Math.sin(radians)
94
+
95
+ new_mid_x = ((layer_mid_x * cos) - (layer_mid_y * sin)).round
96
+ new_mid_y = ((layer_mid_x * sin) + (layer_mid_y * cos)).round
97
+
98
+ layer.image.rotate!(degrees)
99
+
100
+ new_offset_x = new_mid_x - (layer.width/2.0).round + @min_x + bounding_mid_x
101
+ new_offset_y = new_mid_y * -1 - (layer.height/2.0).round + @min_y + bounding_mid_y
102
+
103
+ layer.offset(new_offset_x, new_offset_y)
104
+ end
105
+ bounding_box
106
+ end
107
+ end
108
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: rubyshop
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2006-11-06 00:00:00 -05:00
8
+ summary: Powerful layer based image compositing made easy as pie.
9
+ require_paths:
10
+ - lib
11
+ email: corbanbrook@gmail.com
12
+ homepage: http://schf.uc.org
13
+ rubyforge_project: rubyshop
14
+ description:
15
+ autorequire: rubyshop
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Corban Brook
31
+ files:
32
+ - lib/rubyshop.rb
33
+ - lib/rubyshop/adjustmentlayer.rb
34
+ - lib/rubyshop/canvas.rb
35
+ - lib/rubyshop/filllayer.rb
36
+ - lib/rubyshop/layer.rb
37
+ - lib/rubyshop/layerset.rb
38
+ - LICENSE
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies:
52
+ - !ruby/object:Gem::Dependency
53
+ name: rmagick
54
+ version_requirement:
55
+ version_requirements: !ruby/object:Gem::Version::Requirement
56
+ requirements:
57
+ - - ">"
58
+ - !ruby/object:Gem::Version
59
+ version: 0.0.0
60
+ version: