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.
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.
Labels:
GDI+,
Imaging,
Special Effect,
Water Effect,
Water Over
LINQ
LINQ
Language Integrated Query (LINQ, pronounced "link") is a Microsoft .NET Framework component that adds native data querying capabilities to .NET languages.
An efficient way to experiment with LINQ is to download LINQPad, at www.linqpad.net.
Language Integrated Query (LINQ, pronounced "link") is a Microsoft .NET Framework component that adds native data querying capabilities to .NET languages.
An efficient way to experiment with LINQ is to download LINQPad, at www.linqpad.net.
Water Effect:: Water Over Using GDI+
Water Effect:: Water Over Using GDI+
The code in this post is to create a water effect sample, water over, on images using .NET's GDI+.
See the following example!
This image:
The code in this post is to create a water effect sample, water over, on images using .NET's GDI+.
See the following example!
This image:
Will be converted to the following animated GIF:
The following code shows how to add water waves over frames; where each frame is initiated by the original image.
~ continued (see the next post).
Labels:
GDI+,
Imaging,
Special Effect,
Water Effect,
Water Over
Subscribe to:
Posts (Atom)