Merge two images for “fade” transition with changing opacity? (C#/PNG)?

In a winforms app this can be done pretty easily. Create a user control with a few properties: public Image FromImage { get; set; } public Image ToImage { get; set; } private float opacity = 1 Now override 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); } Now drop a timer onto the control, set its to enabled with an elapsed time of something like 100ms. Handle the tick event: private void timer_Tick(object sender, EventArgs e) { if(opacity == 0) { this.timer.Stop(); return; } this.

Opacity -= 0.01f; this.Invalidate(); } et voila. However, there's one thing to be aware of. This makes quite a flickery transition, which can be alieviated somewhat with this line in the control's constructor: this.

SetStyle(ControlStyles. OptimizedDoubleBuffer | ControlStyles. AllPaintingInWmPaint,true) Update based on Edit: You could turn this into a utility that takes 2 images and, using much the same code, outputs each step to a new image.

Somthing like: 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); } } } Usage: 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.

In a winforms app this can be done pretty easily. Create a user control with a few properties: public Image FromImage { get; set; } public Image ToImage { get; set; } private float opacity = 1; Now override 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); } Now drop a timer onto the control, set its to enabled with an elapsed time of something like 100ms. Handle the tick event: private void timer_Tick(object sender, EventArgs e) { if(opacity == 0) { this.timer.Stop(); return; } this.

Opacity -= 0.01f; this.Invalidate(); } et voila. However, there's one thing to be aware of. This makes quite a flickery transition, which can be alieviated somewhat with this line in the control's constructor: this.

SetStyle(ControlStyles. OptimizedDoubleBuffer | ControlStyles. AllPaintingInWmPaint,true); Update based on Edit: You could turn this into a utility that takes 2 images and, using much the same code, outputs each step to a new image.

Somthing like: 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); } } } Usage: 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.

I want to fade one image to another and save every "frame" of the animation. – WRonX Sep 2 at 12:38 @WRonX - see update. Pretty easy to turn the same code to a util that saves each transition out to disk.

– Jamiec Sep 2 at 13:08 I'll check it, but I suppose it can be the answer. Thank you! My solution (in comments to question) fails at transparent PNGs, so I'll check yours.

I assume if I need a preview, I can just cast and assign, I mean pictureBox1. Image=(Image)image;? – WRonX Sep 2 at 13:43 You suppose it can be the answer?

Don't sound too enthusiastic or anything. – Jamiec Sep 2 at 13:47 Maybe it sounded that way, because: 1.My English isn't good. 2.

I'm usually not that good at C# to know if it is what I meant only by reading the code and I can't check it now (different place, different machine). Sorry, if it offended you, I didn't mean that way. I AM enthusiastic about ending what I started, so once again: thank you very much!

– WRonX Sep 2 at 14:36.

Using winforms you can use Graphics. DrawImage, using the overload that takes an ImageAttributes parameter. That class can specify manipulation to the colour (and alpha) values.

The example on the ImageAttributes page is nearly what you want. Just draw the original and transformed one in the same place, and change the colour matrix to only change the alpha level.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions