Объединить два изображения для перехода "исчезать" с изменением непрозрачности?(C # / PNG) - PullRequest
2 голосов
/ 02 сентября 2011

Прежде всего, я хотел бы предположить, что это не дубликат ЭТОГО вопроса. По крайней мере, это мое мнение :)

То, чего я хочу добиться, - это серия кадров для «исчезающей» анимации.

Я выбираю два файла PNG (скажем, они имеют одинаковый размер), например:

Я хочу "смоделировать" объединение их как слоев в графическом редакторе. Я поместил Pic1 сверху с непрозрачностью 255, Pic2 снизу с непрозрачностью 0, поэтому сначала я вижу только Pic1. Затем я изменяю их непрозрачность, вот так:

Есть ли простой способ для этого?

Ответы [ 2 ]

4 голосов
/ 02 сентября 2011

В приложении 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 мс,Обработайте событие тика:

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

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

и вуаля.Тем не менее, есть одна вещь, о которой нужно знать.Это делает довольно плавный переход, который можно несколько изменить с помощью этой строки в конструкторе элемента управления:

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 
1 голос
/ 02 сентября 2011

Используя , вы можете использовать Graphics.DrawImage, используя перегрузку, которая принимает параметр ImageAttributes.Этот класс может определять манипуляции со значениями цвета ( и alpha ).

Пример на странице ImageAttributes - это почти то, что вам нужно.Просто нарисуйте оригинал и преобразованный в том же месте, и измените цветовую матрицу, чтобы изменить только альфа-уровень.

...