Язык программирования:
C#
Среда программирования:
Microsoft Visual Studio 2013
using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; namespace Lights { public partial class Form1 : Form { private Bitmap btmp1, btmp2, btmp3;// создаём три карты (буферы) private Graphics graph;//поверхность для рисования public SolidBrush g_brush, r_brush, b_brush, back_brush;// цветные кисти и кисть фона public int r_count, g_count, b_count, r = 2, g = 2, b = -2;// счётчики и величина смещения public int diametr, width, height;// размеры окна и диаметр окружности public Form1() { InitializeComponent(); } private void Loading(object sender, EventArgs e)// функция инициализации { //размеры picture box width = pictureBox1.Width; height = pictureBox1.Height; diametr = 200; //изначальный сдвиг окружностей r_count = 0; g_count = 100; b_count = 100; //инициализируем битовые карты btmp1 = new Bitmap(width, height, PixelFormat.Format24bppRgb); btmp2 = new Bitmap(width, height, PixelFormat.Format24bppRgb); btmp3 = new Bitmap(width, height, PixelFormat.Format24bppRgb); // цвета кистей подобраны, чтобы в сумме давать белый g_brush = new SolidBrush(Color.FromArgb(240, 30, 205,25)); r_brush = new SolidBrush(Color.FromArgb(240, 200,25,50)); b_brush = new SolidBrush(Color.FromArgb(240, 25,25, 180)); back_brush = new SolidBrush(Color.Black); timer1.Start();//включаем таймер, по его тикам происходит движение кругов } public void timer1_Tick(object sender, EventArgs e) { // включаем сглаживание,очищаем фон и каждую окружность рисуем на отдельной карте graph = Graphics.FromImage(btmp1); graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.FillRectangle(back_brush, 0, 0, width, height); graph.FillEllipse(r_brush, r_count+2, 0, diametr, diametr); graph = Graphics.FromImage(btmp2); graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.FillRectangle(back_brush, 0, 0, width, height); graph.FillEllipse(g_brush, g_count+2, 0, diametr, diametr); graph = Graphics.FromImage(btmp3); graph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graph.FillRectangle(back_brush, 0, 0, width, height); graph.FillEllipse(b_brush, b_count+2, 0, diametr, diametr); //для вывода на экран создаём ещё одну карту (перестраховка от артефактов) Bitmap bmpdone = new Bitmap (AlphaBlendingUnsafe(btmp2, btmp1, btmp3));// вызываем функцию наложения pictureBox1.BackgroundImage = bmpdone;//отрисовываем на экран //считаем сдвиг кругов по оси x if (r_count >150 || r_count <0) r = -r; else if (g_count > 150 || g_count < 0) g = -g; else if (b_count > 150 || b_count < 0) b = -b; // текущий сдвиг r_count += r; g_count += g; b_count += b; } unsafe Bitmap AlphaBlendingUnsafe(Bitmap x, Bitmap y,Bitmap z)//функция наложения карт { Rectangle rect = new Rectangle(0, 0, width,height);//прямоугольная область размером с picture Box Bitmap result = new Bitmap(width,height,PixelFormat.Format24bppRgb);// результирующая карта (без альфа-составляющей) //BitmapData - это массив пикселей, отображаемых с помощью Bitmap // получаем доступ к элементам массива (одномерного) // LockBits - блокировка рисунка в памяти, чтобы можно было менять значения "вручную", то есть для каждого цвета отдельно // если использовать метод Bitmap.GetPixel, то вычисления займут очень много времени BitmapData res_data = result.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); // для входных параметров - только чтение(ReadOnly) BitmapData x_data = x.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); BitmapData y_data = y.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); BitmapData z_data = z.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); //создаём указатели на первый байт (Scan0) для каждой BitmapData byte* x_pos = (byte*)x_data.Scan0; byte* y_pos = (byte*)y_data.Scan0; byte* z_pos = (byte*)z_data.Scan0; byte* res_pos = (byte*)res_data.Scan0; //проходим двойным циклом по всей результирующей карте for (int h = 0; h < height; h++)//по строкам { res_pos = ((byte*)res_data.Scan0) + h * res_data.Stride;// прибавляем строку for (int w = 0; w < width; w++)//по столбцам { //для каждого байта (R,G,B) считываем сумму из трех входных битмап-дата и помещаем в результирующую *(res_pos++) = (byte)(*(x_pos++) + *(y_pos++)+*(z_pos++)); *(res_pos++) = (byte)(*(x_pos++) + *(y_pos++) + *(z_pos++)); *(res_pos++) = (byte)(*(x_pos++) + *(y_pos++) + *(z_pos++)); } } //разблокируем элементы массива BitmapData для дальнейшего использования result.UnlockBits(res_data); x.UnlockBits(x_data); y.UnlockBits(y_data); z.UnlockBits(z_data); return result;// возвращаем полученный результат } } }
Прикрепленный файл | Размер |
---|---|
Lights.rar | 49.44 кб |