require"imlua" require"cdlua" require"cdluaim" require"iuplua" require"iupluacd" require"iupluatuio" cnv = iup.canvas{rastersize = "1024x768", border = "NO", touch="Yes"} img_x = 0 img_y = 0 -- comment this line to NOT use the TUIO client, only Windows 7 supports multi-touch tuio = iup.tuioclient{} function load_image(filename) local new_image = im.FileImageLoadBitmap(filename) if (not new_image) then iup.Message("Error", "LoadBitmap failed.") else if (image) then image:Destroy() end loaded = true image = new_image iup.Update(cnv) end end function cnv:map_cb() -- the CD canvas can only be created when the IUP canvas is mapped canvas = cd.CreateCanvas(cd.IUP, self) end function cnv:action() -- called everytime the IUP canvas needs to be repainted canvas:Activate() canvas:Clear() if (image) then if (loaded) then local cnv_w, cnv_h = canvas:GetSize() -- inicial zoom and position img_w = image:Width() img_h = image:Height() img_x = (cnv_w-img_w)/2 img_y = (cnv_h-img_h)/2 loaded = false end image:cdCanvasPutImageRect(canvas, img_x, img_y, img_w, img_h, 0, 0, 0, 0) -- use default values end end function cnv:multitouch_cb(count, pid, px, py, pstatus) if (count == 1) then if (pstatus[1] == string.byte('D')) then -- DOWN old_x = px[1] old_y = canvas:UpdateYAxis(py[1]) translate = 1 elseif (pstatus[1] == string.byte('U')) then -- UP if (translate == 1) then translate = 0 end elseif (pstatus[1] == string.byte('M')) then -- MOVE if (translate == 1) then -- translate only local y = canvas:UpdateYAxis(py[1]) local x = px[1] img_x = img_x + (x - old_x) img_y = img_y + (y - old_y) old_x = x old_y = y iup.Update(cnv) end end elseif (count == 2) then if (pstatus[1] == string.byte('D') or pstatus[2] == string.byte('D')) then -- DOWN diff_x = math.abs(px[2]-px[1]) diff_y = math.abs(py[2]-py[1]) ref_x = img_x+img_w/2 -- center of the image as reference ref_y = img_y+img_h/2 old_angle = math.atan2(py[2]-py[1], px[2]-px[1]) zoom = 1 elseif (pstatus[1] == string.byte('U') or pstatus[2] == string.byte('U')) then -- UP if (zoom == 1) then zoom = 0 end elseif (pstatus[1] == string.byte('M') or pstatus[2] == string.byte('M')) then -- MOVE if (zoom == 1) then -- zoom local new_diff_x = math.abs(px[2]-px[1]) local new_diff_y = math.abs(py[2]-py[1]) local angle = math.atan2(py[2]-py[1], px[2]-px[1]) local abs_diff_x = new_diff_x-diff_x local abs_diff_y = new_diff_y-diff_y local diff = 0 if (math.abs(abs_diff_y) > math.abs(abs_diff_x)) then diff = abs_diff_y else diff = abs_diff_x end local prev_w = img_w local prev_h = img_h img_w = img_w + diff img_h = img_h + diff local str = string.format("%g %d %d", -(angle-old_angle)*cd.RAD2DEG, ref_x, ref_y) print("ROTATE=", str) canvas:SetAttribute("ROTATE", str) -- translate to maintain fixed the reference point local orig_x = ref_x - img_x local orig_y = ref_y - img_y orig_x = (img_w/prev_w)*orig_x orig_y = (img_h/prev_h)*orig_y img_x = ref_x - orig_x img_y = ref_y - orig_y diff_x = new_diff_x diff_y = new_diff_y iup.Update(cnv) end end end end function cnv:button_cb(button,pressed,x,y,status) -- start drag if button1 is pressed if button ==iup.BUTTON1 and pressed == 1 then y = canvas:UpdateYAxis(y) old_x = x old_y = y start_x = x start_y = y drag = 1 else if (drag == 1) then drag = 0 end end end function cnv:motion_cb(x,y,status) if (drag == 1) then y = canvas:UpdateYAxis(y) if (iup.iscontrol(status)) then -- zoom local diff_x = (x - old_x) local diff_y = (y - old_y) local diff = 0 if (math.abs(diff_y) > math.abs(diff_x)) then diff = diff_y else diff = diff_x end local prev_w = img_w local prev_h = img_h img_w = img_w + diff img_h = img_h + diff -- translate to maintain fixed the reference point local orig_x = start_x - img_x local orig_y = start_y - img_y orig_x = (img_w/prev_w)*orig_x orig_y = (img_h/prev_h)*orig_y img_x = start_x - orig_x img_y = start_y - orig_y else -- translate only img_x = img_x + (x - old_x) img_y = img_y + (y - old_y) end old_x = x old_y = y iup.Update(cnv) end end function cnv:k_any(c) if c == iup.K_q or c == iup.K_ESC then return iup.CLOSE end if c == iup.K_F1 then if fullscreen then fullscreen = false dlg.fullscreen = "No" else fullscreen = true dlg.fullscreen = "Yes" end end if c == iup.K_F2 then filename = iup.GetFile("*.*") if (filename) then load_image(filename) end end end dlg = iup.dialog{cnv} function dlg:close_cb() if (image) then image:Destroy() end canvas:Kill() self:destroy() return iup.IGNORE -- because we destroy the dialog end if (tuio) then tuio.connect = "YES" tuio.targetcanvas = cnv end dlg:show() cnv.rastersize = nil -- remove minimum size if arg and arg[1] ~= nil then filename = arg[1] else filename = iup.GetFile("*.*") end if (filename) then load_image(filename) end if (iup.MainLoopLevel()==0) then iup.MainLoop() end