如何防止图形口吃滚动大缩小图像时, [英] How to prevent Graphical stutter when scrolling a large zoomed out picture

查看:105
本文介绍了如何防止图形口吃滚动大缩小图像时,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个大的TIFF图片(5.9兆,13K点¯x16K reolution)用户加载到一个滚动面板,他则可以放大/缩小的,滚动和标记点,区域等上。



对于我使用的修改滚动双缓冲面板鲍勃·鲍威尔的真棒ZoomPicBox
的面板显示目前在查看照片的只是一部分。



在缩小(即使interpolationMode滚动图像时出现的口吃被设置为低)



有没有什么事情,可不能做到(最好是没有硬件加速)?



面板的油漆事件:

 保护覆盖无效的OnPaint(System.Windows.Forms.PaintEventArgs E)
{
如果(_image == NULL)
{
base.OnPaintBackground(E);
的回报;
}

//规模
System.Drawing.Drawing2D.Matrix ScaleMat =新System.Drawing.Drawing2D.Matrix(_zoom,0,0,_zoom,0,0) ;
//移到scrollbas
ScaleMat.Translate的位置(this.AutoScrollPosition.X /(_zoom),this.AutoScrollPosition.Y /(_zoom));


e.Graphics.Transform = ScaleMat;
e.Graphics.InterpolationMode = _interpolationMode;

e.Graphics.DrawImage(_image,新矩形(0,0,_image.Width,_image.Height),0,0,_image.Width,_image.Height,GraphicsUnit.Pixel);


base.OnPaint(E);
}




  • _zoom,_image和_interpolationMode是私人领域控制



构造:

 公共PicBoxPlus()
{
的MouseMove + = PicBoxPlus_MouseMove;
的KeyDown + = PicBoxPlus_KeyDown;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer,真正的);

this.AutoScroll = TRUE;
}



编辑:尝试缓存



我试图实施Sinatr的代码,但什么是错的,因为我得到的是一个黑色的图像(大小合适)。 ?任何人有一个想法可能是错误的。



新绘制事件:

 保护覆盖无效的OnPaint(System.Windows.Forms.PaintEventArgs E)
{
如果(mCachedImage == NULL)
{
base.OnPaintBackground(E);
的回报;
}

//规模
System.Drawing.Drawing2D.Matrix ScaleMat =新System.Drawing.Drawing2D.Matrix(mZoom,0,0,mZoom,0,0) ;
//移到scrollbas
ScaleMat.Translate(this.AutoScrollPosition.X /(mZoom),this.AutoScrollPosition.Y /(mZoom))的位置;


{
如果(mCachedImage == NULL)
{
mCachedImage =新位图(this.ClientSize.Width,this.ClientSize.Height );
使用(VAR cacheGraphics = Graphics.FromImage(mCachedImage))
{
cacheGraphics.Transform = ScaleMat;
cacheGraphics.InterpolationMode = _interpolationMode;
cacheGraphics.DrawImage(mCachedImage,新矩形(0,0,mCachedImage.Width,mCachedImage.Height),0,0,mCachedImage.Width,mCachedImage.Height,GraphicsUnit.Pixel);

}

e.Graphics.DrawImage(mCachedImage,Point.Empty);
}
}
赶上(异常前)
{
罚球前;
}

base.OnPaint(E);
}

图片和缩放性能:

 公共位图图像
{
{返回mCachedImage; }

{
mCachedImage =价值;
UpdateScaleFactor();
this.Invalidate();
}
}

公共单身变焦
{
{返回mZoom; }

{
如果(价值< = 0 ||值< 0.001)
{
值= 0.001f;
}

mZoom =价值;
UpdateScaleFactor();
ResetCache(); // Sinatr的功能
this.Invalidate();
}
}



从主窗体加载图片:

  panelMap.Image =(位图)Image.FromFile(pic.tiff); 


解决方案

是不是测试,但应该给个主意。

 位图_cached = NULL; 

覆盖无效的OnPaint(PaintEventArgs的E)
{
如果(_cached == NULL)
{
_cached =新位图(this.ClientSize.Width ,this.ClientSize.Height);使用(VAR图形
= Graphics.FromImage(_cached)
{
//绘制到此图形一次 - >其将在_cached位
缓存}
}
e.Graphics.DrawImage(_cached,Point.Empty);
}

//如果_zoom或ClientSize改变
无效ResetCache()$称之为b $ b {
_cache = NULL;
this.Invalidate(); //强制_zoom变化
}

另外,我不知道该怎么做你出示放大的图片,但通常有一个的偏移的,这样你可以移动(平移)图像。


I have a large tiff picture (5.9 Mb , 13k X 16k reolution) that the user loads into a scrollable panel that he then can zoom in/out of, scroll and mark points, regions etc on.

for the scrollable double buffered panel I am using a modification of Bob Powell's awesome ZoomPicBox The panel displays only the part of the picture currently in view.

The stutter occurs when scrolling the image when zoomed out (even if the interpolationMode is set to low)

Is there anything that can be done about it (preferably without hardware acceleration)?

The paint event of the panel :

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        if (_image == null)
        {
            base.OnPaintBackground(e);
            return;
        }

        //scale
        System.Drawing.Drawing2D.Matrix ScaleMat = new System.Drawing.Drawing2D.Matrix(_zoom, 0, 0, _zoom, 0, 0);
        //move to position of scrollbas
        ScaleMat.Translate(this.AutoScrollPosition.X / (_zoom), this.AutoScrollPosition.Y / (_zoom));


        e.Graphics.Transform = ScaleMat;
        e.Graphics.InterpolationMode = _interpolationMode;

        e.Graphics.DrawImage(_image, new Rectangle(0, 0, _image.Width, _image.Height), 0, 0, _image.Width, _image.Height, GraphicsUnit.Pixel);


        base.OnPaint(e);
    }

  • _zoom ,_image and _interpolationMode are private fields of the control

The constructor:

 public PicBoxPlus()
        {
            MouseMove += PicBoxPlus_MouseMove;
            KeyDown += PicBoxPlus_KeyDown;
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);

            this.AutoScroll = true;
        }

EDIT : Attempting Caching

I tried implementing Sinatr's code but something is wrong, because all I get is a black image (of the right size). Anyone has an idea what could be wrong?

The new paint event:

 protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            if (mCachedImage == null)
            {
                base.OnPaintBackground(e);
                return;
            }

            //scale
            System.Drawing.Drawing2D.Matrix ScaleMat = new System.Drawing.Drawing2D.Matrix(mZoom, 0, 0, mZoom, 0, 0);
            //move to position of scrollbas
            ScaleMat.Translate(this.AutoScrollPosition.X / (mZoom), this.AutoScrollPosition.Y / (mZoom));

            try
            {
                if (mCachedImage == null)
                {
                    mCachedImage = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
                    using (var cacheGraphics = Graphics.FromImage(mCachedImage))
                    {
                        cacheGraphics.Transform = ScaleMat;
                        cacheGraphics.InterpolationMode = _interpolationMode;
                        cacheGraphics.DrawImage(mCachedImage, new Rectangle(0, 0, mCachedImage.Width, mCachedImage.Height), 0, 0, mCachedImage.Width, mCachedImage.Height, GraphicsUnit.Pixel);

                    }

                    e.Graphics.DrawImage(mCachedImage, Point.Empty);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            base.OnPaint(e);
        }

The Image and zoom properties:

public Bitmap Image
    {
        get { return mCachedImage; }
        set
        {
            mCachedImage = value;
            UpdateScaleFactor();
            this.Invalidate();
        }
    }

public Single Zoom
{
    get { return mZoom; }
    set
    {
        if (value <= 0||value < 0.001)
        {
            value = 0.001f;
        }

        mZoom = value;
        UpdateScaleFactor();
        ResetCache(); // Sinatr's function
        this.Invalidate();
    }
}

Loading the image from the main form:

panelMap.Image = (Bitmap)Image.FromFile("pic.tiff");

解决方案

Is not tested, but should give an idea.

Bitmap _cached = null;

override void OnPaint(PaintEventArgs e)
{
    if(_cached == null)
    {
        _cached = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
        using(var graphics = Graphics.FromImage(_cached)
        {
             // draw into this graphics once -> it will be cached in _cached bitmap
        }
    }
    e.Graphics.DrawImage(_cached, Point.Empty);
}

// call this if _zoom or ClientSize is changed
void ResetCache()
{
    _cache = null;
    this.Invalidate(); // mandatory for _zoom change
}

Also, I don't know how to do you present your zoomed-in picture, but usually there is an offset so that you can move (pan) image.

这篇关于如何防止图形口吃滚动大缩小图像时,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆