SetPixel 太慢了。有没有更快的方法来绘制位图?

2024-02-02

我正在开发一个小型绘画程序。我在位图上使用 SetPixel 来绘制线条。当画笔尺寸变大(例如 25 像素)时,性能会明显下降。我想知道是否有更快的方法来绘制位图。以下是该项目的一些背景:

  • 我使用位图,这样我就可以利用图层,就像在 Photoshop 或 GIMP 中一样。
  • 线条是手动绘制的,因为这最终将使用绘图板压力来改变线条在其长度上的大小。
  • 这些线条最终应该沿着边缘进行抗锯齿/平滑处理。

我将包含我的绘图代码,以防万一它是缓慢的而不是设置像素位。

这是在绘画发生的窗口中:

    private void canvas_MouseMove(object sender, MouseEventArgs e)
    {
        m_lastPosition = m_currentPosition;
        m_currentPosition = e.Location;

        if(m_penDown && m_pointInWindow)
            m_currentTool.MouseMove(m_lastPosition, m_currentPosition, m_layer);
        canvas.Invalidate();
    }

鼠标移动的实现:

    public override void MouseMove(Point lastPos, Point currentPos, Layer currentLayer)
    {
        DrawLine(lastPos, currentPos, currentLayer);
    }

绘制线的实现:

    // The primary drawing code for most tools. A line is drawn from the last position to the current position
    public override void DrawLine(Point lastPos, Point currentPos, Layer currentLayer)
    {
        // Creat a line vector
        Vector2D vector = new Vector2D(currentPos.X - lastPos.X, currentPos.Y - lastPos.Y);

        // Create the point to draw at
        PointF drawPoint = new Point(lastPos.X, lastPos.Y);

        // Get the amount to step each time
        PointF step = vector.GetNormalisedVector();

        // Find the length of the line
        double length = vector.GetMagnitude();

        // For each step along the line...
        for (int i = 0; i < length; i++)
        {
            // Draw a pixel
            PaintPoint(currentLayer, new Point((int)drawPoint.X, (int)drawPoint.Y));
            drawPoint.X += step.X;
            drawPoint.Y += step.Y;
        }
    }

PaintPoint 的实现:

    public override void PaintPoint(Layer layer, Point position)
    {
        // Rasterise the pencil tool

        // Assume it is square

        // Check the pixel to be set is witin the bounds of the layer

            // Set the tool size rect to the locate on of the point to be painted
        m_toolArea.Location = position;

            // Get the area to be painted
        Rectangle areaToPaint = new Rectangle();
        areaToPaint = Rectangle.Intersect(layer.GetRectangle(), m_toolArea);

            // Check this is not a null area
        if (!areaToPaint.IsEmpty)
        {
            // Go through the draw area and set the pixels as they should be
            for (int y = areaToPaint.Top; y < areaToPaint.Bottom; y++)
            {
                for (int x = areaToPaint.Left; x < areaToPaint.Right; x++)
                {
                    layer.GetBitmap().SetPixel(x, y, m_colour);
                }
            }
        }
    }

非常感谢您提供的任何帮助。


您可以锁定位图数据并使用指针手动设置值。速度快多了。尽管您必须使用不安全的代码。

public override void PaintPoint(Layer layer, Point position)
    {
        // Rasterise the pencil tool

        // Assume it is square

        // Check the pixel to be set is witin the bounds of the layer

        // Set the tool size rect to the locate on of the point to be painted
        m_toolArea.Location = position;

        // Get the area to be painted
        Rectangle areaToPaint = new Rectangle();
        areaToPaint = Rectangle.Intersect(layer.GetRectangle(), m_toolArea);

        Bitmap bmp;
        BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        int stride = data.Stride;
        unsafe
        {
            byte* ptr = (byte*)data.Scan0;
            // Check this is not a null area
            if (!areaToPaint.IsEmpty)
            {
                // Go through the draw area and set the pixels as they should be
                for (int y = areaToPaint.Top; y < areaToPaint.Bottom; y++)
                {
                    for (int x = areaToPaint.Left; x < areaToPaint.Right; x++)
                    {
                        // layer.GetBitmap().SetPixel(x, y, m_colour);
                        ptr[(x * 3) + y * stride] = m_colour.B;
                        ptr[(x * 3) + y * stride + 1] = m_colour.G;
                        ptr[(x * 3) + y * stride + 2] = m_colour.R;
                    }
                }
            }
        }
        bmp.UnlockBits(data);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SetPixel 太慢了。有没有更快的方法来绘制位图? 的相关文章

  • 即使我没有#include ,为什么仍然可以使用 std::max 和 std::min ?

    include
  • 如何查找boost运行时版本

    我正在编写一个使用 boost 的 C 库 在这个库中 我想包含有关用于编译我的库的二进制版本的 boost 版本的信息 我可以使用宏BOOST VERSION这很好 我还想确定哪个是 boost 的运行时版本 以便我可以与用于编译我的库的
  • 每个 CPU 核心处于 C0 电源状态的时间

    任何帮助弄清楚如何做到这一点都会很棒 在过去一秒内 每个 CPU 核心处于 C0 电源状态的时间有多少 这是针对 Mac 应用程序的 因此需要 Objective C cocoa 和 c OS X 没有任何公开 CPU c 状态的 API
  • 多个源文件中包含包含“const”的头文件

    Why does not包含定义的头文件const并被多个源文件包含会产生编译错误multiple definition const in header file h const int num 5 int x Error Multiple
  • 无法使用 Unity 函数在 Visual Studio Code 中获得完整的 Intellisense

    好吧 我知道这个问题已经被问过并回答过很多次了 但我花了大约 3 天的时间试图解决这个问题 但到目前为止我所做的一切都没有奏效 我基本上在 Visual Studio Code 中有部分智能感知 也就是说 它似乎只识别 Unity 类和变量
  • 如何以编程方式确定 C 中 int 数据的最大和最小限制?

    我正在尝试 K R 的练习 2 1 练习内容如下 编写一个程序来确定范围char short int and long变量 两者signed and unsigned 通过从标准标题打印适当的值并通过直接计算 如果计算它们会更困难 确定各种
  • C++ 克隆惯用语中协变返回类型的用处?

    通常的克隆习惯使用协变返回类型 struct Base virtual Base clone struct Derived public Base Derived clone 我读过一些内容 大意是协变返回类型是 C 后来添加的 较旧的编译
  • 让 WIX 在项目中包含引用

    我对 WiX 和设置自定义安装程序完全陌生 所以我对问题的主题表示歉意 我有一个内部业务应用程序 日记 它构建并运行良好 因此我按照教程 官方文档添加 WiX 项目并引用日记的 csproj 然后构建并运行这个最基本版本的 WiX 安装程序
  • 如何使用 Caliburn.Micro MVVM 将焦点设置到控件

    我有一个表单 我想在发生某些用户操作时将焦点设置到文本框 我知道 MVVM 的处理方式是绑定到 VM 属性 但是 TextBox 没有允许这种情况发生的属性 从虚拟机设置焦点的最佳方法是什么 我创建了一个 IResult 实现 可以很好地实
  • 允许 .NET WebApi 忽略 DOCTYPE 声明

    我正在尝试通过 WebApi 方法将 XML 反序列化为对象 我有以下课程 XmlRoot IsNullable false public class MyObject XmlElement Name public string Name
  • 为什么 MISRA:2012 需要函数原型?

    我想知道为什么 MISRA 2012 需要函数原型 在下面的示例中 这两个原型并不是真正必要的 include
  • 无论表单上的焦点控件如何,如何捕获 Keys.F1?

    我使用了 KeyDown 事件和一些简单的代码 例如if e KeyCode Keys F1 捕获在表单上按下 F1 但如果表单上有一些文本框 或者表单上有一些带有 Dock Fill 的电子表格 则上面的代码将毫无用处并且不执行任何操作
  • 选择要重写哪个基类的方法

    鉴于以下情况 class Observer public virtual void Observe Parameter p 0 template
  • 在同一条线上铸造两次

    我在项目中看到了这段代码 b的类型是void void b int a int unsigned long b 这条线毫无意义吗 我的意思是 这与a int b在所有情况下 这可能会避免 64 位 Unix 系统上的编译器警告unsigne
  • #define, #ifdef #undef #endif

    我有以下代码 define PROC ADD void main void while 1 ifdef PROC ADD Do this code here then undefined it to run the code in the
  • 如何从标准输入读取一行,阻塞直到找到换行符?

    我试图从命令行的标准输入一次读取任意长度的一行 我不确定是否能够包含 GNU readline 并且更喜欢使用库函数 我读过的文档表明getline应该可以工作 但在我的实验中它不会阻塞 我的示例程序 include
  • lambda 表达式是多线程的吗?

    lambda 表达式是多线程的吗 假设当你将数学公式编写为 lambda 方法时 当你将其传递给另一个方法时 它会是多线程的吗 不是100 清楚你问的是什么 您是否想问 lambda 是否自然地在不同的线程上运行 如果是这样 则它们只是 S
  • 为什么C#不支持多重继承? [复制]

    这个问题在这里已经有答案了 可能的重复 C 应该包含多重继承吗 https stackoverflow com questions 191691 should c include multiple inheritance 为什么C 不支持多
  • 如果未返回,则在一段时间后终止线程

    我有一个线程从网络或串行端口获取一些数据 如果 5 秒内没有收到数据 则线程必须终止 或返回 false 换句话说 如果线程运行时间超过 5 秒 则必须停止 我用 C 编写 但任何 NET 语言都可以 有两种方法 1 封装超时 从网络或串行
  • C++20 范围太多 |运营商?

    我在这段代码中使用 g 10 2 有谁知道为什么我最后收到编译器错误std views reverse on results3 include

随机推荐

  • 在 LINQ 查询中将 DateTimeOffset 转换为 DateTime

    当我通过 linq 查询从该表中获取数据并使用时 我的表中有 DateTimeOffset 列 from c in this dbContext SomeTable where c Id someId select new SomeMode
  • 如何自定义 Eclipse 工具栏(Kepler 或一般工具栏)

    我尝试自定义 Eclipse Kepler JavaEE 中的工具栏已经有一段时间了 最终在给定透视图 例如 主 JavaEE 透视图 中按照我想要的方式配置工具栏后 当我切换到不同的透视图 例如 调试透视图 然后再切换回来时 它完全混乱了
  • 模式匹配不等式

    我想从不平等的实例中提取论据 以下不起作用 知道为什么以及如何解决它吗 Inequality 1 Less x Less 2 Inequality a c e gt a c e Inequality 1 Less x Less 2 Hold
  • JBoss AS 7:日志记录

    我对 JBoss AS7 和日志记录有点挣扎 尽管我的问题是一个非常普遍的问题 但我在网络上找不到任何相关内容 默认日志目前如下所示 11 57 29 950 INFO stdout http 0 0 0 0 8081 78 2484089
  • 在 Go 中安装 exp/html

    看起来 Go 还不支持 HTML Web 解析工具 包 尽管它已经通过以下方式提供了 XML 抓取encoding xml 那么我该如何安装exp htmlGo 中的包 据我所知 所有的答案 至少我在网上搜索了10分钟后偶然发现的 都没有返
  • Visual Studio 的评论重花

    是否有内置命令或工具可以在 Visual Studio 中重排 C 注释 有时 一段代码需要多行注释 经过大量编辑后 您必须在适当的位置手动插入换行符 以免它超出编辑器窗口的右边缘 我希望能够通过一个键命令来完成此操作 使用 Visual
  • 使用 ggplot2 在 R 中绘制箱线图

    我是 R 新手 一直在尝试制作箱线图 显示了我正在使用的部分数据 h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 1 0 003719430 0 002975544 0 003049933 0 003421876 0 0034
  • 在 Express / Connect 中配置上下文路径

    我有一个在 Expressconnect Jade Less 上使用 Coffeescript 构建的 Node js 应用程序 该应用程序将部署在几个不同的地方和不同的上下文路径上 例如 http someurl com http som
  • 每个流有多个内核的 CUDA 并发内核执行

    对 CUDA 内核使用不同的流使得并发内核执行成为可能 所以n内核上n如果流适合硬件 理论上它们可以同时运行 对吧 现在我面临以下问题 没有n不同的内核但是n m where m内核需要按顺序执行 例如n 2 and m 3将导致以下带有流
  • 如何查看linux中特定进程每5秒的内存消耗情况

    我只是想知道如何找到特定进程在特定时间 比如5秒 的内存消耗 我是linux新手 因此 详细的步骤将不胜感激 Use top p PID其中 PID 是进程 ID 应显示有关进程的信息 包括使用的系统内存百分比 类型d以及一个以秒为单位的整
  • 条件子句中的赋值是好的 ruby​​ 风格吗?

    为了写得更简洁 而不是这样做 test value method call that might return nil if test value do something with test value end 我一直在条件分配 if t
  • 当我运行 Protractor 时,“Runtime.executionContextCreated 有无效的‘上下文’错误

    当我运行量角器时 我收到以下错误 下面是我的 webstorm 控制台中显示的错误 C Program Files x86 JetBrains WebStorm 2016 2 bin runnerw exe C Program Files
  • 在 PowerShell 脚本中无法通过管道将字符串输入 cmd

    当我直接在 PowerShell 窗口中执行它时 我有以下工作调用 myexe C MyExe exe MyString myexe works Write Output MyString myexe seems to work too 但
  • Visual Studio 2017 - 允许远程用户访问 IIS Express 中的网站

    一直在浏览并尝试我找到的有关该主题的所有指南 但没有运气 我正在使用 HTTPS 运行 MVC 项目 并希望使用一些远程移动设备访问调试站点来测试该网站 我遵循了一个几乎可以工作的指南 我想我已经非常接近让它工作了 以下是我已完成的步骤 关
  • 如何获得可旋转div的四个角旋转手柄?

    我有一个div 用过Jquery UI rotatable旋转 div 的插件 我怎样才能让这个旋转手柄与绿色div的四个角一起旋转 box draggable rotatable 这是示例图像 在黑色圆形标记中我需要放置其他三个可旋转手柄
  • 使用supervisord管理docker容器的最佳方式

    我必须在上面设置 dockerized 环境 集成 质量保证和生产 same服务器 客户端的要求 每个环境的组成如下 rabbitmq celery flower 基于 python 3 的应用程序称为 A 每个特定分支 环境 在它们之上
  • XXX.exe 中发生“System.ExecutionEngineException”类型的未处理异常

    我有一个用 C 编写的 DLL 文件 我尝试在我的 C 代码中使用 C DLL C 方法调用正确 但进程完成后出现错误 异常详细信息 Completed System ExecutionEngineException 未处理 消息 Syst
  • 格式化输出流 ios::left 和 ios::right

    我有这个代码 cout lt lt std setiosflags std ios right cout lt lt setw 3 lt lt 1 lt lt setw 3 lt lt 2 lt lt n Output two values
  • 如何编写 IQueryable 来查询递归数据库表?

    我有一个这样的数据库表 Entity ID int PK ParentID int FK Code varchar Text text The ParentID字段是与同一表中另一条记录的外键 递归 所以该结构代表一棵树 我正在尝试编写一种
  • SetPixel 太慢了。有没有更快的方法来绘制位图?

    我正在开发一个小型绘画程序 我在位图上使用 SetPixel 来绘制线条 当画笔尺寸变大 例如 25 像素 时 性能会明显下降 我想知道是否有更快的方法来绘制位图 以下是该项目的一些背景 我使用位图 这样我就可以利用图层 就像在 Photo