summaryrefslogtreecommitdiff
path: root/html/examples/animate_gif.wlua
blob: 04d69e02ba335bb876fe5d10b3b1f283df9d319a (plain)
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()