PixelFormat.Format32bppArgb の画像に8方向からアルファ値の傾斜をかける
SetGradientAlpha32 をつくった。
ここでやった AlphaGradient と同じように、LinerGradientBrush をつかって
マスクをつくり、すでに設定されているアルファ値に対して任意の傾斜を
設定できる。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using ImageUtils;
namespace LuminanceToAlpha
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static bool LuminanceToAlpha(Bitmap bmp, bool bStretch,
Color baseColor, out Bitmap result32)
{
result32 = null;
if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
return false;
int w = bmp.Width;
int h = bmp.Height;
Bitmap bw = bmp.Clone() as Bitmap;
ImgUtils.GrayScale(ref bw);
if (bStretch) ImgUtils.HistoStretch(ref bw);
result32 = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(result32);
g.Clear(baseColor);
g.Dispose();
BmpProc8 src = new BmpProc8(bw);
BmpProc32 dst = new BmpProc32(result32);
for (int y = 0; y <h; y++)<br>
for (int x = 0; x <w; x++)<br>
{
dst[x, y, eRGB.a] = (byte)(255 - src[x, y]);
}
ImgUtils.CallDispose(dst, src, bw);
return true;
}
public static bool SetAlpha32(ref Bitmap bmp, int percent)
{
if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
return false;
int w = bmp.Width;
int h = bmp.Height;
double p = percent / 100d;
BmpProc32 dst = new BmpProc32(bmp);
for (int y = 0; y <h; y++)<br>
for (int x = 0; x <w; x++)<br>
{
if (dst[x, y, eRGB.a] == 0) continue;
dst[x, y, eRGB.a] = ImgUtils.AdjustByte(dst[x, y, eRGB.a] * p);
}
dst.Dispose();
return true;
}
public static void DrawImageCenterAt(Graphics g, Bitmap bmp, int x, int y)
{
int xx = x - bmp.Width / 2;
int yy = y - bmp.Height / 2;
g.DrawImage(bmp, xx, yy, bmp.Width, bmp.Height);
}
public static Bitmap GetGradientMask(int width, int height, float[] factor,
float[] position, GradientSide gs)
{
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
Color endColor = Color.White;
Color startColor = Color.Black;
Point start = new Point(-1, 0);
Point end = new Point(0, 0);
switch (gs)
{
case GradientSide.Left:
end.X = width;
break;
case GradientSide.Right:
start.X = width;
break;
case GradientSide.Upper:
end.Y = height;
break;
case GradientSide.Lower:
start.Y = height;
break;
case GradientSide.UpperLeft:
end.X = width;
end.Y = height;
break;
case GradientSide.UpperRight:
start.X = width;
end.Y = height;
break;
case GradientSide.LowerLeft:
start.Y = height;
end.X = width;
break;
case GradientSide.LowerRight:
start.X = width;
start.Y = height;
break;
}
Blend bl = new Blend();
bl.Factors = factor;
bl.Positions = position;
LinearGradientBrush br = new LinearGradientBrush(
start, end, startColor, endColor);
br.Blend = bl;
//br.GammaCorrection = true;
Rectangle rct = new Rectangle(0, 0, width, height);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(br, rct);
g.Dispose();
return bmp;
}
public static bool SetGradientAlpha32(ref Bitmap bmp32, float[] factor,
float[] position, GradientSide gs)
{
if (bmp32.PixelFormat != PixelFormat.Format32bppArgb)
return false;
int w = bmp32.Width;
int h = bmp32.Height;
Bitmap mask = GetGradientMask(w, h, factor, position, gs);
byte a;
BmpProc24 src = new BmpProc24(mask);
BmpProc32 dst = new BmpProc32(bmp32);
for (int y = 0; y <h; y++)<br>
for (int x = 0; x <w; x++)<br>
{
a = dst[x, y, eRGB.a];
if (a == 0) continue;
dst[x, y, eRGB.a] = ImgUtils.AdjustByte(a * src[x, y, eRGB.r] / 255);
}
ImgUtils.CallDispose(dst, src, mask);
return true;
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(@"c:HomeImgWorkSGASample2.png");
int w = bmp.Width;
int h = bmp.Height;
Bitmap tmp1, tmp2;
LuminanceToAlpha(bmp, true, Color.FromArgb(120, 0, 0), out tmp1);
tmp2 = tmp1.Clone() as Bitmap;
float[] position = { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f };
float[] factor = { 1.0f, 0.9f, 0.6f, 0.15f, 0.03f, 0.0f };
SetGradientAlpha32(ref tmp2, factor, position, GradientSide.Left);
Graphics g = this.CreateGraphics();
for (int i = 0; i <4; i++)<br>
{
g.DrawImage(tmp2, 20 + 90 * i, 50 + 45 * i, w, h);
}
g.DrawImage(tmp1, 20 + 90 * 4, 50 + 45 * 4, w, h);
g.Dispose();
tmp2.Dispose();
tmp1.Dispose();
bmp.Dispose();
}
}
}
SGASample2

画像の中心を設定座標になるように描く DrawImageCenterAt をつくった。
非常に簡単な関数だが、こういうのが意外と便利だったりする。

全コードをしめす。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using ImageUtils;
namespace LuminanceToAlpha
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static bool LuminanceToAlpha(Bitmap bmp, bool bStretch,
Color baseColor, out Bitmap result32)
{
result32 = null;
if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
return false;
int w = bmp.Width;
int h = bmp.Height;
Bitmap bw = bmp.Clone() as Bitmap;
ImgUtils.GrayScale(ref bw);
if (bStretch) ImgUtils.HistoStretch(ref bw);
result32 = new Bitmap(w, h, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(result32);
g.Clear(baseColor);
g.Dispose();
BmpProc8 src = new BmpProc8(bw);
BmpProc32 dst = new BmpProc32(result32);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
dst[x, y, eRGB.a] = (byte)(255 - src[x, y]);
}
ImgUtils.CallDispose(dst, src, bw);
return true;
}
public static bool SetAlpha32(ref Bitmap bmp, int percent)
{
if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
return false;
int w = bmp.Width;
int h = bmp.Height;
double p = percent / 100d;
BmpProc32 dst = new BmpProc32(bmp);
for (int y = 0; y < h; y++)
for (int x = 0; x < w; x++)
{
if (dst[x, y, eRGB.a] == 0) continue;
dst[x, y, eRGB.a] = ImgUtils.AdjustByte(dst[x, y, eRGB.a] * p);
}
dst.Dispose();
return true;
}
public static void DrawImageCenterAt(Graphics g, Bitmap bmp, int x, int y)
{
int xx = x - bmp.Width / 2;
int yy = y - bmp.Height / 2;
g.DrawImage(bmp, xx, yy, bmp.Width, bmp.Height);
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(@"c:\Home\ImgWork\CenterAtSample3.png");
int centerX = 450;
int centerY = 450;
double radius = 250d;
int hh;
int ss = 250;
int ll = 50;
byte rr, gg, bb;
int xx, yy;
Bitmap tmp1, tmp2;
Color baseColor;
Graphics g = this.CreateGraphics();
for (int i = 0; i < 10; i++)
{
hh = 36 * i;
ImgUtils.HSLToRGB(hh, ss, ll, out rr, out gg, out bb);
baseColor = Color.FromArgb(rr, gg, bb);
LuminanceToAlpha(bmp, true, baseColor, out tmp1);
tmp2 = ImgUtils.BitmapRotate(tmp1, (float)(hh+90), Color.Transparent);
SetAlpha32(ref tmp2, 85);
xx = (int)(Math.Cos((double)hh / 180d * Math.PI) * radius) + centerX;
yy = (int)(Math.Sin((double)hh / 180d * Math.PI) * radius) + centerY;
DrawImageCenterAt(g, tmp2, xx, yy);
tmp2.Dispose();
tmp1.Dispose();
}
g.Dispose();
bmp.Dispose();
}
}
}
CenterAtSample3


























