在MS Paint上编写绘画程序 - 如何在鼠标移动事件之间进行插值?

Hei*_*mus 11 user-interface interpolation wxwidgets paint mouseover

我想以MS Paint的风格编写一个绘画程序.

为了在用户移动鼠标时在屏幕上绘画,我必须等待鼠标移动事件并在我收到鼠标时在屏幕上绘图.显然,mose移动事件不经常发送,所以我必须通过在当前鼠标位置和前一个鼠标位置之间画一条线来插值鼠标移动.在伪代码中,这看起来像这样:

var positionOld = null

def handleMouseMove(positionNew):
    if mouse.button.down:
        if positionOld == null:
            positionOld = positionNew
        screen.draw.line(positionOld,positionNew)
        positionOld = positionNew
Run Code Online (Sandbox Code Playgroud)

现在我的问题是:使用直线段进行插值看起来太符合我的口味了,你能推荐一种更好的插值方法吗?GIMP或Adobe Photoshop采用什么方法?

或者,有没有办法增加我收到的鼠标移动事件的频率?我正在使用的GUI框架是wxWidgets.

GUI框架:wxWidgets.
(编程语言:Haskell,但这里不相关)

编辑:澄清:我想要看起来比直线段更平滑的东西,看图片(原始大小):

在鼠标位置之间绘制的锯齿状线条http://i26.tinypic.com/hwa42h.jpg

EDIT2:我使用的代码如下所示:

-- create bitmap and derive drawing context
im      <- imageCreateSized (sy 800 600)
bitmap  <- bitmapCreateFromImage im (-1)    -- wxBitmap
dc      <- memoryDCCreate                   -- wxMemoryDC
memoryDCSelectObject dc bitmap

...
-- handle mouse move
onMouse ... sw (MouseLeftDrag posNew _) = do
    ...
    line dc posOld posNew [color     := white
                          , penJoin  := JoinRound
                          , penWidth := 2]
    repaint sw                              -- a wxScrolledWindow

-- handle paint event
onPaint ... = do
    ...
    -- draw bitmap on the wxScrolledWindow
    drawBitmap dc_sw bitmap pointZero False []
Run Code Online (Sandbox Code Playgroud)

这可能会有所作为.也许我对wx-classes的选择就是为什么我的鼠标移动事件频率相当低.

Hei*_*mus 1

用线段插值鼠标移动很好,GIMP 也这样做,如以下来自非常快速的鼠标移动的屏幕截图所示:

GIMP 也使用线段

因此,平滑度来自于高频率的鼠标移动事件。WxWidgets 可以做到这一点,如相关问题的示例代码所示。

问题出在你的代码中,海因里希。也就是说,先绘制一个大位图,然后将整个位图复制到屏幕上,这并不便宜!要估计您需要的效率,请将您的问题与视频游戏进行比较:每秒 30 个鼠标移动事件的平滑速率对应于 30 fps。复制双缓冲区对于现代机器来说没有问题,但 WxHaskell 可能没有针对视频游戏进行优化,因此您遇到一些抖动也就不足为奇了。

解决方案是直接在屏幕上仅绘制必要的内容,即仅绘制线条,例如上面的链接所示。