2011-08-01 24 views
2

我有一個軌跡欄可以放大或縮小圖像,但它不會平滑放大,對於200%或更多的縮放而言,分割第二滯後。如何讓這個圖像縮放得更快?

private void trackBar1_ValueChanged(object sender, EventArgs e) 
{ 
    zoom = trackBar1.Value; 
    zoomValue = (float)(zoom/10.0f); 
    newBitmap = new Bitmap((int)(currWidth * zoomValue), (int)(currHeight * zoomValue)); 

    g = Graphics.FromImage(newBitmap); 
    Matrix mx = new Matrix(); 
    mx.Scale(zoomValue, zoomValue); 

    g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
    g.Transform = mx; 
    g.DrawImage(currImage, new Rectangle(0, 0, currWidth, currHeight)); 
    g.Dispose(); 
    mx.Dispose(); 
    panel1.BackgroundImage = newBitmap; 
} 

我發現一個用戶控件有人制作了http://www.codeproject.com/KB/graphics/YLScsImagePanel.aspx,這個用戶控件非常流暢地放大。根本沒有滯後。

private void trackBar1_Scroll(object sender, EventArgs e) 
{ 
    imagePanel1.Zoom = trackBar1.Value * 0.02f; 
} 

這是從自定義控制ImagePanel.cs

public float Zoom 
{ 
    get { return zoom; } 
    set 
    { 
     if (value < 0.001f) value = 0.001f; 
     zoom = value; 

     displayScrollbar(); 
     setScrollbarValues(); 
     Invalidate(); 
    } 
} 

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    //draw image 
    if(image!=null) 
    { 
     Rectangle srcRect,distRect; 
     Point pt=new Point((int)(hScrollBar1.Value/zoom),(int)(vScrollBar1.Value/zoom)); 
     if (canvasSize.Width * zoom < viewRectWidth && canvasSize.Height * zoom < viewRectHeight) 
      srcRect = new Rectangle(0, 0, canvasSize.Width, canvasSize.Height); // view all image 
     else srcRect = new Rectangle(pt, new Size((int)(viewRectWidth/zoom), (int)(viewRectHeight/zoom))); // view a portion of image 

     distRect=new Rectangle((int)(-srcRect.Width/2),-srcRect.Height/2,srcRect.Width,srcRect.Height); // the center of apparent image is on origin 

     Matrix mx=new Matrix(); // create an identity matrix 
     mx.Scale(zoom,zoom); // zoom image 
     mx.Translate(viewRectWidth/2.0f,viewRectHeight/2.0f, MatrixOrder.Append); // move image to view window center 

     Graphics g=e.Graphics; 
     g.InterpolationMode=interMode; 
     g.Transform=mx; 
     g.DrawImage(image,distRect,srcRect, GraphicsUnit.Pixel); 
    } 

} 

是不是因爲我每次創建,它滯後時間一個新的位圖?我怎樣才能讓它像這樣平滑地變焦?

+0

爲什麼不使用codeproject中的一個? – Yahia

+2

當我嘗試水平居中時,圖像的隱藏部分會垂直混亂。滾動條看起來太小了。我現在的工作方式只是我想要的,它不會變得非常快。 – Jonas

+0

拆分繪畫代碼和trackBar1_ValueChanged代碼,以便沿着軌跡條滾動。 – CodingBarfield

回答

1

as @CodingBarfield提到,在trackBar1_ValueChanged()方法中計算縮放圖像並不是一個好主意。原因是,如果你縮小得太快,你仍然可以在每個中間步驟計算重新縮放的圖像(即使那些步驟永遠不會顯示)。因此,改變的方法是這樣的:

private void trackBar1_ValueChanged(object sender, EventArgs e) 
{ 
    panel1.Invalidate(); 
} 

並把縮放本身的OnPaint()方法看起來是這樣的:

protected override void OnPaint(PaintEventArgs e) 
{ 
    base.OnPaint(e); 

    zoom = trackBar1.Value; 
    if (lastZoom != zoom) 
    { 
     // the zoom has changed, clear the cache 
     lastZoom = zoom; 
     imageCache = null; 
    } 

    if (imageCache == null && image != null) 
    { 
     // compute scaled image 
     imageCache = scaleImage(image, zoom); 
    } 

    //draw image 
    if(image!=null) 
    { 
     ... 
    } 
} 

OnPaint()方法中的比例不是100%乾淨的解決方案,因爲它仍然可以讓你的GUI線程恢復。更好的選擇是使用後臺線程,但我認爲這應該足夠了,它可以爲您節省一些編碼時間。

您還可以通過縮放所需圖像的一部分來獲得額外的性能增益。這項技術將爲您節省變焦的平方,因此變焦越大,保存的計算量就越多。

另一種選擇是選擇一些計算量較小的插值模式。或者你甚至可以計算一些低質量的近似值,顯示它,然後使用後臺線程計算一些質量更好的圖像。

或者,也許你可以扔掉所有的代碼,只是修改CodePlex example以適應你的需求:)。

希望這會有所幫助。