gd2 1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|