gd2 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.
- data/COPYING +340 -0
- data/COPYRIGHT +18 -0
- data/README +13 -0
- data/Rakefile +32 -0
- data/lib/gd2.rb +184 -0
- data/lib/gd2/canvas.rb +281 -0
- data/lib/gd2/color.rb +236 -0
- data/lib/gd2/font.rb +343 -0
- data/lib/gd2/image.rb +773 -0
- data/lib/gd2/palette.rb +253 -0
- data/test/dl.rb +11 -0
- data/test/image.rb +22 -0
- metadata +57 -0
data/lib/gd2/palette.rb
ADDED
@@ -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
|
data/test/dl.rb
ADDED
data/test/image.rb
ADDED
@@ -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: []
|