gd2 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,253 @@
1
+ #
2
+ # Ruby/GD2 -- Ruby binding for gd 2 graphics library
3
+ #
4
+ # Copyright © 2005 Robert Leslie
5
+ #
6
+ # This file is part of Ruby/GD2.
7
+ #
8
+ # Ruby/GD2 is free software; you can redistribute it and/or modify it under
9
+ # the terms of the GNU General Public License as published by the Free
10
+ # Software Foundation; either version 2 of the License, or (at your option)
11
+ # any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful, but
14
+ # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
+ # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16
+ # for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License along
19
+ # with this program; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
+ #
22
+
23
+ module GD2
24
+ # = Description
25
+ #
26
+ # Palette objects are associated with an Image and hold the selection of
27
+ # pixel colors available to the Image. This is primarily a concern for
28
+ # Image::IndexedColor images, but their use with Image::TrueColor images is
29
+ # supported for consistency.
30
+ #
31
+ # == Obtaining
32
+ #
33
+ # Obtain a Palette object from the associated Image:
34
+ #
35
+ # palette = image.palette
36
+ #
37
+ class Palette
38
+ class PaletteFullError < StandardError; end
39
+ class ColorNotFoundError < StandardError; end
40
+
41
+ # The Image associated with this Palette
42
+ attr_reader :image
43
+
44
+ def initialize(image) #:nodoc:
45
+ @image = image
46
+ end
47
+
48
+ # Return the maximum number of colors this palette can hold.
49
+ def size
50
+ MAX_COLORS
51
+ end
52
+ alias length size
53
+
54
+ def allocated?(index) #:nodoc:
55
+ @image.image_ptr[:"open[#{index}]"].zero?
56
+ end
57
+ protected :allocated?
58
+
59
+ # Return the number of colors presently allocated in this palette.
60
+ def used
61
+ (0...size).inject(0) do |sum, i|
62
+ sum + (allocated?(i) ? 1 : 0)
63
+ end
64
+ end
65
+
66
+ # Return the number of palette entries available to be allocated for new
67
+ # colors.
68
+ def available
69
+ size - used
70
+ end
71
+
72
+ # Return the color allocated to the specified +index+, or *nil* if the
73
+ # entry is unallocated.
74
+ def [](index)
75
+ index = size + index if index < 0
76
+ raise RangeError unless (0...size).include? index
77
+ return nil unless allocated?(index)
78
+ get_color(index)
79
+ end
80
+
81
+ # Assign (allocate) the given +color+ to the palette entry identified by
82
+ # +index+. If the entry was previously allocated to a different color,
83
+ # every pixel in the image having the given color +index+ will effectively
84
+ # be changed to the new color. This method cannot be used with
85
+ # Image::TrueColor palettes.
86
+ def []=(index, color)
87
+ raise RangeError unless (0...MAX_COLORS).include? index
88
+ if color.nil?
89
+ deallocate(self[index] ||
90
+ Color.new_from_palette(0, 0, 0, 0, index, self))
91
+ else
92
+ ptr = @image.image_ptr
93
+ ptr[:"red[#{index}]"] = color.red
94
+ ptr[:"green[#{index}]"] = color.green
95
+ ptr[:"blue[#{index}]"] = color.blue
96
+ ptr[:"alpha[#{index}]"] = color.alpha
97
+ ptr[:"open[#{index}]"] = 0
98
+ end
99
+ end
100
+
101
+ # Locate the given +color+ in this palette and return it if found;
102
+ # otherwise try to allocate the +color+, or if the palette is full, return
103
+ # a color from the palette that is closest to it.
104
+ def resolve(color)
105
+ raise TypeError unless color.kind_of? Color
106
+ c = SYM[:gdImageColorResolveAlpha].call(@image.image_ptr,
107
+ color.red, color. green, color.blue, color.alpha)[0]
108
+ c == -1 ? nil : get_color(c)
109
+ end
110
+
111
+ # Locate the given +color+ in this palette and return it. Returns *nil*
112
+ # if the color is not presently in the palette.
113
+ def exact(color)
114
+ raise TypeError unless color.kind_of? Color
115
+ c = SYM[:gdImageColorExactAlpha].call(@image.image_ptr,
116
+ color.red, color.green, color.blue, color.alpha)[0]
117
+ c == -1 ? nil : get_color(c)
118
+ end
119
+
120
+ # Like Palette#exact except an error is raised if the color is not
121
+ # presently in the palette.
122
+ def exact!(color)
123
+ exact(color) or raise Palette::ColorNotFoundError,
124
+ "Color #{color} is not in the palette"
125
+ end
126
+
127
+ # Return the color in this palette that is closest to the given +color+
128
+ # according to Euclidian distance.
129
+ def closest(color)
130
+ raise TypeError unless color.kind_of? Color
131
+ c = SYM[:gdImageColorClosestAlpha].call(@image.image_ptr,
132
+ color.red, color.green, color.blue, color.alpha)[0]
133
+ c == -1 ? nil : get_color(c)
134
+ end
135
+
136
+ # Return the color in this palette that is closest to the given +color+
137
+ # according to hue, whiteness, and blackness.
138
+ def closest_hwb(color)
139
+ raise TypeError unless color.kind_of? Color
140
+ c = SYM[:gdImageColorClosestHWB].call(@image.image_ptr,
141
+ color.red, color.green, color.blue)[0]
142
+ c == -1 ? nil : get_color(c)
143
+ end
144
+
145
+ # Assign the given +color+ to an unoccupied entry in this palette and
146
+ # return it. Does not check whether the color is already allocated, and
147
+ # raises an error for Image::IndexedColor palettes if the palette is full.
148
+ def allocate(color)
149
+ raise TypeError unless color.kind_of? Color
150
+ c = SYM[:gdImageColorAllocateAlpha].call(@image.image_ptr,
151
+ color.red, color.green, color.blue, color.alpha)[0]
152
+ c == -1 ? raise(Palette::PaletteFullError, 'Palette is full') :
153
+ get_color(c)
154
+ end
155
+
156
+ # Ensure the given +color+ is present in this palette, allocating it if
157
+ # necessary. Returns the palette so calls may be stacked.
158
+ def <<(color)
159
+ exact(color) or allocate(color)
160
+ self
161
+ end
162
+
163
+ # Remove the given +color+ from this palette.
164
+ def deallocate(color)
165
+ color = exact(color) unless color.index
166
+ return nil if color.nil? || color.index.nil?
167
+ SYM[:gdImageColorDeallocate].call(@image.image_ptr, color.index)
168
+ nil
169
+ end
170
+
171
+ # Remove all colors from this palette that are not currently in use by the
172
+ # associated Image. This is an expensive operation. Returns the number of
173
+ # palette entries deallocated.
174
+ def deallocate_unused
175
+ # implemented by subclass
176
+ end
177
+ end
178
+
179
+ class Palette::IndexedColor < Palette
180
+ include Enumerable
181
+
182
+ def inspect #:nodoc:
183
+ "#<#{self.class} [#{used}]>"
184
+ end
185
+
186
+ def get_color(index) #:nodoc:
187
+ ptr = @image.image_ptr
188
+ Color.new_from_palette(
189
+ ptr[:"red[#{index}]"],
190
+ ptr[:"green[#{index}]"],
191
+ ptr[:"blue[#{index}]"],
192
+ ptr[:"alpha[#{index}]"],
193
+ index, self)
194
+ end
195
+ protected :get_color
196
+
197
+ # Iterate through every color allocated in this palette.
198
+ def each #:yields: color
199
+ (0...MAX_COLORS).each do |i|
200
+ color = self[i]
201
+ yield color unless color.nil?
202
+ end
203
+ self
204
+ end
205
+
206
+ def deallocate_unused #:nodoc:
207
+ used = @image.collect.flatten.uniq.inject(Array.new(MAX_COLORS)) do
208
+ |ary, c|
209
+ ary[c] = true
210
+ ary
211
+ end
212
+ count = 0
213
+ each do |color|
214
+ unless used.at(color.index)
215
+ self[color.index] = nil
216
+ count += 1
217
+ end
218
+ end
219
+ count.zero? ? nil : count
220
+ end
221
+ end
222
+
223
+ class Palette::TrueColor < Palette
224
+ def inspect #:nodoc:
225
+ "#<#{self.class}>"
226
+ end
227
+
228
+ def size #:nodoc:
229
+ ((1 + RGB_MAX) ** 3) * (1 + ALPHA_MAX)
230
+ end
231
+ alias length size
232
+ alias used size
233
+
234
+ def allocated?(index) #:nodoc:
235
+ true
236
+ end
237
+ protected :allocated?
238
+
239
+ # Return *true*.
240
+ def include?(color)
241
+ true
242
+ end
243
+
244
+ def get_color(index) #:nodoc:
245
+ Color.new_from_rgba(index)
246
+ end
247
+ protected :get_color
248
+
249
+ def []=(index, color) #:nodoc:
250
+ raise "Palette assignment not supported for #{self.class}"
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'dl'
3
+
4
+ class DLTest < Test::Unit::TestCase
5
+ def test_dlopen
6
+ assert_nothing_raised {
7
+ DL.dlopen(Config::CONFIG['arch'] == 'powerpc-darwin' ?
8
+ 'libgd.2.dylib' : 'libgd.so.2')
9
+ }
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+
3
+ $:.push 'lib'
4
+ require 'gd2'
5
+
6
+ class ImageTest < Test::Unit::TestCase
7
+ include GD2
8
+
9
+ def setup
10
+ @image = Image.new(50, 50)
11
+ end
12
+
13
+ def test_image
14
+ assert @image == Image.new(50, 50),
15
+ 'Images are not equal'
16
+ end
17
+
18
+ def teardown
19
+ @image = nil
20
+ GC.start
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: gd2
5
+ version: !ruby/object:Gem::Version
6
+ version: "1.0"
7
+ date: 2005-11-14 00:00:00 -08:00
8
+ summary: Ruby interface to gd 2 library.
9
+ require_paths:
10
+ - lib
11
+ email: rob@mars.org
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: gd2
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
25
+ version:
26
+ platform: ruby
27
+ signing_key:
28
+ cert_chain:
29
+ authors:
30
+ - Rob Leslie
31
+ files:
32
+ - README
33
+ - COPYING
34
+ - COPYRIGHT
35
+ - Rakefile
36
+ - lib/gd2.rb
37
+ - lib/gd2/canvas.rb
38
+ - lib/gd2/color.rb
39
+ - lib/gd2/font.rb
40
+ - lib/gd2/image.rb
41
+ - lib/gd2/palette.rb
42
+ test_files:
43
+ - test/dl.rb
44
+ - test/image.rb
45
+ rdoc_options:
46
+ - "--title"
47
+ - Ruby/GD2
48
+ - "--charset"
49
+ - utf-8
50
+ extra_rdoc_files:
51
+ - README
52
+ - COPYING
53
+ executables: []
54
+ extensions: []
55
+ requirements:
56
+ - "libgd, v2.0.33 or greater"
57
+ dependencies: []