円錐形のグラデーションの描画方法が分からなかったので、
書いてみた。
本当はもっと簡単な方法があるのかもしれない。
- //
- // ConicalGradient 円錐形グラデーションの描画クラス
- //
- using System;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Runtime.InteropServices;
- using System.Threading.Tasks;
- namespace DrawTest
- {
- class ConicalGradient
- {
- public static Bitmap GetBitmap(Color[] colorList, int width, int height)
- {
- return GetBitmap(colorList, 0, width, height, width / 2, height / 2);
- }
- public static Bitmap GetBitmap(Color[] colorList, double d, int width, int height)
- {
- return GetBitmap(colorList, d, width, height, width / 2, height / 2);
- }
- public static Bitmap GetBitmap(Color[] colorList, double d, int width, int height, int centerX, int centerY)
- {
- try
- {
- //Color配列が空の時はHueの値でも入れとく
- if (colorList == null || colorList.Length == 0)
- {
- colorList = new Color[6];
- colorList[0] = Color.FromArgb(255, 0, 0);
- colorList[1] = Color.FromArgb(255, 255, 0);
- colorList[2] = Color.FromArgb(0, 255, 0);
- colorList[3] = Color.FromArgb(0, 255, 255);
- colorList[4] = Color.FromArgb(0, 0, 255);
- colorList[5] = Color.FromArgb(255, 0, 255);
- }
- Color[] colArry;
- int colLength;
- //色と色の間隔は最大でも256色なので×配列の要素数分の色を作っとく
- colArry = new Color[colorList.Length * 256];
- colLength = colArry.Length;
- Parallel.For(0, colLength, delegate(int i)
- {
- //for (int i = 0; i < colLength; i++)
- //{
- colArry[i] = GetColor(colorList, ((double)i / colLength) * 360.0);
- //}
- });
- Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
- BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
- int stride = bmpData.Stride;
- byte[] bmpByte = new byte[height * stride];
- const double rad = 180 / Math.PI;
- Parallel.For(0, width, delegate(int i)
- {
- //for (int i = 0; i < width; i++)
- //{
- for (int j = 0; j < height; j++)
- {
- double angle = (Math.Atan2(centerY - j, centerX - i) * rad) + 180 + d;
- angle = (angle + 360) % 360;//0~359.99…の中に収める
- Color col = colArry[(int)(angle * (colLength / 360.0))];
- bmpByte[(i * 4) + (j * stride) + 3] = col.A;
- bmpByte[(i * 4) + (j * stride) + 2] = col.R;
- bmpByte[(i * 4) + (j * stride) + 1] = col.G;
- bmpByte[(i * 4) + (j * stride) + 0] = col.B;
- }
- //}
- });
- Marshal.Copy(bmpByte, 0, bmpData.Scan0, bmpByte.Length);
- bmp.UnlockBits(bmpData);
- return bmp;
- }
- catch
- {
- return null;
- }
- }
- /// <summary>
- /// 色の取得
- /// </summary>
- /// <param name="colors">/// <param name="angle">0.0~259.99... /// <returns></returns> private static Color GetColor(Color[] colors, double angle) { //色の初期化 int a, r, g, b, //色の数 length = colors.Length, num = 0; int d = (int)(angle / (360.0 / length)); double rest = (angle % (360.0 / length)) / (360.0 / length); if (d + 1 < length) num = d + 1; int startA = colors[d].A, endA = colors[num].A, startR = colors[d].R, endR = colors[num].R, startG = colors[d].G, endG = colors[num].G, startB = colors[d].B, endB = colors[num].B; if (startA < endA) { a = startA + (int)((endA - startA) * rest); } else { a = startA - (int)((startA - endA) * rest); } if (startR < endR) { r = startR + (int)((endR - startR) * rest); } else { r = startR - (int)((startR - endR) * rest); } if (startG < endG) { g = startG + (int)((endG - startG) * rest); } else { g = startG - (int)((startG - endG) * rest); } if (startB < endB) { b = startB + (int)((endB - startB) * rest); } else { b = startB - (int)((startB - endB) * rest); } return Color.FromArgb(a, r, g, b); } } }
- using System.Drawing;
- using System.Windows.Forms;
- using System;
- using System.Drawing.Drawing2D;
- using System.Diagnostics;
- namespace DrawTest
- {
- class ConicalGradientView : Control
- {
- private Bitmap bmp;
- private double angle = 0;
- private Point center;
- public Point Center
- {
- get { return center; }
- set
- {
- center = value;
- Refresh();
- }
- }
- private Color[] colors = null;
- public Color[] Colors
- {
- get { return colors; }
- set
- {
- colors = value;
- Refresh();
- }
- }
- public ConicalGradientView()
- {
- SetStyle(ControlStyles.UserPaint, true);
- SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
- SetStyle(ControlStyles.SupportsTransparentBackColor, true);
- SetStyle(ControlStyles.ResizeRedraw, true);
- }
- protected override void OnPaint(PaintEventArgs pe)
- {
- base.OnPaint(pe);
- Stopwatch sw = new Stopwatch();
- sw.Start();
- bmp = ConicalGradient.GetBitmap(colors, angle, this.ClientSize.Width, this.ClientSize.Height, Center.X, Center.Y);
- Console.WriteLine(sw.Elapsed);
- if (bmp != null)
- {
- pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
- pe.Graphics.FillEllipse(new TextureBrush(bmp), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
- pe.Graphics.DrawEllipse(Pens.Black, 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
- pe.Graphics.DrawEllipse(Pens.Black, Center.X - 5, Center.Y - 5, 10, 10);
- }
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- Center = e.Location;
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- if (e.Button == MouseButtons.Left)
- {
- angle = (Math.Atan2(Center.X - e.X, Center.Y - e.Y) * (180 / Math.PI));
- Refresh();
- }
- }
- }
- }
Conical Gradient
0 件のコメント:
コメントを投稿