合成图片源码:
elements是6个Bitmap对象数组合成一张图片的时间约莫1秒,由于项目每次要多次合成图片,每次要耗费时间7、8秒,速度太慢,希望高手提供更好的方法!this.s_image = new Bitmap(this.Body.Width, this.Body.Height);
Graphics g = Graphics.FromImage(this.s_image);
for (int i = 0; i < elements.Length; i++)
{
if (elements[i] != null)
{
if (i != 4)
{
g.DrawImage(elements[i], p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height);
}
else
{
if (has_glassses)
{
g.DrawImage(elements[i], p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height);
}
}
}
}
g.Dispose();
elements是6个Bitmap对象数组合成一张图片的时间约莫1秒,由于项目每次要多次合成图片,每次要耗费时间7、8秒,速度太慢,希望高手提供更好的方法!this.s_image = new Bitmap(this.Body.Width, this.Body.Height);
Graphics g = Graphics.FromImage(this.s_image);
for (int i = 0; i < elements.Length; i++)
{
if (elements[i] != null)
{
if (i != 4)
{
g.DrawImage(elements[i], p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height);
}
else
{
if (has_glassses)
{
g.DrawImage(elements[i], p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height);
}
}
}
}
g.Dispose();
我曾经处理两张大图融合(要做个特效出来),花了10几秒
C++如果让我用估计也快不到哪去
对Photoshop的图片处理技术一直很眼红
曾经尝试过国外牛人们写的Paint(C#),速度真是慢到家了,要不Photoshop怎么能卖钱呢
年末,有点忙要赶回家~代码有时间给你上啊~O(∩_∩)O哈哈~
用 Bitmap 中的 LockBits 索定 this.s_image ,
然后 把DrawImage 换成直接操作 LockBits的指针数据就可以 了。
速度应该可以提高50倍,或更多
如果没有透明和拉伸的需求,建议直接用GDI的函数
1.利用BitBlt合成图片
public void SetImage()
{
DateTime dt = DateTime.Now;
if (this.Body != null)
{
this.s_image = new Bitmap(this.Body.Width, this.Body.Height);
using (Graphics g = Graphics.FromImage(this.s_image))
{
IntPtr hdc = g.GetHdc();
DateTime dt4 = DateTime.Now;
IntPtr memdc = Win32Support.CreateCompatibleDC(hdc);
Console.WriteLine("创建层:" + (DateTime.Now - dt4));
for (int i = 0; i < elements.Length; ++i)
{
if (elements[i] != null)
{
DateTime dt3 = DateTime.Now;
Win32Support.SelectObject(memdc, elements[i].GetHbitmap());
Console.WriteLine("创建第" + i + "层:" + (DateTime.Now - dt3));
using (Graphics memDc = Graphics.FromHdc(memdc))
{
IntPtr shdc = memDc.GetHdc();
if (i != 4)
{
DateTime dt1 = DateTime.Now;
Win32Support.BitBlt(hdc, p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height,
shdc, 0, 0, Win32Support.TernaryRasterOperations.SRCCOPY);
Console.WriteLine("绘制第" + i + "层:" + (DateTime.Now - dt1));
}
else
{
if (has_glassses)
{
DateTime dt1 = DateTime.Now;
Win32Support.BitBlt(hdc, p_list.PointArray[i].X, p_list.PointArray[i].Y, this.Body.Width, this.Body.Height,
shdc, 0, 0, Win32Support.TernaryRasterOperations.SRCCOPY);
Console.WriteLine("绘制第" + i + "层:" + (DateTime.Now - dt1));
}
}
memDc.ReleaseHdc(shdc);
}
}
}
g.ReleaseHdc(hdc);
}
}
Console.WriteLine("总共:" + (DateTime.Now - dt));
}速度没有提高,并只显示最后一层,透明处全部成黑色2.利用BitmapData合成图片public void SetImage(){
DateTime dt = DateTime.Now;
if (this.Body != null)
{
int w = Convert.ToInt32(this.Body.Width * _scale);
int h = Convert.ToInt32(this.Body.Height * _scale); this.s_image = new Bitmap(w, h);
BitmapData dataOut = this.s_image.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
for (int i = 0; i < elements.Length; ++i)
{
if (elements[i] != null)
{
if (i != 4)
{
try
{
DateTime dt1 = DateTime.Now;
Rectangle rect = new Rectangle(0, 0, w, h);
DrawImage(ref dataOut, elements[i], rect);
Console.WriteLine("绘制第" + i + "层:" + (DateTime.Now - dt1));
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
else
{
if (has_glassses)
{
DateTime dt1 = DateTime.Now;
Rectangle rect = new Rectangle(0, 0, w, h);
DrawImage(ref dataOut, elements[i], rect);
Console.WriteLine("绘制第" + i + "层:" + (DateTime.Now - dt1));
}
}
}
}
this.s_image.UnlockBits(dataOut);
}
Console.WriteLine("共用时间:" + (DateTime.Now - dt));
}
private void DrawImage(ref BitmapData dataOut, Bitmap btpIn, Rectangle rect)
{
BitmapData dataIn = btpIn.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* pIn = (byte*)(dataIn.Scan0.ToPointer());
byte* pOut = (byte*)(dataOut.Scan0.ToPointer()); for (int y = 0; y < dataIn.Height; y++)
{
for (int x = 0; x < dataIn.Width; x++)
{
if ((int)pIn[4] != 0)
{
pOut[0] = pIn[0];
pOut[1] = pIn[1];
pOut[2] = pIn[2];
pOut[4] = pIn[4];
}
pIn += 3;
pOut += 3;
}
pIn += dataIn.Stride - dataIn.Width * 3;
pOut += dataOut.Stride - dataOut.Width * 3;
}
}
btpIn.UnlockBits(dataIn);
}
速度没有提高,也是显示最后一层,透明处全部成白色还没有其他方法!现在项目一运行就的等待10多秒钟!慢死了
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;
namespace neicun
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
Bitmap m_Bmp = new Bitmap("d:\\nvhai.bmp");
int h = m_Bmp.Height;
int w = m_Bmp.Width; Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format24bppRgb); BitmapData dataIn = m_Bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData dataOut = bmpOut.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); unsafe
{
byte* pIn = (byte*)(dataIn.Scan0.ToPointer());
byte* pOut = (byte*)(dataOut.Scan0.ToPointer()); for (int y = 0; y < dataIn.Height; y++)
{
for (int x = 0; x < dataIn.Width; x++)
{ pOut[1] = pOut[0];
pOut[2] = pOut[0]; pIn += 3;
pOut += 3;
} pIn += dataIn.Stride - dataIn.Width * 3;
pOut += dataOut.Stride - dataOut.Width * 3;
}
} bmpOut.UnlockBits(dataOut);
m_Bmp.UnlockBits(dataIn);
pictureBox1.Image = bmpOut;
}
}
}
指针法,要勾上允许执行不安全代码,还有个内存法,不过现在找不到代码了
//内存法,大概2.5毫秒一张.
private void memory_Click(object sender, EventArgs e)
{
if (curBitmap != null)
{
myTimer.ClearTimer();
myTimer.Start();
Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height * 3;
byte[] rgbValues = new byte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
double colorTemp = 0;
for (int i = 0; i < rgbValues.Length; i += 3)
{
colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114;
rgbValues[i] = rgbValues[i + 1] = rgbValues[i + 2] = (byte)colorTemp;
}
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
curBitmap.UnlockBits(bmpData);
myTimer.Stop();
timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒";
Invalidate();
}
}
也就是要绘制36张A4大小的图。
A4大小2479x3508像素
每个像素4个通道。
每次绘制,需要计算颜色重叠,也就是2479*3508*4*3*36=3756815424次乘法运算。
37亿次乘法运算。
cpu累死了,大哥。怎么着也要6,7秒啊。
除非你能自己重写图片重叠的算法,并且能优化它。
万一你写出来了,记得去申请个专利,卖个100w没问题。
首先,检测最后一张图片,完全不透明的点,先绘制上去,因为他们会把前面35张都挡掉,也就是前面35张都百画了。
然后检测透明点(alpha不为255的点)。
对于每一个不透明点,检测35--1张,发现有alpha==255的点,则不再往前检测。比如,23-35的这一点alpha值都小于255,22张的这一点alpha为255.则只需要计算22--36的像素半透明融合。
这个算法可以在非常大程度上改进速度,但是也要看你的36张图具体而言。比如第36张为全不透明,那几十毫秒就结束了。
如果36张全他妈的是半透明的,那没办法,10s钟像素覆盖融合算法自己找找吧,我写过,但是忘记扔哪里去了。
为什么要一个象素一个象素的弄。直接画整个图片不可以嘛??g.DrawImage(picture)