gale 0.0.1alpha-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +45 -0
- data/lib/gale.rb +5 -0
- data/lib/gale/dll.rb +244 -0
- data/lib/gale/file.rb +105 -0
- data/lib/gale/frame.rb +77 -0
- data/lib/gale/gosu.rb +134 -0
- data/lib/gale/layer.rb +56 -0
- data/lib/gale/version.rb +3 -0
- metadata +123 -0
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
Gale
|
2
|
+
====
|
3
|
+
|
4
|
+
Ruby gem to read info and data from a Graphics Gale (.gal) animation file.
|
5
|
+
|
6
|
+
Note: Only works on Windows and requires the Graphics Gale DLL (galefile.dll),
|
7
|
+
available for download from http://www.humanbalance.net/gale/us/
|
8
|
+
(I have to ask for permission to distribute it with the gem, but haven't had a reply yet).
|
9
|
+
|
10
|
+
* Author: Spooner / Bil Bas (bil.bagpuss@gmail.com)
|
11
|
+
* License: MIT
|
12
|
+
|
13
|
+
Installation
|
14
|
+
------------
|
15
|
+
|
16
|
+
gem install gale
|
17
|
+
|
18
|
+
Examples
|
19
|
+
--------
|
20
|
+
|
21
|
+
# By default, gale has no external dependencies, but can only export bitmaps.
|
22
|
+
require 'gale'
|
23
|
+
animation = Gale::File.open "jumping.gal" do
|
24
|
+
puts animation.size #=> 3, which is the number of frames.
|
25
|
+
puts [animation.width, animation.height] #=> [64, 32]
|
26
|
+
puts animation[0].name #=> "Dog getting ready to jump"
|
27
|
+
puts animation[0][0].name #=> "Dog's Body"
|
28
|
+
animation[0].export_bitmap "jump_0.bmp" # Saves the first frame as a bitmap.
|
29
|
+
animation[0][0].export_alpha_channel "jump_0_0_alpha.bmp" # Saves the first layer's alpha channel
|
30
|
+
animation[0][0].export_bitmap "jump_0_0.bmp" # Saves the first layer as a bitmap.
|
31
|
+
animation.export_yaml "jump.yml", [:name, :delay] # Saves a YAML data file containing info about each frame.
|
32
|
+
end
|
33
|
+
|
34
|
+
# If using Gosu/TexPlay, then it is possible to export directly to a Gosu::Image, with transparency.
|
35
|
+
require 'gale/gosu' # Will require the gosu and texplay gems for you.
|
36
|
+
animation = Gale::File.open "jumping.gal" do
|
37
|
+
gosu_frame = animation[0].to_image #=> a Gosu::Image, being the first frame.
|
38
|
+
gosu_layer = animation[0][0].to_image #=> a Gosu::Image, being the first layer.
|
39
|
+
gosu_frames = animation.map {|f| f.to_image } #=> Array of Gosu::Image, one for each frame.
|
40
|
+
|
41
|
+
gosu_spritesheet = animation.to_spritesheet #=> a Gosu::Image, being a horizontal series of frames.
|
42
|
+
gosu_spritesheet.save "jumping.png" # Gosu images can be saved in png or bmp format.
|
43
|
+
|
44
|
+
gosu_color = Gosu::Color.from_gale animation.background_color #=> a Gosu::Color
|
45
|
+
end
|
data/lib/gale.rb
ADDED
data/lib/gale/dll.rb
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
ENV['PATH'] = File.expand_path("../../../bin", __FILE__) + File::PATH_SEPARATOR + ENV['PATH']
|
4
|
+
|
5
|
+
module Gale
|
6
|
+
# Directly exposes galefile.dll to Ruby
|
7
|
+
module Dll
|
8
|
+
extend FFI::Library
|
9
|
+
|
10
|
+
ffi_lib 'galefile'
|
11
|
+
ffi_convention :stdcall
|
12
|
+
|
13
|
+
# Sensible size for string buffer.
|
14
|
+
STRING_BUFFER_SIZE = 256
|
15
|
+
|
16
|
+
TRUE = 1
|
17
|
+
|
18
|
+
# Returned by #last_error (ggGetLastError)
|
19
|
+
module Error
|
20
|
+
NONE = 0
|
21
|
+
FILE_NOT_FOUND = 1 # File does not exist.
|
22
|
+
BAD_FORMAT = 2 # File format is invalid.
|
23
|
+
CANNOT_BE_CLOSED = 3 # File can not be closed.
|
24
|
+
INVALID_ADDRESS = 4 # The address of gale object is invalid.
|
25
|
+
PARAMETER_INVALID = 5 # Parameter is invalid.
|
26
|
+
end
|
27
|
+
|
28
|
+
# Passed to #info (ggGetInfo)
|
29
|
+
module Info
|
30
|
+
BACKGROUND_COLOR = 1 # Return value is background-color.
|
31
|
+
PALETTE_SINGLE = 2 # If the palette is single, return value is 1.
|
32
|
+
TRANSPARENCY_DISABLED = 3 # If the transparency of bottom layer is disabled, return value is 1.
|
33
|
+
BPP = 4 # Return value is bpp(1,4,8,15,16,24).
|
34
|
+
WIDTH = 5 # Return value is width of image by pixel.
|
35
|
+
HEIGHT = 6 # Return value is height of image by pixel.
|
36
|
+
end
|
37
|
+
|
38
|
+
# Passed to #frame_info (ggGetFrameInfo)
|
39
|
+
module FrameInfo
|
40
|
+
TRANSPARENT_COLOR = 1 # Return value is the transparent color.
|
41
|
+
DELAY_MS = 2 # Return value is the delay by milli-second.
|
42
|
+
DISPOSAL = 3 # Return value is the disposal type after display.
|
43
|
+
|
44
|
+
# Returned by #frame_info (ggGetFrameInfo)
|
45
|
+
module Disposal
|
46
|
+
NOT_SPECIFIED = 0 # Not specified.
|
47
|
+
NOT_DISPOSED = 1 # Not disposed.
|
48
|
+
BACKGROUND_FILL = 2 # Filled by the background-color.
|
49
|
+
RESTORE_PREVIOUS = 3 # Restored to previous state.
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Passed to #layer_info (ggGetLayerInfo)
|
54
|
+
module LayerInfo
|
55
|
+
VISIBLE = 1 # If the layer is visible, return value is 1.
|
56
|
+
TRANSPARENT_COLOR = 2 # Return value is the transparent color.
|
57
|
+
OPACITY = 3 # Return value is the opacity(0~255).
|
58
|
+
ALPHA_CHANNEL = 4 # If the alpha-channel is effective, return value is 1
|
59
|
+
end
|
60
|
+
|
61
|
+
# LPVOID __stdcall ggOpen(LPCSTR apath);
|
62
|
+
# Opens a gal file.
|
63
|
+
# @param Filename [String] of the gal file.
|
64
|
+
# @return If the function succeeds, the return value is the address of the gale object. The gale object must be deleted by ggClose. If the function fails, the return value is NULL.
|
65
|
+
attach_function :open, :ggOpen, [:string], :pointer
|
66
|
+
|
67
|
+
# LONG __stdcall ggClose(LPVOID pFile);
|
68
|
+
# Deletes a gale object.
|
69
|
+
# @param pFile The address of the gale object.
|
70
|
+
# @return If the function succeeds, the return value is 1. If the function fails, the return value is 0.
|
71
|
+
attach_function :close, :ggClose, [:pointer], :bool
|
72
|
+
|
73
|
+
#DWORD __stdcall ggGetLastError(void);
|
74
|
+
#Contents: Retrieves the latest error code.
|
75
|
+
#Parameters: Nothing.
|
76
|
+
#Return: Error code.
|
77
|
+
# 1 = File does not exist.
|
78
|
+
# 2 = File format is invalid.
|
79
|
+
# 3 = File can not be closed.
|
80
|
+
# 4 = The address of gale object is invalid.
|
81
|
+
# 5 = Parameter is invalid.
|
82
|
+
attach_function :last_error, :ggGetLastError, [], :uint
|
83
|
+
|
84
|
+
# DWORD __stdcall ggGetFrameCount(LPVOID pFile);
|
85
|
+
# Contents: Retrieves number of frame.
|
86
|
+
# Parameters: pFile = The address of the gale object.
|
87
|
+
# Return: If the function succeeds, the return value is number of frame.
|
88
|
+
# If the function fails, the return value is 0.
|
89
|
+
attach_function :frame_count, :ggGetFrameCount, [:pointer], :uint
|
90
|
+
|
91
|
+
# DWORD __stdcall ggGetLayerCount(LPVOID pFile,LONG frameNo);
|
92
|
+
# Contents: Retrieves number of layer.
|
93
|
+
# Parameters: pFile = The address of the gale object.
|
94
|
+
# frameNo = The frame index which begin from zero.
|
95
|
+
# Return: If the function succeeds, the return value is number of
|
96
|
+
# layer of specified frame.
|
97
|
+
# If the function fails, the return value is 0.
|
98
|
+
attach_function :layer_count, :ggGetLayerCount, [:pointer, :long], :uint
|
99
|
+
|
100
|
+
# LONG __stdcall ggGetInfo(LPVOID pFile,LONG nID);
|
101
|
+
# Contents: Retrieves information of gale object.
|
102
|
+
# Parameters: pFile = The address of the gale object.
|
103
|
+
# nID = Specifies information ID.
|
104
|
+
# 1 = Return value is background-color.
|
105
|
+
# 2 = If the palette is single, return value is 1.
|
106
|
+
# 3 = If the transparency of bottom layer is disabled,
|
107
|
+
# return value is 1.
|
108
|
+
# 4 = Return value is bpp(1,4,8,15,16,24).
|
109
|
+
# 5 = Return value is width of image by pixel.
|
110
|
+
# 6 = Return value is height of image by pixel.
|
111
|
+
# Return: See the Parameters.
|
112
|
+
attach_function :info, :ggGetInfo, [:pointer, :long], :long
|
113
|
+
|
114
|
+
# LONG __stdcall ggGetFrameInfo(LPVOID pFile,LONG frameNo,LONG nID);
|
115
|
+
# Contents: Retrieves information of specified frame.
|
116
|
+
# Parameters: pFile = The address of the gale object.
|
117
|
+
# frameNo = The frame index which begin from zero.
|
118
|
+
# nID = Specifies information ID.
|
119
|
+
# 1 = Return value is the transparent color.
|
120
|
+
# 2 = Return value is the delay by milli-second.
|
121
|
+
# 3 = Return value is the disposal type after display.
|
122
|
+
# 0 = Not specified.
|
123
|
+
# 1 = Not disposed.
|
124
|
+
# 2 = Filled by the background-color.
|
125
|
+
# 3 = Restored to previous state.
|
126
|
+
# Return: See the Parameters.
|
127
|
+
attach_function :frame_info, :ggGetFrameInfo, [:pointer, :long, :long], :long
|
128
|
+
|
129
|
+
# LONG __stdcall ggGetFrameName(LPVOID pFile,LONG frameNo,LPSTR pName,LONG len);
|
130
|
+
# Contents: Retrieves the name of specified frame.
|
131
|
+
# Parameters: pFile = The address of the gale object.
|
132
|
+
# frameNo = The frame index which begin from zero.
|
133
|
+
# pName = The address of string buffer that receives the
|
134
|
+
# null-terminated string specifying the name.
|
135
|
+
# If it is NULL, return value is necessary size of
|
136
|
+
# buffer.
|
137
|
+
# len = Specifies the size in byte of the buffer.
|
138
|
+
# Return: If the function succeeds, the return value is the length in
|
139
|
+
# byte, of the string copied to pName.
|
140
|
+
# If the function fails, the return value is 0.
|
141
|
+
attach_function :frame_name, :ggGetFrameName, [:pointer, :long, :buffer_out, :long], :long
|
142
|
+
|
143
|
+
# LONG __stdcall ggGetLayerInfo(LPVOID pFile,LONG frameNo,LONG layerNo,LONG nID);
|
144
|
+
# Contents: Retrieves information of specified layer.
|
145
|
+
# Parameters: pFile = The address of the gale object.
|
146
|
+
# frameNo = The frame index which begin from zero.
|
147
|
+
# layerNo = The layer index which begin from zero.
|
148
|
+
# nID = Specifies information ID.
|
149
|
+
# 1 = If the layer is visible, return value is 1.
|
150
|
+
# 2 = Return value is the transparent color.
|
151
|
+
# 3 = Return value is the opacity(0~255).
|
152
|
+
# 4 = If the alpha-channel is effective, return value is 1
|
153
|
+
# Return: See the Parameters.
|
154
|
+
attach_function :layer_info, :ggGetLayerInfo, [:pointer, :long, :long, :long], :long
|
155
|
+
|
156
|
+
# LONG __stdcall ggGetLayerName(LPVOID pFile,LONG frameNo,LONG layerNo,LPSTR pName,LONG len);
|
157
|
+
# Contents: Retrieves the name of specified layer.
|
158
|
+
# Parameters: pFile = The address of the gale object.
|
159
|
+
# frameNo = The frame index which begin from zero.
|
160
|
+
# layerNo = The layer index which begin from zero.
|
161
|
+
# pName = The address of string buffer that receives the
|
162
|
+
# null-terminated string specifying the name.
|
163
|
+
# If it is NULL, return value is necessary size of
|
164
|
+
# buffer.
|
165
|
+
# len = Specifies the size in byte of the buffer.
|
166
|
+
# Return: If the function succeeds, the return value is the length in
|
167
|
+
# byte, of the string copied to pName.
|
168
|
+
# If the function fails, the return value is 0.
|
169
|
+
attach_function :layer_name, :ggGetLayerName, [:pointer, :long, :long, :buffer_out, :long], :long
|
170
|
+
|
171
|
+
# HBITMAP __stdcall ggGetBitmap(LPVOID pFile,LONG frameNo,LONG layerNo);
|
172
|
+
# Contents: Retrieves the handle of bitmap of specified frame and
|
173
|
+
# layer. The handle must not be deleted.
|
174
|
+
# Parameters: pFile = The address of the gale object.
|
175
|
+
# frameNo = The frame index which begin from zero.
|
176
|
+
# layerNo = The layer index which begin from zero.
|
177
|
+
# If it is -1, combined image is retrieved.
|
178
|
+
# Return: If the function succeeds, the return value is the handle of
|
179
|
+
# bitmap.
|
180
|
+
# If the function fails, the return value is 0.
|
181
|
+
#attach_function :bitmap, :ggGetBitmap, [:pointer, :long, :long], :pointer
|
182
|
+
|
183
|
+
|
184
|
+
#HBITMAP __stdcall ggGetAlphaChannel(LPVOID pFile,LONG frameNo,LONG layerNo);
|
185
|
+
# Contents: Retrieves the handle of bitmap of alpha channel of specified
|
186
|
+
# frame and layer. The handle must not be deleted.
|
187
|
+
# Parameters: pFile = The address of the gale object.
|
188
|
+
# frameNo = The frame index which begin from zero.
|
189
|
+
# layerNo = The layer index which begin from zero.
|
190
|
+
# Return: If the function succeeds, the return value is the handle of
|
191
|
+
# bitmap.
|
192
|
+
# If the function fails, the return value is 0.
|
193
|
+
#attach_function :alpha_channel, :ggGetAlphaChannel, [:pointer, :long, :long], :pointer
|
194
|
+
|
195
|
+
|
196
|
+
#HPALETTE __stdcall ggGetPalette(LPVOID pFile,LONG frameNo);
|
197
|
+
# Contents: Retrieves the handle of palette of specified frame.
|
198
|
+
# The handle must not be deleted.
|
199
|
+
# Parameters: pFile = The address of the gale object.
|
200
|
+
# frameNo = The frame index which begin from zero.
|
201
|
+
# Return: If the function succeeds, the return value is the handle of
|
202
|
+
# palette.
|
203
|
+
# If the function fails, the return value is 0.
|
204
|
+
#attach_function :palette, :ggGetPalette, [:pointer, :long], :pointer
|
205
|
+
|
206
|
+
|
207
|
+
#LONG __stdcall ggDrawBitmap(LPVOID pFile,LONG frameNo,LONG layerNo,HDC toDC,LONG toX,LONG toY);
|
208
|
+
# Contents: Draws the image of specified frame and layer to specified
|
209
|
+
# device context.
|
210
|
+
# Parameters: pFile = The address of the gale object.
|
211
|
+
# frameNo = The frame index which begin from zero.
|
212
|
+
# layerNo = The layer index which begin from zero.
|
213
|
+
# If it is -1, combined image is retrieved.
|
214
|
+
# toDC = The handle of device context of the destination.
|
215
|
+
# toX = Specifies the x-coordinate of the destination.
|
216
|
+
# toY = Specifies the y-coordinate of the destination.
|
217
|
+
# Return: If the function succeeds, the return value is 1.
|
218
|
+
# If the function fails, the return value is 0.
|
219
|
+
|
220
|
+
#LONG __stdcall ggExportBitmap(LPVOID pFile,LONG frameNo,LONG layerNo,LPCSTR outPath);
|
221
|
+
# Contents: Creates a bmp file from the image of specified frame and
|
222
|
+
# layer.
|
223
|
+
# Parameters: pFile = The address of the gale object.
|
224
|
+
# frameNo = The frame index which begin from zero.
|
225
|
+
# layerNo = The layer index which begin from zero.
|
226
|
+
# If it is -1, combined image is created.
|
227
|
+
# outPath = The filename for output.
|
228
|
+
# Return: If the function succeeds, the return value is 1.
|
229
|
+
# If the function fails, the return value is 0.
|
230
|
+
attach_function :export_bitmap, :ggExportBitmap, [:pointer, :long, :long, :string], :long
|
231
|
+
|
232
|
+
|
233
|
+
#LONG __stdcall ggExportAlphaChannel(LPVOID pFile,LONG frameNo,LONG layerNo,LPCSTR outPath);
|
234
|
+
# Contents: Creates a bmp file from the alpha channel of specified frame
|
235
|
+
# and layer.
|
236
|
+
# Parameters: pFile = The address of the gale object.
|
237
|
+
# frameNo = The frame index which begin from zero.
|
238
|
+
# layerNo = The layer index which begin from zero.
|
239
|
+
# outPath = The filename for output.
|
240
|
+
# Return: If the function succeeds, the return value is 1.
|
241
|
+
# If the function fails, the return value is 0.
|
242
|
+
attach_function :export_alpha_channel, :ggExportAlphaChannel, [:pointer, :long, :long, :string], :long
|
243
|
+
end
|
244
|
+
end
|
data/lib/gale/file.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Gale
|
4
|
+
class FormatError < StandardError; end
|
5
|
+
|
6
|
+
# A GraphicsGale image, containing Frames and Layers.
|
7
|
+
class File
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# Just for use by Frame/Layer
|
11
|
+
attr_reader :handle
|
12
|
+
protected :handle
|
13
|
+
|
14
|
+
class << self
|
15
|
+
alias_method :open, :new
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(filename)
|
19
|
+
@handle = Dll.open filename
|
20
|
+
if @handle.null?
|
21
|
+
case Dll.last_error
|
22
|
+
when Dll::Error::FILE_NOT_FOUND
|
23
|
+
raise Errno::ENOENT, "File not found: #{filename}"
|
24
|
+
when Dll::Error::BAD_FORMAT
|
25
|
+
raise FormatError, "File not in GraphicsGale format: #{filename}"
|
26
|
+
else
|
27
|
+
raise "Unknown error opening: #{filename}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
num_frames = Dll.frame_count @handle
|
32
|
+
@frames = num_frames.times.map {|i| Frame.new self, i }
|
33
|
+
|
34
|
+
if block_given?
|
35
|
+
begin
|
36
|
+
yield self
|
37
|
+
ensure
|
38
|
+
close
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def each_frame(&block)
|
44
|
+
@frames.each(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
alias_method :each, :each_frame
|
48
|
+
|
49
|
+
def size
|
50
|
+
@frames.size
|
51
|
+
end
|
52
|
+
|
53
|
+
def [](frame_index)
|
54
|
+
@frames[frame_index]
|
55
|
+
end
|
56
|
+
|
57
|
+
def close
|
58
|
+
Dll.close @handle
|
59
|
+
@handle = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def height; @height ||= Dll.info @handle, Dll::Info::HEIGHT; end
|
63
|
+
def width; @width ||= Dll.info @handle, Dll::Info::WIDTH; end
|
64
|
+
def bits_per_pixel; @bits_per_pixel ||= Dll.info @handle, Dll::Info::BPP; end
|
65
|
+
|
66
|
+
def background_color
|
67
|
+
@background_color ||= Dll.info @handle, Dll::Info::BACKGROUND_COLOR
|
68
|
+
end
|
69
|
+
|
70
|
+
def transparency_disabled?
|
71
|
+
@transparency_disabled ||= begin
|
72
|
+
value = Dll.info @handle, Dll::Info::TRANSPARENCY_DISABLED
|
73
|
+
value == Dll::TRUE
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def palette_single?
|
78
|
+
@palette_single ||= begin
|
79
|
+
value = Dll.info @handle, Dll::Info::PALETTE_SINGLE
|
80
|
+
value == Dll::TRUE
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param properties [Array<Symbol>] One or more of [:name, :transparent_color, :transparent_color_hex, :delay, :disposal]
|
85
|
+
def export_yaml(filename, properties)
|
86
|
+
data = @frames.map do |frame|
|
87
|
+
frame_data = {}
|
88
|
+
frame_data[:name] = "".sub(//, frame.name) if properties.include? :name
|
89
|
+
|
90
|
+
hex_color = frame.transparent_color? ? ("%06x" % frame.transparent_color) : nil
|
91
|
+
frame_data[:transparent_color] = frame.transparent_color if properties.include? :transparent_color
|
92
|
+
frame_data[:transparent_color_hex] = hex_color if properties.include? :transparent_color_hex
|
93
|
+
|
94
|
+
frame_data[:delay] = frame.delay if properties.include? :delay
|
95
|
+
frame_data[:disposal] = frame.disposal if properties.include? :disposal
|
96
|
+
|
97
|
+
raise ArgumentError, "Must specify at least some :properties to export" if frame_data.empty?
|
98
|
+
|
99
|
+
frame_data
|
100
|
+
end
|
101
|
+
|
102
|
+
::File.open(filename, "w") {|f| f.puts data.to_yaml }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/gale/frame.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module Gale
|
2
|
+
class Frame
|
3
|
+
include Enumerable
|
4
|
+
attr_reader :file, :index
|
5
|
+
|
6
|
+
def initialize(file, index)
|
7
|
+
@file, @index = file, index
|
8
|
+
|
9
|
+
num_layers = Dll.layer_count file.send(:handle), index
|
10
|
+
@layers = num_layers.times.map {|i| Layer.new file, self, i }
|
11
|
+
end
|
12
|
+
|
13
|
+
def each_layer(&block)
|
14
|
+
@layers.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :each, :each_layer
|
18
|
+
|
19
|
+
def size
|
20
|
+
@layers.size
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](layer_index)
|
24
|
+
@layers[layer_index]
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
@name ||= begin
|
29
|
+
buffer = FFI::Buffer.new Dll::STRING_BUFFER_SIZE
|
30
|
+
length = Dll.frame_name file.send(:handle), index, buffer, buffer.size
|
31
|
+
buffer.get_string 0, length
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def delay
|
36
|
+
@delay ||= Dll.frame_info file.send(:handle), index, Dll::FrameInfo::DELAY_MS
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Integer, nil] 0xRRGGBB or nil if transparency disabled.
|
40
|
+
def transparent_color
|
41
|
+
@transparent_color ||= begin
|
42
|
+
value = Dll.frame_info file.send(:handle), index, Dll::FrameInfo::TRANSPARENT_COLOR
|
43
|
+
(value == -1) ? nil : value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Boolean] true if a transparent color has been set.
|
48
|
+
def transparent_color?
|
49
|
+
not transparent_color.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [:none, :no_disposal, :background, :previous]
|
53
|
+
def disposal
|
54
|
+
@disposal ||= begin
|
55
|
+
value = Dll.frame_info file.send(:handle), index, Dll::FrameInfo::DISPOSAL
|
56
|
+
case value
|
57
|
+
when Dll::FrameInfo::Disposal::NOT_SPECIFIED
|
58
|
+
:none
|
59
|
+
when Dll::FrameInfo::Disposal::NOT_DISPOSED
|
60
|
+
:no_disposal
|
61
|
+
when Dll::FrameInfo::Disposal::BACKGROUND_FILL
|
62
|
+
:background
|
63
|
+
when Dll::FrameInfo::Disposal::RESTORE_PREVIOUS
|
64
|
+
:previous
|
65
|
+
else
|
66
|
+
raise "Unknown disposal value #{value}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def export_bitmap(filename)
|
72
|
+
result = Dll.export_bitmap file.send(:handle), index, -1, filename
|
73
|
+
raise "Export failed" if result == 0
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/gale/gosu.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
require 'gosu'
|
4
|
+
require 'texplay'
|
5
|
+
|
6
|
+
require 'gale'
|
7
|
+
|
8
|
+
module Gosu
|
9
|
+
class Color
|
10
|
+
class << self
|
11
|
+
# Create Color from an opaque color from a Graphics Gale file.
|
12
|
+
# @param color [Integer] 0xrrggbb
|
13
|
+
def from_gale(color)
|
14
|
+
rgb (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Gale
|
21
|
+
class File
|
22
|
+
# Create a sprite-sheet from the frames in the File. By default, this will be a horizontal strip.
|
23
|
+
#
|
24
|
+
# @option :columns [Integer] (#size) Number of columns to use. Will leave excess columns empty.
|
25
|
+
# @option :window [Gosu::Window] ($window) Window used to create the image.
|
26
|
+
# @return Gosu::Image
|
27
|
+
def to_spritesheet(options = {})
|
28
|
+
options = {
|
29
|
+
:columns => size,
|
30
|
+
:window => $window,
|
31
|
+
}.merge! options
|
32
|
+
|
33
|
+
columns = options[:columns]
|
34
|
+
rows = size.fdiv(columns).ceil
|
35
|
+
|
36
|
+
sheet = TexPlay.create_image options[:window], columns * width, rows * height, :caching => true
|
37
|
+
|
38
|
+
each do |frame|
|
39
|
+
row, column = frame.index.divmod columns
|
40
|
+
sheet.splice frame.to_image, column * width, row * height
|
41
|
+
end
|
42
|
+
sheet
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Frame
|
47
|
+
# @option :window [Gosu::Window] ($window) Window used to create the image.
|
48
|
+
# @return Gosu::Image
|
49
|
+
def to_image(options = {})
|
50
|
+
options = {
|
51
|
+
:window => $window,
|
52
|
+
}.merge! options
|
53
|
+
|
54
|
+
# Hack because I have no idea how to make #to_blob properly.
|
55
|
+
bitmap = Tempfile.new 'gale_bitmap'
|
56
|
+
image = nil
|
57
|
+
begin
|
58
|
+
bitmap.close # Don't actually use it directly, since we are going to overwrite it.
|
59
|
+
export_bitmap bitmap.path
|
60
|
+
|
61
|
+
image = Gosu::Image.new options[:window], bitmap.path, :caching => true
|
62
|
+
# TODO: Should use disposal to add a background or whatever.
|
63
|
+
|
64
|
+
if transparent_color?
|
65
|
+
# We want only to clear the alpha channel, not the whole bit to transparent black.
|
66
|
+
color_to_replace = Gosu::Color.from_gale(transparent_color)
|
67
|
+
replace_with = color_to_replace.dup
|
68
|
+
replace_with.alpha = 0
|
69
|
+
image.clear :dest_select => color_to_replace, :tolerance => 0.001, :color => replace_with
|
70
|
+
end
|
71
|
+
ensure
|
72
|
+
bitmap.unlink
|
73
|
+
end
|
74
|
+
|
75
|
+
image
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Layer
|
80
|
+
# @option :window [Gosu::Window] ($window) Window used to create the image.
|
81
|
+
# @return Gosu::Image
|
82
|
+
def to_image(options = {})
|
83
|
+
options = {
|
84
|
+
:window => $window,
|
85
|
+
}.merge! options
|
86
|
+
|
87
|
+
# Hack because I have no idea how to make #to_blob properly.
|
88
|
+
bitmap = Tempfile.new 'gale_bitmap'
|
89
|
+
alpha_channel = alpha_channel? ? Tempfile.new('gale_alpha_channel') : nil
|
90
|
+
image = nil
|
91
|
+
begin
|
92
|
+
bitmap.close # Don't actually use it directly, since we are going to overwrite it.
|
93
|
+
export_bitmap bitmap.path
|
94
|
+
|
95
|
+
if alpha_channel
|
96
|
+
alpha_channel.close
|
97
|
+
export_alpha_channel alpha_channel.path
|
98
|
+
end
|
99
|
+
|
100
|
+
image = Gosu::Image.new options[:window], bitmap.path, :caching => true
|
101
|
+
if alpha_channel?
|
102
|
+
# Multiply by alpha channel image.
|
103
|
+
ac_image = Gosu::Image.new options[:window], alpha_channel.path, :caching => true
|
104
|
+
image.splice ac_image, 0, 0, :color_control => lambda {|pixel, alpha|
|
105
|
+
# alpha will be black to white (transparent to opaque).
|
106
|
+
pixel[3] *= alpha[0]
|
107
|
+
pixel
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
if transparent_color?
|
112
|
+
color_to_replace = Gosu::Color.from_gale(transparent_color)
|
113
|
+
replace_with = color_to_replace.dup
|
114
|
+
replace_with.alpha = 0
|
115
|
+
image.clear :dest_select => color_to_replace, :tolerance => 0.001, :color => replace_with
|
116
|
+
end
|
117
|
+
|
118
|
+
# Fade out if opacity is low.
|
119
|
+
if opacity < 255
|
120
|
+
factor = opacity / 255.0
|
121
|
+
image.each do |c|
|
122
|
+
c[3] *= factor
|
123
|
+
c
|
124
|
+
end
|
125
|
+
end
|
126
|
+
ensure
|
127
|
+
bitmap.unlink
|
128
|
+
alpha_channel.unlink if alpha_channel
|
129
|
+
end
|
130
|
+
|
131
|
+
image
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/gale/layer.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Gale
|
2
|
+
class Layer
|
3
|
+
attr_reader :file, :frame, :index
|
4
|
+
|
5
|
+
def initialize(file, frame, index)
|
6
|
+
@file, @frame, @index = file, frame, index
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
@name ||= begin
|
11
|
+
buffer = FFI::Buffer.new Dll::STRING_BUFFER_SIZE
|
12
|
+
length = Dll.layer_name file.send(:handle), frame.index, index, buffer, buffer.size
|
13
|
+
buffer.get_string 0, length
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def visible?
|
18
|
+
@visible ||= Dll.layer_info(file.send(:handle), frame.index, index, Dll::LayerInfo::VISIBLE) == Dll::TRUE
|
19
|
+
end
|
20
|
+
|
21
|
+
def alpha_channel?
|
22
|
+
@alpha_channel ||= Dll.layer_info(file.send(:handle), frame.index, index, Dll::LayerInfo::ALPHA_CHANNEL) == Dll::TRUE
|
23
|
+
end
|
24
|
+
|
25
|
+
# Layer opacity
|
26
|
+
# @return [Integer] 0..255 for transparent to opaque.
|
27
|
+
def opacity
|
28
|
+
@opacity ||= Dll.layer_info file.send(:handle), frame.index, index, Dll::LayerInfo::OPACITY
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Integer, nil] 0xRRGGBB or nil if transparency disabled.
|
32
|
+
def transparent_color
|
33
|
+
@transparent_color ||= begin
|
34
|
+
value = Dll.layer_info file.send(:handle), frame.index, index, Dll::LayerInfo::TRANSPARENT_COLOR
|
35
|
+
value == -1 ? nil : value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Boolean] true if a transparent color has been set.
|
40
|
+
def transparent_color?
|
41
|
+
not transparent_color.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
def export_bitmap(filename)
|
45
|
+
result = Dll.export_bitmap file.send(:handle), frame.index, index, filename
|
46
|
+
raise "Export failed" if result == 0
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def export_alpha_channel(filename)
|
51
|
+
result = Dll.export_alpha_channel file.send(:handle), frame.index, index, filename
|
52
|
+
raise "Export failed" if result == 0
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/gale/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gale
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1alpha
|
5
|
+
prerelease: 5
|
6
|
+
platform: x86-mingw32
|
7
|
+
authors:
|
8
|
+
- Bil Bas (Spooner)
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ffi
|
16
|
+
requirement: &28062996 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.11
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *28062996
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: gosu
|
27
|
+
requirement: &28062120 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.7.41
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *28062120
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: texplay
|
38
|
+
requirement: &28039068 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.3.5
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *28039068
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &28038240 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.2.2
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *28038240
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rspec
|
60
|
+
requirement: &28037304 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 2.8.0
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *28037304
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: &28036752 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.6.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *28036752
|
80
|
+
description:
|
81
|
+
email:
|
82
|
+
- bil.bagpuss@gmail.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- lib/gale/dll.rb
|
88
|
+
- lib/gale/file.rb
|
89
|
+
- lib/gale/frame.rb
|
90
|
+
- lib/gale/gosu.rb
|
91
|
+
- lib/gale/layer.rb
|
92
|
+
- lib/gale/version.rb
|
93
|
+
- lib/gale.rb
|
94
|
+
- README.md
|
95
|
+
homepage: http://spooner.github.com/libraries/gale/
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
hash: 93171905
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ! '>'
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.3.1
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project: gale
|
119
|
+
rubygems_version: 1.8.16
|
120
|
+
signing_key:
|
121
|
+
specification_version: 3
|
122
|
+
summary: Read Graphics Gale (.gal) files
|
123
|
+
test_files: []
|