俩小时写的软件,生成签字图片分分钟,上传效果大家看看。猜猜是谁?
好玩吧!
原理很简单。
1、遍历图片
2、判断当前点覆盖的签字区域的灰度值。
3、设定一个阈值,如果超过阈值,绘图签字区域。并且将原图对应的区域变浅。
下面是核心部分代码:
private void btnCreateImg_Click(object sender, RoutedEventArgs e)
{
if (imagePen == null || imageImg == null)
{
MessageBox.Show("请选择原图!");
return;
}
//原图尺寸
int imageWidth = imageImg.PixelWidth;
int imageHeight = imageImg.PixelHeight;
//签字图尺寸
int penWidth = imagePen.PixelWidth;
int penHeight = imagePen.PixelHeight;
int deepRate = int.Parse(tbDeepRate.Text);
double shardowRate = double.Parse(tbShadowRate.Text);
WriteableBitmap writeImage = new WriteableBitmap(imageWidth, imageHeight,
72, 72, PixelFormats.Bgra32, null);
bdTarget.Source = writeImage;
//ARGB
int totalSize = imageWidth * imageHeight;
int penSize = penWidth * penHeight;
byte[] b = new byte[4 * totalSize];
byte[] penb = new byte[4 * penSize];
byte[] writeImg = Enumerable.Repeat((byte)0xff, 4 * totalSize).ToArray();
Int32Rect rect = new Int32Rect(0, 0, imageWidth, imageHeight);
imageImg.CopyPixels(rect, b, 4 * imageWidth, 0);
Int32Rect rectPen = new Int32Rect(0, 0, penWidth, penHeight);
imagePen.CopyPixels(rectPen, penb, 4 * penWidth, 0);
//白 0 黑 255
byte[] avgB = new byte[totalSize];
for (int i = 0; i < totalSize; i++)
{
avgB[i] = (byte)(255 - (b[i * 4 + 1] + b[i * 4 + 2] + b[i * 4 + 0]) / 3);
}
//白 0 黑 255
byte[] avgP = new byte[penSize];
for (int i = 0; i < penSize; i++)
{
avgP[i] = (byte)(255 - (penb[i * 4 + 1] + penb[i * 4 + 2] + penb[i * 4 + 0]) / 3);
}
int times = 1;
int curIJ = 0;
double maxClr = -1;
int maxX = 0;
int maxY = -1;
Random rdm = new Random();
while(true)
{
#if false
//斜着写
maxY++;//增加一行
if (maxY > curIJ || maxY >= imageHeight - penHeight)//最后一行
{
curIJ++;
if (curIJ >= imageWidth - penWidth)
{
maxY = curIJ - (imageWidth - penWidth) + 1;
if (maxY >= imageHeight - penHeight)
{
break;
}
}
else
{
maxY = 0;
}
}
maxX = curIJ - maxY;
maxClr = GetPixClr(maxX, maxY, penWidth, penHeight, imageWidth, avgB, avgP);
if (maxClr < shardowRate * penSize)
{
continue;
}
#else
if (maxY == -1)
{
maxY = 0;
}
maxX++;
if (maxX >= imageWidth - penWidth)
{
maxX = 0;
maxY++;
if (maxY >= imageHeight - penHeight)
{
break;
}
}
maxClr = GetPixClr(maxX, maxY, penWidth, penHeight, imageWidth, avgB, avgP);
if (maxY == 0)
{
double rdmrate = shardowRate * rdm.Next(1, 7);
if (maxClr < rdmrate * penSize)
{
continue;
}
}
else if (maxClr < shardowRate * penSize)
{
continue;
}
#endif
byte gray = 0;
for (int i = 0; i < penWidth; i++)
{
for (int j = 0; j < penHeight; j++)
{
if (avgB[(maxY + j) * imageWidth + maxX + i] > (deepRate + avgP[j * penWidth + i]))
{
avgB[(maxY + j) * imageWidth + maxX + i] -= (byte)(deepRate + avgP[j * penWidth + i]);
}
else
{
avgB[(maxY + j) * imageWidth + maxX + i] = 0;
}
gray = (byte)((avgP[j * penWidth + i]) * 0.5);
if (writeImg[((maxY + j) * imageWidth + maxX + i) * 4] > gray)
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4] -= gray;
}
else
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4] = 0;
}
if (writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 1] > gray)
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 1] -= gray;
}
else
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 1] = 0;
}
if (writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 2] > gray)
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 2] -= gray;
}
else
{
writeImg[((maxY + j) * imageWidth + maxX + i) * 4 + 2] = 0;
}
}
}
writeImage.WritePixels(new System.Windows.Int32Rect(0, 0, imageWidth, imageHeight), writeImg,
imageWidth * 4, 0);
tbCount.Text = times.ToString();
times++;
DoEvents();
}
RenderTargetBitmap bmp = new RenderTargetBitmap((int)bdTarget.ActualWidth, (int)bdTarget.ActualHeight,
96, 96, PixelFormats.Pbgra32);
bmp.Render(bdTarget);
JpegBitmapEncoder encode = new JpegBitmapEncoder();
encode.Frames.Add(BitmapFrame.Create(bmp));
MemoryStream ms = new MemoryStream();
encode.Save(ms);
byte[] byteSource = ms.ToArray();
File.WriteAllBytes("Export.jpg", byteSource);
}
private double GetPixClr(int x, int y, int penWidth, int penHeight, int imgWidth, byte[] avgB, byte[] avgP)
{
double totalClr = 0;
for (int i = 0; i < penWidth; i++)
{
for (int j = 0; j < penHeight; j++)
{
totalClr += avgB[(y + j) * imgWidth + x + i] * (avgP[j * penWidth + i] / 255.0);
}
}
return totalClr;
}