2011-03-10 81 views
0

我需要創建具有透明圓角的縮略圖圖像。這個要求之前,我使用的簡單:創建帶圓角的圖像縮略圖

using (var b = new Bitmap(dataSize.Width, dataSize.Height, PixelFormat.Format32bppArgb)) 
using (var g = Graphics.FromImage(b)) 
{ 
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default; 
    g.DrawImage(original, 0, 0, b.Width, b.Height); 
} 

這產生了很大的結果(減少至約50x50px),即使沒有任何插值。現在用圓角我用下面的算法(4「,如果公司有那麼我可以在每個4角變圓度):

using (var b = new Bitmap(dataSize.Width, dataSize.Height, PixelFormat.Format32bppArgb)) 
using (var g = Graphics.FromImage(b)) 
{ 
    // set interpolation 
    g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
    g.SmoothingMode = SmoothingMode.HighQuality; 

    // transformation to scale and shift the brush 
    var transform = new Matrix(); 
    transform.Scale(ratio, ratio); 
    transform.Translate(start.X/ratio, start.Y/ratio); 
    var brush = new TextureBrush(original) { Transform = transform }; 

    // create path for stamping the iamge 
    var gp = new GraphicsPath(FillMode.Winding); 
    if (descriptor.CornerRadiusLeftTop > 0) 
     gp.AddArc(descriptor.GetLeftTopCorner(b.Size), 180, 90); 
    else 
     gp.AddLine(-1, -1, -1, -1); 

    if (descriptor.CornerRadiusRightTop > 0) 
     gp.AddArc(descriptor.GetRightTopCorner(b.Size), 270, 90); 
    else 
     gp.AddLine(b.Width + 1, -1, b.Width + 1, -1); 

    if (descriptor.CornerRadiusRightBottom > 0) 
     gp.AddArc(descriptor.GetRightBottomCorner(b.Size), 0, 90); 
    else 
     gp.AddLine(b.Width + 1, b.Height + 1, b.Width + 1, b.Height + 1); 

    if (descriptor.CornerRadiusLeftBottom > 0) 
     gp.AddArc(descriptor.GetLeftBottomCorner(b.Size), 90, 90); 
    else 
     gp.AddLine(-1, b.Height + 1, -1, b.Height + 1); 
    // stamp the image with original 
    g.FillPath(brush, gp); 
} 

但這種方法生產的醜未插值成像與真正鋸齒狀梯度。有沒有更好的方法來創建透明的縮略圖,還是有一些設置可以用來改善輸出?

回答

2

我寫了一篇博客文章,解釋瞭如何做到這一點。

http://danbystrom.se/2008/08/24/soft-edged-images-in-gdi/

如果你看一下第一個樣本圖像,你看到的5),我展示瞭如何在6到達)。祝你好運。

+0

我用你的傳送通道的方法,但用我自己的函數來創建掩碼位圖。還有插值問題,第一行圖像是半透明的,所以我不得不在整個圖像周圍畫出一條GraphicPath,而只是剪掉角落中的小圓弧。 – puco 2011-03-18 14:56:49

0

我會先將圖像複製到第二個帶有圓角的圖像,然後使用GetThumbnailImage將其縮小。

0

我已經使用了修改的TransferChannel方法來添加掩碼,這在danbystrom的博客文章中並不是不安全的。

public static void TransferChannel(Bitmap src, Bitmap dst, ChannelARGB sourceChannel, ChannelARGB destChannel) 
    { 
     if (src.Size != dst.Size) 
      throw new ArgumentException(); 

     var r = new Rectangle(Point.Empty, src.Size); 
     var bdSrc = src.LockBits(r, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 
     var bdDst = dst.LockBits(r, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 

     var s = bdSrc.Stride * src.Height; 
     var baSrc = new byte[s]; 
     var baDst = new byte[s]; 

     Marshal.Copy(bdSrc.Scan0, baSrc, 0, s); 
     Marshal.Copy(bdDst.Scan0, baDst, 0, s); 

     for (var counter = 0; counter < baSrc.Length; counter += 4) 
      baDst[counter + (int)destChannel] = baSrc[counter + (int)sourceChannel]; 

     Marshal.Copy(baDst, 0, bdDst.Scan0, s); 

     src.UnlockBits(bdSrc); 
     dst.UnlockBits(bdDst); 
    } 

而且我的方法來調整,使圓角是:

 var b = new Bitmap(dataSize.Width, dataSize.Height, PixelFormat.Format32bppArgb); 

     using (var g = Graphics.FromImage(b)) 
     { 
      g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      g.DrawImage(original, start.X, start.Y, original.Width * ratio, original.Height * ratio); 

      if (hasRoundedCorners) 
       using (var mask = CreateMask(dataSize, radius)) 
        TransferChannel(mask, b, ChannelARGB.Blue, ChannelARGB.Alpha); 
     } 
     return b;