Tuesday, June 30, 2009

Water Effect:: Water Over Using GDI+ (source code)

The code for the previous post (Water Effect:: Water Over Using GDI+):


using
System.Collections.Generic;
using System.Drawing.Imaging;
using System.Drawing;
using System.Runtime.InteropServices;
using System;


namespace
WaterOver.GR
{

public class WaterOver
{

///
/// Create Water Over an Animated GIF Frames.
///
/// Returns full file name of frames.

public static string[] CreateWaterOverFrames(Bitmap bmp, int frameCount, string outputPath, string fileName)
{

string[] rtn = new string[frameCount];
int width = bmp.Width;
int height = bmp.Height;
int _waveWidth = width;
int _waveHeight = height;
int[, ,] __wave = new int[_waveWidth,_waveHeight, 2];
int __buffer = 0;

int radius = (int)(0.6 * Math.Min(width, height));

int fromX = (int)(4.0 * width / 10.0);
int toX = 1 + (int)(6.0 * width / 10.0);
int fromY = height - (1 + (int)(height / 10.0));
int toY = height;
Random r = new Random();
int x, y;
string gnlFfn; // general full file name (to save frame files)

// Set gnlFfn.
outputPath = outputPath.Trim();

if(!outputPath.EndsWith(@"\"))
outputPath +=
@"\";
gnlFfn = outputPath + fileName.Trim() +
"_";

byte[] _bmpBytes = new Byte[width * height * 4];

// Set _bmpBytes.
BitmapData _bmpBitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

Marshal.Copy(_bmpBitmapData.Scan0, _bmpBytes, 0, width * height * 4);

////////////////////////////////
// Generate frames one by one //
////////////////////////////////

for (int h = 0; h < frameCount;h++)
{

///////////////////
// Refine waves. //
///////////////////

int __newBuffer = (__buffer == 0) ? 1 : 0;

bool wavesFound = false;

for (x = 1; x <>for (y = 1; y <>> 2) - __wave[x, y, __newBuffer];

if (__wave[x, y, __newBuffer] != 0)
{
__wave[x, y, __newBuffer] -= __wave[x, y, __newBuffer] >> 4;
wavesFound =
true;
}

}
// next y
} // next x

__buffer = __newBuffer;


///////////////////////////////
// Put a wave center (drop). //
///////////////////////////////

x = r.Next(fromX , toX);
y = r.Next(fromY, toY);
double dist;

for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { if (((x + i <= 0) && (x + i < dist =Math.Sqrt(i * i + j * j);

if (dist <>int)(Math.Cos(dist * Math.PI / radius) * height);

}
}
}

/////////////////////
// Paint the frame //
/////////////////////


using (Bitmap tmpBmp = (Bitmap)bmp.Clone())
{

int xOffset, yOffset;

byte alpha;

if (wavesFound)
{

BitmapData tmpData = tmpBmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);

byte[] tmpBytes = new Byte[width * height * 4];
Marshal.Copy(tmpData.Scan0, tmpBytes, 0, width * height * 4);
for (x = 1; x <>for (y = 1; y <>int waveX = x;
int waveY = y;
// Check bounds.
if (waveX <= 0) waveX = 1; if (waveY <= 0) waveY = 1; if (waveX <= _waveWidth - 1) waveX = _waveWidth - 2; if (waveY <= _waveHeight - 1) waveY = _waveHeight - 2; // Make the effect of water breaking the light.
xOffset = (__wave[waveX - 1, waveY, __buffer] - __wave[waveX + 1, waveY, __buffer]) >> 3;

yOffset = (__wave[waveX, waveY - 1, __buffer] - __wave[waveX, waveY + 1, __buffer]) >> 3;

if ((xOffset != 0) (yOffset != 0))
{
// Check bounds.
if (x + xOffset >= width - 1) xOffset = width - x - 1;
if (y + yOffset >= height - 1) yOffset = height - y - 1;
if (x + xOffset < 0) xOffset = -x;

if (y + yOffset < 0) yOffset = -y;

// Generate alpha.
alpha = (byte)(200 - xOffset);
if (alpha <>
alpha = 0;
if (alpha < alpha =" 254;">// Set colors.
tmpBytes[4 * (x + y * width)] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * width)];
tmpBytes[4 * (x + y * width) + 1] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * width) + 1];
tmpBytes[4 * (x + y * width) + 2] = _bmpBytes[4 * (x + xOffset + (y + yOffset) * width) + 2];
tmpBytes[4 * (x + y * width) + 3] = alpha;
}
}
// next y
} // next x


// Copy data back.
Marshal.Copy(tmpBytes, 0, tmpData.Scan0, width * height * 4);
tmpBmp.UnlockBits(tmpData);
}

// Save tmpBmp, the new frame generated.
rtn[h] = gnlFfn + h.ToString() + ".gif";
tmpBmp.Save(rtn[h],
ImageFormat.Gif);

}
}
// next h

return rtn;
}

}
}


The method CreateWaterOverFrames returns an array of file names (frames) that can be used in a function to create a single animated gif file; there are a few of them; one that is fairly a good one and simple to use can be found here.


No comments:

Post a Comment