C#加速Bitmap存图

如果希望大幅提高图像保存速度,特别是在处理非常大的图像时,可以尝试以下更直接、更高效的方法:

1. 避免使用 Bitmap 类的 Save 方法
Bitmap.Save 方法的速度受限于 GDI+ 库的操作,尤其是对于非常大的图像,它可能会经历内存分配、像素格式转换等多重开销。我们可以通过直接操作图像数据流来绕过这些问题。

2. 直接将图像数据写入文件(原始像素数据)
对于大型图像,您可以直接将图像的像素数据转换为 BMP 格式的二进制流,并快速写入文件。BMP 格式是一个非常简单的无压缩格式,因此您可以手动构造 BMP 文件头和像素数据流。

下面是一个使用 原始图像数据流 写入RGB-BMP 文件的例子:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;class Program
{static void Main(){// 创建一个较大的 Bitmap 对象(例如 5000x5000)Bitmap bitmap = new Bitmap(5000, 5000);// 在这里填充图像,模拟数据using (Graphics g = Graphics.FromImage(bitmap)){g.Clear(Color.Blue);  // 蓝色背景}// 保存为 BMP 格式SaveBitmapAsBmpFast(bitmap, "output.bmp");}static void SaveBitmapAsBmpFast(Bitmap bitmap, string filePath){// 锁定位图数据Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);// 创建文件流using (FileStream fs = new FileStream(filePath, FileMode.Create)){// 计算图像文件大小int rowSize = bitmapData.Stride;int dataSize = rowSize * bitmap.Height;// BMP 文件头byte[] fileHeader = new byte[14] {0x42, 0x4D,             // 'BM'标识符0, 0, 0, 0,             // 文件大小(稍后设置)0, 0,                   // 保留字段0, 0,                   // 保留字段0x36, 0x00, 0x00, 0x00  // 位图数据的偏移量};fs.Write(fileHeader, 0, fileHeader.Length);// 信息头byte[] infoHeader = new byte[40] {0x28, 0x00, 0x00, 0x00,  // 信息头大小(byte)(bitmap.Width & 0xFF), (byte)((bitmap.Width >> 8) & 0xFF), 0, 0, // 图像宽度(byte)(bitmap.Height & 0xFF), (byte)((bitmap.Height >> 8) & 0xFF), 0, 0, // 图像高度0x01, 0x00,              // 颜色平面0x18, 0x00,              // 每像素位数(24位,RGB)0x00, 0x00, 0x00, 0x00,  // 压缩方法0x00, 0x00, 0x00, 0x00,  // 图像大小(0表示未压缩)0x13, 0x0B, 0x00, 0x00,  // 水平分辨率(假设为72 DPI)0x13, 0x0B, 0x00, 0x00,  // 垂直分辨率0x00, 0x00, 0x00, 0x00,  // 调色板数量(0表示不使用调色板)0x00, 0x00, 0x00, 0x00   // 重要颜色数量};fs.Write(infoHeader, 0, infoHeader.Length);// 写入像素数据byte[] buffer = new byte[dataSize];Marshal.Copy(bitmapData.Scan0, buffer, 0, buffer.Length);fs.Write(buffer, 0, buffer.Length);}// 解锁位图数据bitmap.UnlockBits(bitmapData);Console.WriteLine("Image saved as BMP (fast).");}
}

下面是一个使用 原始图像数据流 写入Gray-BMP 文件的例子:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;class Program
{static void Main(){// 创建一个灰度图像的 Bitmap 对象(例如 5000x5000)Bitmap bitmap = new Bitmap(5000, 5000, PixelFormat.Format8bppIndexed);// 创建一个调色板,包含256个灰度颜色ColorPalette palette = bitmap.Palette;for (int i = 0; i < 256; i++){palette.Entries[i] = Color.FromArgb(i, i, i);  // 设置灰度颜色}bitmap.Palette = palette;// 填充灰度图像using (Graphics g = Graphics.FromImage(bitmap)){for (int x = 0; x < bitmap.Width; x++){for (int y = 0; y < bitmap.Height; y++){// 创建一个灰度值(在此示例中,使用随机值)int grayValue = (x + y) % 256;  // 这里使用简单的算法产生灰度值,实际应用中可以按需要设置bitmap.SetPixel(x, y, Color.FromArgb(grayValue, grayValue, grayValue));}}}// 保存为 BMP 格式SaveBitmapAsBmpFast(bitmap, "output_gray_8bpp.bmp");}static void SaveBitmapAsBmpFast(Bitmap bitmap, string filePath){// 锁定位图数据Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);// 创建文件流using (FileStream fs = new FileStream(filePath, FileMode.Create)){// 计算图像文件大小int rowSize = bitmapData.Stride;int dataSize = rowSize * bitmap.Height;// BMP 文件头byte[] fileHeader = new byte[14] {0x42, 0x4D,             // 'BM'标识符0, 0, 0, 0,             // 文件大小(稍后设置)0, 0,                   // 保留字段0, 0,                   // 保留字段0x36, 0x00, 0x00, 0x00  // 位图数据的偏移量};fs.Write(fileHeader, 0, fileHeader.Length);// 信息头byte[] infoHeader = new byte[40] {0x28, 0x00, 0x00, 0x00,  // 信息头大小(byte)(bitmap.Width & 0xFF), (byte)((bitmap.Width >> 8) & 0xFF), 0, 0, // 图像宽度(byte)(bitmap.Height & 0xFF), (byte)((bitmap.Height >> 8) & 0xFF), 0, 0, // 图像高度0x01, 0x00,              // 颜色平面0x08, 0x00,              // 每像素位数(8位灰度图)0x00, 0x00, 0x00, 0x00,  // 压缩方法0x00, 0x00, 0x00, 0x00,  // 图像大小(0表示未压缩)0x13, 0x0B, 0x00, 0x00,  // 水平分辨率(假设为72 DPI)0x13, 0x0B, 0x00, 0x00,  // 垂直分辨率0x00, 0x00, 0x00, 0x00,  // 调色板数量(0表示不使用调色板)0x00, 0x00, 0x00, 0x00   // 重要颜色数量};fs.Write(infoHeader, 0, infoHeader.Length);// 调色板(256个灰度颜色)byte[] colorTable = new byte[1024];  // 256个条目,每个条目4字节(ARGB)for (int i = 0; i < 256; i++){colorTable[i * 4] = (byte)i;        // RcolorTable[i * 4 + 1] = (byte)i;    // GcolorTable[i * 4 + 2] = (byte)i;    // BcolorTable[i * 4 + 3] = 0x00;       // A (透明度)}fs.Write(colorTable, 0, colorTable.Length);// 写入像素数据byte[] buffer = new byte[dataSize];Marshal.Copy(bitmapData.Scan0, buffer, 0, buffer.Length);fs.Write(buffer, 0, buffer.Length);}// 解锁位图数据bitmap.UnlockBits(bitmapData);Console.WriteLine("Grayscale image (8bpp) saved as BMP (fast).");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI系统】算子开发编程语言 Ascend C

算子开发编程语言 Ascend C 本节将深入探讨昇腾算子开发编程语言 Ascend C&#xff0c;这是一种专为昇腾 AI 处理器算子开发设计的编程语言&#xff0c;它原生支持 C 和 C标准规范&#xff0c;最大化匹配用户的开发习惯。Ascend C 通过多层接口抽象、自动并行计算、孪生调试等…

Python基于大数据的微博的舆情分析,机器学习的微博情感分析系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

WPF+LibVLC开发播放器-LibVLC播放控制

接上一篇&#xff1a; LibVLC在C#中的使用 实现LibVLC播放器播放控制 界面 界面上添加一个Button按钮用于控制播放 <ButtonGrid.Row"1"Width"88"Height"24"Margin"10,0,0,0"HorizontalAlignment"Left"VerticalAlignme…

【设计模式系列】中介者模式(十八)

一、什么是中介者模式 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;其核心思想是通过一个中介者对象来封装一系列对象之间的交互&#xff0c;使这些对象不需要相互显式引用。中介者模式提供了一个中介层&#xff0c;用以协调各个对象…

18-1_需求调研记录

1 一轮系统部署的硬件环境需求调研记录 项目名称 不动产统一登记信息系统 调研时间 调研地点 区各市政务服务大厅 调研对象 全区各不动产登记事务中心 系统 序号 新增需求或问题 是否实现 实现方案 硬件环境调研 1 不动产统一登记信息系…

【AI系统】Ascend C 编程范式

Ascend C 编程范式 AI 的发展日新月异&#xff0c;AI 系统相关软件的更新迭代也是应接不暇&#xff0c;作为一本讲授理论的作品&#xff0c;我们将尽可能地讨论编程范式背后的原理和思考&#xff0c;而少体现代码实现&#xff0c;以期让读者理解 Ascend C 为何这样设计&#x…

【Linux】重定向、管道符、通配符、转义字符、环境变量

声明&#xff1a;以下内容均学习自《Linux就该这么学》一书。 1、输入输出重定向 输入重定向&#xff1a; 指把文件导入到命令中&#xff1b; 标准输入重定向STDIN 文件描述符为0。默认从键盘输入&#xff0c;也可以从其他文件或命令中输入。 输入重定向符号及作用 命令 &…

是什么阻断了kafka与zk的链接?

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 问题描述&#xff1a; 前几天部署一套环境&#xff0c;先把zk集群起来了&#xff0c;之后第二天在启动kafka的时候&#xff0c;…

CentOS 二进制安装部署MongoDB 4.0

一、安装MongoDB 1. 下载 MongoDB 二进制文件 前往 MongoDB 官方下载页面(https://www.mongodb.com/try/download/community) 选择对应版本的 tar 包。 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.28.tgz 2. 解压并移动至目标目录 解压文件&#xff…

【数据结构】【线性表】特殊的线性表-字符串

目录 字符串的基本概念 字符串的三要素 字符串的基本概念 串的编码 串的实现及基本运算 顺序串的实现 串的静态数组实现 串的动态数组的实现 顺序存储的四种方案 链式串的实现 基本运算 方案三 方案一 字符串的基本概念 数据结构千千万&#xff0c…

Agile VMO分享:海尔案例

海尔集团是全球最大的家电制造商之一&#xff0c;拥有超过76 000名员工。它获得了2018-2019年全球智能家电品牌前10名和2018-2019年全球消费电子品牌前50名的荣誉。 海尔利用价值流结构将自己组织成一些可以自管理的微型企业。这些微型企业拥有决策&#xff0c;设计和交付新产品…

ThinkPHP场景动态验证

一、缘由 今天在用thinkphp8写东西的时候发现&#xff0c;写验证器规则和场景优点费时间&#xff0c;就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。 就突发奇想能不能自动生成验证器&#xff0c;也不能是说自动生成验证器&#xff0c;生成验证其的…

限定符使用

正则表达式的元字符一次一般只能匹配一个位置或一个字符,如果想要匹配零个、一个或多个字符时,则需要使用限定符。限定符用于指定允许特定字符或字符集自身重复出现的次数。常用限定符如下: <asp:TextBox [^>]> 正则表达式字符类[^>]匹配除过“>”之外的任何字…

vue3+vite 批量引入组件动态使用

import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…

电脑关机的趣味小游戏——system函数、strcmp函数、goto语句的使用

文章目录 前言一. system函数1.1 system函数清理屏幕1.2 system函数暂停运行1.3 system函数电脑关机、重启 二、strcmp函数三、goto语句四、电脑关机小游戏4.1. 程序要求4.2. 游戏代码 总结 前言 今天我们写一点稍微有趣的代码&#xff0c;比如写一个小程序使电脑关机&#xf…

VScode离线下载扩展安装

在使用VScode下在扩展插件时&#xff0c;返现VScode搜索不到插件&#xff0c;网上搜了好多方法&#xff0c;都不是常规操作&#xff0c;解决起来十分麻烦&#xff0c;可以利用离线下载安装的方式安装插件&#xff01;亲测有效&#xff01;&#xff01;&#xff01; 1.找到VScod…

数据结构基础之《(10)—快速排序》

一、快速排序基础 1、Partition过程 给定一个数组arr&#xff0c;和一个整数num。请把小于等于num的数放在数组的左边&#xff0c;大于num的数放在数组的右边。 要求额外空间复杂度O(1)&#xff0c;时间复杂度O(N) 2、例子 区分小于等于num的数 (<区) [5 3 7 2 3 4 1] num…

Java 网络编程详解:UDP 与 TCP 编程核心知识

Java 网络编程是现代开发中不可或缺的一部分&#xff0c;尤其是在分布式系统、即时通讯、在线游戏、以及 IoT&#xff08;物联网&#xff09;等场景中&#xff0c;网络编程的作用更为重要。在 Java 中&#xff0c;网络编程主要涉及两种传输协议&#xff1a;UDP&#xff08;用户…

2023年第十四届蓝桥杯Scratch国赛真题—推箱子

推箱子 程序演示及其源码解析&#xff0c;可前往&#xff1a; https://www.hixinao.com/scratch/creation/show-188.html 若需在线编程&#xff0c;在线测评模考&#xff0c;助力赛事可自行前往题库中心&#xff0c;按需查找&#xff1a; https://www.hixinao.com/ 题库涵盖…

【QNX+Android虚拟化方案】133 - 88Q5152 如何读取 C22,GLB1,GLB2,C45等寄存器

【QNX+Android虚拟化方案】133 - 88Q5152 如何读取 C22,GLB1,GLB2,C45等寄存器 1. C22 Port i Reg j 寄存器读取2. GLB1 寄存器读取3. GLB2 寄存器读取4. 读取 C45 寄存器基于原生纯净代码,自学总结 纯技术分享,不会也不敢涉项目、不泄密、不传播代码文档!!! 本文禁止转载…