2011-09-02 74 views
2

首先,我想建议它不是THIS问题的重复。至少这是我的意见:)合并两张图像进行“淡入淡出”转换并改变不透明度? (C#/ PNG)

我想实现的是一系列帧“淡入淡出”的动画。

我选择两种PNG文件(让我们说,他们是相同的大小),例如:

我想 “模拟” 合并他们像层在图形编辑器中。我把Pic1放在不透明度为255的顶部,下面的图片为2,不透明度为0,所以起初我只看到Pic1。然后,我改变自己的不透明度,就像这样:

是否有任何简单的方法?

+0

无代码,没有饼干!你试过什么了? – leppie

+0

我们在说WPF吗?赢取表格? Silverlight的? – ForbesLindesay

+0

对不起,WinForms。这里是cookie:http://wronx.net/misc/so/fade。txt - 我找到了一个不同的例子,并设法自己改变它。不确定,如果它在数学上是正确的,但它有效。 – WRonX

回答

4

在一个winforms应用程序中,这可以很容易地完成。有几个属性创建一个用户控件:

public Image FromImage { get; set; } 
public Image ToImage { get; set; } 

private float opacity = 1; 

现在重写的OnPaint

protected override void OnPaint(PaintEventArgs e) 
    { 
     if (FromImage != null && ToImage != null) 
     { 
      ColorMatrix matrix1 = new ColorMatrix(); 
      matrix1.Matrix33 = opacity; 
      ImageAttributes attributes1 = new ImageAttributes(); 
      attributes1.SetColorMatrix(matrix1, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 


      ColorMatrix matrix2 = new ColorMatrix(); 
      matrix2.Matrix33 = 1 - opacity; 
      ImageAttributes attributes2 = new ImageAttributes(); 
      attributes2.SetColorMatrix(matrix2, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 

      e.Graphics.DrawImage(FromImage, new Rectangle(0, 0, this.Width, this.Height), 0, 0, this.Width, 
           this.Height, GraphicsUnit.Pixel, attributes1); 
      e.Graphics.DrawImage(ToImage, new Rectangle(0, 0, this.Width, this.Height), 0, 0, this.Width, 
           this.Height, GraphicsUnit.Pixel, attributes2); 
     } 
     base.OnPaint(e); 
    } 

现在拖放一个计时器上的控制,设置它能够与像100毫秒经过时间启用。处理tick事件:

private void timer_Tick(object sender, EventArgs e) 
    { 
     if(opacity == 0) 
     { 
      this.timer.Stop(); 
      return; 
     } 

     this.opacity -= 0.01f; 
     this.Invalidate(); 
    } 

et瞧。但是,有一件事要注意。这使得相当flickery过渡,这可以在一定程度与这条线在控件的构造函数中alieviated:

this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint,true); 

更新基于编辑:你可以把它变成一个工具,需要2个图像,并使用多相同的代码,输出每一步到一个新的形象。财产以后这样的:

public class ImageUtility 
{ 
    private Image image1; 
    private Image image2; 

    public ImageUtility(Image image1, Image image2) 
    { 
     this.image1 = image1; 
     this.image2 = image2; 
    } 

    public void SaveTransitions(int numSteps, string outDir) 
    { 
     var opacityChange = 1.0f/(float) numSteps; 

     for(float opacity = 1,i=0;opacity>0;opacity-=opacityChange,i++) 
     { 
      using(var image = new Bitmap(image1.Width,image2.Width)) 
      { 
       Graphics g = Graphics.FromImage(image); 
       ColorMatrix matrix1 = new ColorMatrix(); 
       matrix1.Matrix33 = opacity; 
       ImageAttributes attributes1 = new ImageAttributes(); 
       attributes1.SetColorMatrix(matrix1, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 


       ColorMatrix matrix2 = new ColorMatrix(); 
       matrix2.Matrix33 = 1 - opacity; 
       ImageAttributes attributes2 = new ImageAttributes(); 
       attributes2.SetColorMatrix(matrix2, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); 

       g.DrawImage(image1, new Rectangle(0, 0, image1.Width, image1.Height), 0, 0, image1.Width, 
            image1.Height, GraphicsUnit.Pixel, attributes1); 
       g.DrawImage(image2, new Rectangle(0, 0, image2.Width, image2.Height), 0, 0, image2.Width, 
            image2.Height, GraphicsUnit.Pixel, attributes2); 

       image.Save(Path.Combine(outDir,"Image" + i + ".png"),ImageFormat.Png); 
      } 
     } 
    } 

用法:

ImageUtility util = new ImageUtility(Image.FromFile(@"C:\path\pic1.png"), Image.FromFile(@"C:\path\pic2.png")); 
util.SaveTransitions(100, @"C:\path\output"); // saves 100 images 
+0

不知道我是否理解 - “第二”图像在哪里?我想将一个图像淡入另一个图像并保存动画的每个“帧”。 – WRonX

+0

@WRonX - 查看更新。很容易将相同的代码转换为一个将每个转换保存到磁盘的util。 – Jamiec

+0

我会检查它,但我想这可能是答案。谢谢!我的解决方案(针对问题的评论)在透明的PNG上失败,所以我会检查你的。我假设如果我需要一个预览,我可以施放和分配,我的意思是pictureBox1.Image =(Image)image; ?? – WRonX

1

使用可以使用Graphics.DrawImage,使用带ImageAttributes参数的过载。该类可以指定对颜色的操作(和alpha)值。

ImageAttributes页面上的示例几乎就是您想要的。只需在同一个地方绘制原始图像并将其转换,然后更改颜色矩阵以仅更改alpha级别。