gale 0.0.1alpha-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'gale/dll'
2
+
3
+ require 'gale/layer'
4
+ require 'gale/frame'
5
+ require 'gale/file'
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ module Gale
2
+ VERSION = "0.0.1alpha"
3
+ end
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: []