C#合并BitMap图像生成超 * itmap
作者:记住我Gxy 发布时间:2023-12-08 18:24:11
标签:C#,合并,BitMap
当只需要两个图像合并的时候,可以简单的使用gdi+,把两个图像画到一个画布上面实现合并bitmap.
当需要将许多bitmap合并时,由于bitmap类限制,长度或宽度太大时会报异常,前面这种方法就行不通了。
由于bitmapp属于位图格式,了解图像格式后,发现,bitmap文件的第3-8位存储了文件大小信息,第19-22位存储了高度信息,第23-26位存储了宽度信息。文件头后面都是像素的argb,并无其它信息。于是,试想一下,如果把第二张图像的像素argb放到第一张后面,并修改第一张的文件头信息,是不是就可以实现文件合并了呢。事实证明:yes。
//设置文件头里面文件大小信息
public void SetBitmapFileSizeInfo(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
long le = fileInfo.Length;
string hexSize = le.ToString("X").PadLeft(8, '0');
int size1 = Convert.ToInt32(hexSize.Substring(0, 2), 16);
int size2 = Convert.ToInt32(hexSize.Substring(2, 2), 16);
int size3 = Convert.ToInt32(hexSize.Substring(4, 2), 16);
int size4 = Convert.ToInt32(hexSize.Substring(6, 2), 16);
byte[] sizeBytes = new byte[] { (byte)size4, (byte)size3, (byte)size2, (byte)size1 };
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Write))
{
using (BinaryWriter r = new BinaryWriter(fs))
{
r.Seek(2, 0);
r.Write(sizeBytes, 0, sizeBytes.Length);
}
}
}
设置文件头里面文件长度和宽度信息
public void SetBitmapSizeInfo(string filePath,int width=0,int height=0)
{
if (height != 0)
{
string hexHeight = height.ToString("X").PadLeft(8, '0');
int h1 = Convert.ToInt32(hexHeight.Substring(0, 2), 16);
int h2 = Convert.ToInt32(hexHeight.Substring(2, 2), 16);
int h3 = Convert.ToInt32(hexHeight.Substring(4, 2), 16);
int h4 = Convert.ToInt32(hexHeight.Substring(6, 2), 16);
byte[] sizeHeight = new byte[] { (byte)h4, (byte)h3, (byte)h2, (byte)h1 };
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (BinaryWriter r = new BinaryWriter(fs))
{
r.Seek(22, 0);//高度保存位置
r.Write(sizeHeight, 0, sizeHeight.Length);
}
}
}
if (width != 0)
{
string hexWidth = height.ToString("X").PadLeft(8, '0');
int w1 = Convert.ToInt32(hexWidth.Substring(0, 2), 16);
int w2 = Convert.ToInt32(hexWidth.Substring(2, 2), 16);
int w3 = Convert.ToInt32(hexWidth.Substring(4, 2), 16);
int w4 = Convert.ToInt32(hexWidth.Substring(6, 2), 16);
byte[] sizeWidth = new byte[] { (byte)w4, (byte)w3, (byte)w2, (byte)w1 };
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
using (BinaryWriter r = new BinaryWriter(fs))
{
r.Seek(18, 0);//高度保存位置
r.Write(sizeWidth, 0, sizeWidth.Length);
}
}
}
}
合并多个bitmap文件,并生成一个最终文件
private void CreateBitMap(string tempPath,string imagePath)
{
string[] files = Directory.GetFiles(tempPath, "*.png");
Bitmap bmp;
int height=0;
for (int i = files.Length-1; i >0; i--)
{
string fileName = files[i];
bmp = new Bitmap(fileName);
if (i == files.Length - 1)
{
bmp.Save(imagePath, ImageFormat.Bmp);
height += bmp.Height;
bmp.Dispose();
continue;
}
else
{
byte[] bytes = GetImageRasterBytes(bmp, PixelFormat.Format32bppRgb);
using (FileStream fs = new FileStream(imagePath, FileMode.Open, FileAccess.Write))
{
fs.Seek(fs.Length, 0);
fs.Write(bytes, 0, bytes.Length);
}
height += bmp.Height;
bmp.Dispose();
}
}
SetBitmapFileSizeInfo(imagePath);
SetBitmapSizeInfo(imagePath, height: height);
//MessageBox.Show("合并成功");
}
private static byte[] GetImageRasterBytes(Bitmap bmp, PixelFormat format)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
byte[] bits = null;
try
{
// Lock the managed memory
BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, format);
// Declare an array to hold the bytes of the bitmap.
bits = new byte[bmpdata.Stride * bmpdata.Height];
// Copy the values into the array.
System.Runtime.InteropServices.Marshal.Copy(bmpdata.Scan0, bits, 0, bits.Length);
// Release managed memory
bmp.UnlockBits(bmpdata);
}
catch
{
return null;
}
return bits;
}
来源:https://blog.csdn.net/qq_35669328/article/details/100696671
0
投稿
猜你喜欢
- 序言使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式:一、基于注解(@Scheduled)二、基于接口(Schedu
- 想要实现一个功能:同一个用户在两个不同的浏览器中登录,后面的踢掉之前的登录。本来的思路是在httpSession * 中进行判断。但是在使用
- 概述MerkleTree被广泛的应用在比特币技术中,本文旨在通过代码实现一个简单的MerkleTree,并计算出Merkle tree的 T
- Parallel类是对线程的一个抽象。该类位于System.Threading.Tasks名称空间中,提供了数据和任务并行性。Paralle
- 前言最近一直被无尽的业务需求淹没,没时间喘息,终于接到一个能让我突破代码舒适区的活儿,解决它的过程非常曲折,一度让我怀疑人生,不过收获也很大
- 一、BufferedImage类介绍生成验证码图片主要用到了一个BufferedImage类,如下:创建一个DrawImage Servle
- 一、需要导入的jar1.commons-collections4-4.1.jar2.poi-3.17-beta1.jar3.poi-ooxm
- 什么是volatile关键字volatile是Java中用于修饰变量的关键字,其可以保证该变量的可见性以及顺序性,但是无法保证原子性。更准确
- 简单介绍equals方法是java.lang.Object类的方法有两种用法说明:一、对于字符串变量来说,使用“==”和“equals()”
- 1、线程的控制很常见,如文件传送到一半时,需要暂停文件传送,或终止文件传送,这实际上就是控制线程的运行。2、线程有创建、可运行、运行中、阻塞
- 首先看一看什么是装箱和拆箱?简单的来说:装箱就是值类型转换为引用类型;拆箱就是引用类型转换为值类型。值类型,包括原类型(Sbyte、Byte
- 把三状态转换图放在这,方便分析方法的作用:1.Session的save()方法Session是Hibernate所有接口中最重要的接口,提供
- 最近要做一个java web项目,因为页面不是很多,所以就没有前后端分离,前后端写在一起,这时候就用到thymeleaf了,以下是不动脑式的
- C# 获取某个时间的0点0分和23点59分59秒,具体代码如下所示:C#获取当月第一天和最后一天当月第一天0时0分0秒:DateTime.N
- 本文实例为大家分享了Java界面编程实现界面跳转的具体代码,供大家参考,具体内容如下在事件处理中创建对象public void action
- 我们知道,Java和MySQL中的数据类型是不同的,Java中除了基本数据类型,还有对象。有时候使用MySQL存储数据,或者从MySQL中读
- 一、简介地图控件自v2.3.5版本起,支持多实例,即开发者可以在一个页面中建立多个地图对象,并且针对这些对象分别操作且不会产生相互干扰。文件
- 详细描述maven中央仓库发布jar包的中间过程, 以及遇到的一些问题汇总, 尽量用文字描述清楚, 耐心看下去, 就一定会发布成功----S
- 一、前言在java中,异常机制是非常有用的构成部分,异常信息对于查找错误来说是必不可少至关重要的信息,因此我们希望在发生错误的时候先看到捕捉
- 现在Java的大部分项目都是基于Maven, 在Maven项目中使用Selenium2. 非常简单。 首先你需要配置好