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 太慢了。有没有更快的方法来绘制位图? 的相关文章

  • CMake 找不到请求的 Boost 库

    既然我已经浏览了其他人的解决方案几个小时 但找不到适合我的问题的正确答案 我想将我的具体问题带给您 我正在尝试使用 CMake 构建 vsomeip 为此 我之前构建了 boost 1 55 但是 我在 CMake 中收到以下错误 The
  • 您可以从基本 Win32 控制台模板应用程序中的 C#/Winrt 组件调用(不是 WinForm/abstractions/wrappers 或使用 C++/Winrt 模板)吗?)

    我有一个现有的程序 win32 x86 控制台应用程序 需要调用托管代码 来自 Net 的 C dll The dll不暴露给 COM 但可以从 C WinRT 组件调用并由 C WinRT 控制台模板应用引用 BUT即使安装了 C Win
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • C++ 长 switch 语句还是用地图查找?

    在我的 C 应用程序中 我有一些值充当代表其他值的代码 为了翻译代码 我一直在争论使用 switch 语句还是 stl 映射 开关看起来像这样 int code int value switch code case 1 value 10 b
  • 解析 JWT 令牌以仅获取有效负载内容,无需 C# 或 Blazor 中的外部库

    我正在使用 Blazor 编写可以访问 JWT 的客户端应用程序 我想知道一种简单的方法来读取令牌有效负载内容而不添加额外的依赖项 因为我不需要其他信息 也不需要验证令牌 我认为解析有效负载内容应该足够简单 只需将其写入方法即可 JwtTo
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • 有什么方法可以禁用 PDF/Postscript 输出中的“减号破解”吗?

    在 R 中 将绘图保存到 PDF 或 Postscript 文件时 轴标签中的连字符会变成减号 显然 这是设计使然 根据 postscript 设备的文档 正常编码规则 有一个例外 字符 45 始终设置为负号 其在 Adob e ISOLa
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 帮我用光线追踪器解决这个错误

    我不会针对这个问题发布任何代码 因为它需要太多的上下文 但我将从概念上解释我正在做什么 我正在构建一个使用仿射变换的简单光线追踪器 我的意思是 我将来自相机坐标的所有光线与通用形状相交 这些形状都具有关联的仿射变换 并且光线在与场景对象相交
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC

随机推荐

  • 在 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