代码之家  ›  专栏  ›  技术社区  ›  Margus

如何绘制不断变化的图形

  •  2
  • Margus  · 技术社区  · 14 年前

    以前没有这样做过( >除了在Java 中,看看如何< HRFF=“http://StaskOpf.com /用户/ 2959 /史提夫麦克劳德”> Steve McLeod < /a>修复它),所以显然我很讨厌它。这里,当前鼠标位置周围的64个像素在窗体上绘制得稍大一些。问题是,这是“某种程度上”的慢,我不知道从哪里开始修复。

    除此之外,我还制作了一个计时器线程,当它完成时,它会不断调用更新图形和一点类似fps的文本,以显示绘制东西的速度。

    图像示例:(图像来自Microsoft VS2010中“IntelliTrace”中的字母“A”)。

    源示例:

    使用系统;
    使用system.collections.generic;
    使用System.ComponentModel;
    使用系统数据;
    使用系统、图纸;
    使用system.linq;
    使用system.text;
    使用system.windows.forms;
    使用System.Runtime.InteropServices;
    
    命名空间缩放
    {
    公共分部类Form1:Form
    {
    静态类dllref
    {
    [dllimport(“user32.dll”)]
    [返回:marshalas(unmanagedType.bool)]
    静态外部bool getcursorpos(输出点lppoint);
    
    [dllimport(“user32.dll”)]
    静态外部intptr getdc(intptr hwnd);
    
    [dllimport(“user32.dll”)]
    静态外部int32 releasedc(intptr hwnd,intptr hdc);
    
    [dllimport(“gdi32.dll”)]
    静态外部uint getpixel(intptr hdc,int nxpos,int nypos);
    
    //来自http://www.pinvoke.net/default.aspx/gdi32/getpixel.html
    静态公共系统.drawing.color getPixelColor(int x,int y){
    intptr hdc=getdc(intptr.zero);
    uint pixel=获取像素(hdc,x,y);
    释放直流电(Intpr.Zero,HDC);
    color color=color.fromargb((int)(像素&0x000000FF),
    (int)(像素&0x0000 ff00)>>8,
    (int)(像素&0x00ff0000)>>16);
    返回颜色;
    }
    静态公共系统.drawing.point getmouseposition()。{
    点P=新点();
    GETCURSORPOS(输出P);
    返回P;
    }
    }
    
    公共窗体1()。{
    初始化组件();
    this.size=新尺寸(400400);
    this.text=“图像缩放”;
    this.location=新点(640,0);
    this.image=新位图(320、320);
    this.timeRef=datetime.now;
    this.backcolor=color.white;
    timer t=新timer();
    t.间隔=25;
    t.tick+=新事件处理程序(计时器\u tick);
    启动();
    }
    
    公共无效计时器勾号(对象发送方、事件参数搜索){
    this.form1_paint(this,new paintEventArgs(this.creategraphics(),new rectangle(0,0,this.width,this.height));
    }
    
    private bool isdone=真;
    private int iter=0;
    私有位图图像;
    私有日期时间TimeRef;
    private void form1_paint(对象发送器,paintEventArgs e){
    如果(ISDON){
    ISDON=假;
    INT步骤=40;
    点P=dllRef.getMousePosition();
    pen mypen=新笔(color.gray,1);
    solidbrush mybrush=空;
    位图图像2=新位图(320、340);
    
    graphics gc=graphics.fromimage(图像2);
    
    对于(int x=0;x<8;x++){
    对于(int y=0;y<8;y++){
    myBrush=新solidBrush(dllRef.getPixelColor(p.x-4+x,p.y-4+y));
    gc.fillEllipse(myBrush,x*步骤,y*步骤,步骤-3,步骤-3);
    gc.drawEllipse(mypen,x*步骤,y*步骤,步骤-3,步骤-3);
    }
    }
    StringBuilder sb=new StringBuilder();
    追加(ITER)
    .append(“帧输入”)。
    .append(string.format(“0:0.”),((datetime.now this.timeRef.total毫秒)/1000))
    追加(“S”);
    gc.fillRectangle(新solidBrush(this.backcolor)、新矩形(0、320、320、40));
    gc.drawstring(sb.toString(),新字体(“Arial”,12),新solidBrush(color.black),10,320);
    气相色谱法;
    ISDON=真;
    ITER ++;
    图像=IIGE2;
    }
    e.图形。DrawImage(图像,35F,15F);
    }
    }
    }
    < /代码> 
    
    

    在我做了一些修改之后,这个速度快了约98%:

    使用系统;
    使用system.collections.generic;
    使用System.ComponentModel;
    使用系统数据;
    使用系统、图纸;
    使用system.linq;
    使用system.text;
    使用system.windows.forms;
    使用System.Runtime.InteropServices;
    
    
    命名空间缩放
    {
    公共分部类Form1:Form
    {
    静态类dllref
    {
    [dllimport(“user32.dll”)]
    [返回:marshalas(unmanagedType.bool)]
    静态外部bool getcursorpos(输出点lppoint);
    
    [dllimport(“user32.dll”)]
    静态外部intptr getdc(intptr hwnd);
    
    [dllimport(“user32.dll”)]
    静态外部int32 releasedc(intptr hwnd,intptr hdc);
    
    [dllimport(“gdi32.dll”)]
    静态外部uint getpixel(intptr hdc,int nxpos,int nypos);
    
    //来自http://www.pinvoke.net/default.aspx/gdi32/getpixel.html
    静态公共系统.drawing.color getPixelColor(int x,int y){
    intptr hdc=getdc(intptr.zero);
    uint pixel=获取像素(hdc,x,y);
    释放直流电(Intpr.Zero,HDC);
    color color=color.fromargb((int)(像素&0x000000FF),
    (int)(像素&0x0000 ff00)>>8,
    (int)(像素&0x00ff0000)>>16);
    返回颜色;
    }
    静态公共系统.drawing.point getmouseposition()。{
    点P=新点();
    GETCURSORPOS(输出P);
    返回P;
    }
    }
    
    公共窗体1()。{
    初始化组件();
    this.size=新尺寸(400400);
    this.text=“图像缩放”;
    this.location=新点(640,0);
    this.image=新位图(320、340);
    this.timeRef=datetime.now;
    this.backcolor=color.white;
    timer t=新timer();
    t.间隔=25;
    t.tick+=新事件处理程序(计时器\u tick);
    启动();
    }
    
    公共无效计时器勾号(对象发送方、事件参数搜索){
    this.form1_paint(this,new paintEventArgs(this.creategraphics(),new rectangle(0,0,this.width,this.height));
    }
    
    private bool isdone=真;
    private int iter=0;
    私有位图图像;
    私有日期时间TimeRef;
    private void form1_paint(对象发送器,paintEventArgs e){
    如果(ISDON){
    ISDON=假;
    INT步骤=40;
    点P=dllRef.getMousePosition();
    solidbrush mybrush=空;
    bitmap hc=新位图(8,8);
    
    使用(pen mypen=新笔(color.gray,1))
    使用(graphics gc=graphics.fromimage(image))
    使用(graphics gf=graphics.fromimage(hc))
    {
    从屏幕复制(P.X-4,P.Y-4,0,0,新尺寸(8,8)
    copyPixelOperation.sourceCopy);
    
    对于(int x=0;x<8;x++)
    {
    对于(int y=0;y<8;y++)
    {
    myBrush=新solidBrush(hc.getPixel(x,y));
    gc.fillEllipse(myBrush,x*步骤,y*步骤,步骤-3,步骤-3);
    gc.drawEllipse(mypen,x*步骤,y*步骤,步骤-3,步骤-3);
    }
    }
    
    double ts=(datetime.now-this.timeref).totalms)/1000;
    StringBuilder sb=new StringBuilder();
    sb.append(++iter).append(“frames in”).append(string.format(“0:0.”,ts)).append(“s.”);
    
    gc.fillRectangle(新solidBrush(this.backcolor)、新矩形(0、320、320、40));
    gc.drawstring(sb.toString(),新字体(“Arial”,12),新solidBrush(color.black),10,320);
    
    }
    
    ISDON=真;
    }
    e.图形。DrawImage(图像,35F,15F);
    }
    }
    }
    < /代码> <看看怎么样Steve McLeod修好了),所以很明显我很讨厌。这里,当前鼠标位置周围的64个像素在窗体上绘制得稍大一些。问题是,它是'某种'慢,我不知道从哪里开始修复。

    除此之外,我还做了一个计时器线程,当它完成时,它会不断调用更新图形和一些类似于fps的文本,以显示绘制东西的速度。

    图像示例:(图像来自Microsoft VS2010中“IntelliTrace”中的字母“A”)。

    alt text

    实例:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    namespace Zoom
    {
        public partial class Form1 : Form
        {
            static class dllRef
            {
                [DllImport("user32.dll")]
                [return: MarshalAs(UnmanagedType.Bool)]
                static extern bool GetCursorPos(out Point lpPoint);
    
                [DllImport("user32.dll")]
                static extern IntPtr GetDC(IntPtr hwnd);
    
                [DllImport("user32.dll")]
                static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);
    
                [DllImport("gdi32.dll")]
                static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);
    
                // from http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html
                static public System.Drawing.Color getPixelColor(int x, int y) {
                    IntPtr hdc = GetDC(IntPtr.Zero);
                    uint pixel = GetPixel(hdc, x, y);
                    ReleaseDC(IntPtr.Zero, hdc);
                    Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                                 (int)(pixel & 0x0000FF00) >> 8,
                                 (int)(pixel & 0x00FF0000) >> 16);
                    return color;
                }
                static public System.Drawing.Point getMousePosition() {
                    Point p = new Point();
                    GetCursorPos(out p); 
                    return p;
                }
            }
    
            public Form1() {
                InitializeComponent();
                this.Size = new Size(400,400);
                this.Text="Image zoom";
                this.Location = new Point(640, 0);
                this.image = new Bitmap(320, 320);
                this.timeRef = DateTime.Now;
                this.BackColor = Color.White;
                Timer t = new Timer();
                t.Interval = 25;
                t.Tick += new EventHandler(Timer_Tick);
                t.Start();
            }
    
            public void Timer_Tick(object sender, EventArgs eArgs) {
                this.Form1_Paint(this, new PaintEventArgs(this.CreateGraphics(), new Rectangle(0, 0, this.Width, this.Height)));
            }
    
            private bool isdone = true;
            private int iter = 0;
            private Bitmap image;
            private DateTime timeRef;
            private void Form1_Paint(object sender, PaintEventArgs e) {
                if (isdone) {
                    isdone = false;
                    int step = 40;
                    Point p = dllRef.getMousePosition();
                    Pen myPen = new Pen(Color.Gray, 1);
                    SolidBrush myBrush = null;
                    Bitmap image2 = new Bitmap(320, 340);
    
                    Graphics gc = Graphics.FromImage(image2);
    
                    for (int x = 0; x < 8; x++) {
                        for (int y = 0; y < 8; y++) {
                            myBrush = new SolidBrush(dllRef.getPixelColor(p.X - 4 + x, p.Y - 4 + y));
                            gc.FillEllipse(myBrush, x * step, y * step, step - 3, step - 3);
                            gc.DrawEllipse(myPen, x * step, y * step, step - 3, step - 3);
                        }
                    }
                    StringBuilder sb = new StringBuilder();
                    sb.Append(iter)
                            .Append(" frames in ")
                            .Append(String.Format("{0:0.###}", ((DateTime.Now-this.timeRef).TotalMilliseconds)/1000))
                            .Append("s.");
                    gc.FillRectangle(new SolidBrush(this.BackColor), new Rectangle( 0, 320, 320, 40));
                    gc.DrawString(sb.ToString(),new Font("Arial", 12),new SolidBrush(Color.Black), 10, 320);
                    gc.Dispose();
                    isdone = true;
                    iter++;
                    image = image2;
                }
                e.Graphics.DrawImage(image, 35f, 15f);
            }
        }
    }
    

    在我做了一些修改之后,这一个速度提高了约98%:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    
    namespace Zoom
    {
        public partial class Form1 : Form
        {
            static class dllRef
            {
                [DllImport("user32.dll")]
                [return: MarshalAs(UnmanagedType.Bool)]
                static extern bool GetCursorPos(out Point lpPoint);
    
                [DllImport("user32.dll")]
                static extern IntPtr GetDC(IntPtr hwnd);
    
                [DllImport("user32.dll")]
                static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);
    
                [DllImport("gdi32.dll")]
                static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);
    
                // from http://www.pinvoke.net/default.aspx/gdi32/GetPixel.html
                static public System.Drawing.Color getPixelColor(int x, int y) {
                    IntPtr hdc = GetDC(IntPtr.Zero);
                    uint pixel = GetPixel(hdc, x, y);
                    ReleaseDC(IntPtr.Zero, hdc);
                    Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                                 (int)(pixel & 0x0000FF00) >> 8,
                                 (int)(pixel & 0x00FF0000) >> 16);
                    return color;
                }
                static public System.Drawing.Point getMousePosition() {
                    Point p = new Point();
                    GetCursorPos(out p); 
                    return p;
                }
            }
    
            public Form1() {
                InitializeComponent();
                this.Size = new Size(400,400);
                this.Text="Image zoom";
                this.Location = new Point(640, 0);
                this.image = new Bitmap(320, 340);
                this.timeRef = DateTime.Now;
                this.BackColor = Color.White;
                Timer t = new Timer();
                t.Interval = 25;
                t.Tick += new EventHandler(Timer_Tick);
                t.Start();
            }
    
            public void Timer_Tick(object sender, EventArgs eArgs) {
                this.Form1_Paint(this, new PaintEventArgs(this.CreateGraphics(), new Rectangle(0, 0, this.Width, this.Height)));
            }
    
            private bool isdone = true;
            private int iter = 0;
            private Bitmap image;
            private DateTime timeRef;
            private void Form1_Paint(object sender, PaintEventArgs e) {
                if (isdone) {
                    isdone = false;
                    int step = 40;
                    Point p = dllRef.getMousePosition();
                    SolidBrush myBrush = null;
                    Bitmap hc = new Bitmap(8, 8);
    
                    using (Pen myPen = new Pen(Color.Gray, 1))
                    using (Graphics gc = Graphics.FromImage(image))
                    using (Graphics gf = Graphics.FromImage(hc))
                    {
                        gf.CopyFromScreen(p.X - 4, p.Y - 4, 0, 0, new Size(8, 8),
                                CopyPixelOperation.SourceCopy);
    
                        for (int x = 0; x < 8; x++)
                        {
                            for (int y = 0; y < 8; y++)
                            {
                                myBrush = new SolidBrush(hc.GetPixel(x, y));
                                gc.FillEllipse(myBrush, x * step, y * step, step - 3, step - 3);
                                gc.DrawEllipse(myPen, x * step, y * step, step - 3, step - 3);
                            }
                        }
    
                        double ts = ((DateTime.Now - this.timeRef).TotalMilliseconds) / 1000;
                        StringBuilder sb = new StringBuilder();
                        sb.Append(++iter).Append(" frames in ").Append(String.Format("{0:0.###}", ts)).Append("s.");
    
                        gc.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 320, 320, 40));
                        gc.DrawString(sb.ToString(), new Font("Arial", 12), new SolidBrush(Color.Black), 10, 320);
    
                    }
    
                    isdone = true;
                }
                e.Graphics.DrawImage(image, 35f, 15f);
            }
        }
    }
    
    1 回复  |  直到 14 年前
        1
  •  4
  •   Community CDub    7 年前

    GetDC ReleaseDC

    for each pixel
      GetDC
      Read Pixel
      ReleaseDC
    

    GetDC
    for each pixel
      read pixel and store value
    ReleaseDC
    

    GetPixel Capture the Screen into a Bitmap