1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
-- Based on a code from Stuart P. Bentley
require"imlua"
require"cdlua"
require"cdluaim"
require"iuplua"
require"iupluacd"
require"iupluaimglib"
anim={}
function print_error(err)
local msg = {}
msg[im.ERR_OPEN] = "Error Opening File."
msg[im.ERR_MEM] = "Insuficient memory."
msg[im.ERR_ACCESS] = "Error Accessing File."
msg[im.ERR_DATA] = "Image type not Suported."
msg[im.ERR_FORMAT] = "Invalid Format."
msg[im.ERR_COMPRESS] = "Invalid or unsupported compression."
if msg[err] then
print(msg[err])
else
print("Unknown Error.")
end
end
function load_frames(file_name)
ifile, err=im.FileOpen(file_name)
if not ifile then
print_error(err)
return
end
anim.images={}
anim.delays={}
anim.disposal={}
anim.pos={}
anim.frame=1
local ScreenWidth = 0
local ScreenHeight = 0
for i=1, select(3,ifile:GetInfo()) do
anim.images[i]=ifile:LoadBitmap(i-1)
err, anim.images[i] = im.ConvertColorSpaceNew(anim.images[i], im.RGB, true)
local delay=anim.images[i]:GetAttribute("Delay") -- time to wait betweed frames in 1/100 of a second]
if delay then
anim.delays[i]=delay[1]*10 -- timer in miliseconds
else
if (i == 1) then
anim.delays[i]=100
else
anim.delays[i]=anim.delays[i-1]
end
end
anim.disposal[i]=anim.images[i]:GetAttribute("Disposal", true) -- [UNDEF, LEAVE, RBACK, RPREV]
local w = anim.images[i]:Width()
local h = anim.images[i]:Height()
if (w > ScreenWidth) then ScreenWidth = w end
if (h > ScreenHeight) then ScreenHeight = h end
w = anim.images[i]:GetAttribute("ScreenWidth")
h = anim.images[i]:GetAttribute("ScreenHeight")
if (w and w[1] > ScreenWidth) then ScreenWidth = w[1] end
if (h and h[1] > ScreenHeight) then ScreenHeight = h[1] end
local X = anim.images[i]:GetAttribute("XScreen")
local Y = anim.images[i]:GetAttribute("YScreen")
anim.pos[i] = {x=0, y=0}
if (X) then anim.pos[i].x = X[1] end
if (Y) then anim.pos[i].y = Y[1] end
end
ifile:Close()
anim.ScreenHeight = ScreenHeight
anim.ScreenWidth = ScreenWidth
cnv.rastersize = ScreenWidth.."x"..ScreenHeight
dlg.size=nil
iup.Refresh(cnv)
end
t = iup.timer{}
function start_timer()
dlg.title = "Animated Gif"
dlg.play_bt.image="IUP_MediaPause" dlg.play_bt.title="Pause"
t.run = "NO"
t.time = anim.delays[anim.frame]
t.run = "YES"
iup.Update(cnv)
end
function stop_timer()
dlg.title = "Animated Gif "..anim.frame.."/"..#anim
dlg.play_bt.image="IUP_MediaPlay" dlg.play_bt.title="Play"
t.run="NO"
iup.Update(cnv)
end
function set_frame(f)
anim.frame = f
if anim.frame > #anim.images then
anim.frame = #anim.images
end
if anim.frame < 1 then
anim.frame = 1
end
stop_timer()
end
function t:action_cb()
anim.frame = anim.frame + 1
if anim.frame == #anim.images+1 then
anim.frame = 1
end
start_timer()
end
cnv = iup.canvas{border = "NO"}
function cnv:map_cb()-- the CD canvas can only be created when the IUP canvas is mapped
canvas = cd.CreateCanvas(cd.IUP, self)
canvas:Activate()
start_timer()
end
function cnv:action()-- called everytime the IUP canvas needs to be repainted
canvas:Activate()
if (anim.disposal[anim.frame] == "RBACK") then
canvas:Clear()
end
local x = anim.pos[anim.frame].x
local y = anim.ScreenHeight - anim.pos[anim.frame].y - anim.images[anim.frame]:Height()
anim.images[anim.frame]:cdCanvasPutImageRect(canvas, x, y, 0, 0, 0, 0, 0, 0) -- use default values
end
function cnv:resize_cb()
canvas:Activate()
canvas:Clear()
end
function cnv:button_cb(but, pressed)
if (but == iup.BUTTON1 and pressed==1) then
local file_name, error = iup.GetFile("*.*")
if error ~= 0 then
return
end
load_frames(file_name)
canvas:Activate()
canvas:Clear()
start_timer()
end
end
buts = iup.hbox{
iup.button{title="First", image="IUP_MediaGotoBegin", action=function(self) set_frame(1) end},
iup.button{title="Previous", image="IUP_MediaRewind", action=function(self) set_frame(anim.frame-1) end},
iup.button{title="Pause", image="IUP_MediaPause", action=function(self) if (t.run=="YES") then stop_timer() else start_timer() end end},
iup.button{title="Next", image="IUP_MediaForward", action=function(self) set_frame(anim.frame+1) end},
iup.button{title="Last", image="IUP_MediaGoToEnd", action=function(self) set_frame(#anim) end},
}
dlg = iup.dialog{iup.vbox{cnv, buts},title="Animated Gif", margin="5x5", gap=10}
dlg.play_bt = dlg[1][2][3]
function dlg:close_cb()
iup.Destroy(t)
anim=nil --Destroys will be called by the garbage collector
canvas:Kill()
self:destroy()
return iup.IGNORE -- because we destroy the dialog
end
load_frames(iup.GetFile("*.*"))
dlg:show()
iup.MainLoop()
|