使用: new Bitmap2(bitmap); //代替原有的Bitmap即可
版本:20240513
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms.VisualStyles;
using BitmapD = System.Drawing.Bitmap;
namespace Sci
{
public class Bitmap2
{
/// <summary>
/// Bitmap数据源
/// </summary>
public BitmapD bitmap;
/// <summary>
/// 图像宽度
/// </summary>
public int Width;
/// <summary>
/// 图像高度
/// </summary>
public int Height;
/// <summary>
/// 图像保存格式
/// </summary>
public PixelFormat PixelFormat;
/// <summary>
/// 图像所有像素的颜色值
/// </summary>
int[,] Datas = null;
/// <summary>
/// 从Bitmap构造Bitmap2
/// </summary>
/// <param name="bitmap"></param>
public Bitmap2(BitmapD bitmap0) // 执行耗时: 2毫秒0微秒
{
this.bitmap = bitmap0;
Width = bitmap0.Width; // 图像宽度
Height = bitmap0.Height; // 图像高度
PixelFormat = bitmap0.PixelFormat; // 图像保存格式
Datas = ColorsInt2(bitmap0, 0, 0, Width, Height); // 获取图像所有颜色信息
}
~Bitmap2()
{
if (bitmap != null)
{
bitmap.Dispose();
bitmap = null;
}
}
/// <summary>
/// 摘要:
/// 获取此 System.Drawing.Bitmap 中指定像素的颜色。
/// 参数:
/// x: 要检索的像素的 x 坐标。
/// y: 要检索的像素的 y 坐标。
/// </summary>
public Color GetPixel(int x, int y)
{
return Color.FromArgb(Datas[x, y]);
}
int White = Color.White.ToArgb();
int Black = Color.Black.ToArgb();
/// <summary>
/// 在此Bitmap上,设置指定像素的颜色
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="color"></param>
public void SetPixel(int x, int y, Color color)
{
Datas[x, y] = color.ToArgb();
}
/// <summary>
/// 获取像素对应的Int颜色值
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int GetPixel_Int(int x, int y)
{
return Datas[x, y];
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public BitmapD ToBitmap() // 执行耗时: 0微秒
{
BitmapD tmp = ToBitmap(Datas, Width, Height);
if (tmp.PixelFormat == PixelFormat) return tmp;
else
{
BitmapD tmp2 = tmp.Clone(new Rectangle(0, 0, tmp.Width, tmp.Height), PixelFormat); // 与原有格式不相同,则转化回原有格式
tmp.Dispose();
return tmp2;
}
}
/ <summary>
/ 转化为Drawing.Bitmap
/ </summary>
/ <returns></returns>
//public BitmapD ToBitmap_SetPixel() // 执行耗时: 1秒271毫秒72微秒
//{
// BitmapD pic = new BitmapD(Width, Height);
// // 获取所有(x, y)坐标位置的像素信息
// for (int y = 0; y < Height; y++)
// {
// for (int x = 0; x < Width; x++)
// {
// Color color = GetPixel(x, y);
// pic.SetPixel(x, y, color);
// }
// }
// return pic;
//}
#region Int32颜色值 (从低到高,每8位依次为BGRA)。二维数组
/// <summary>
/// 从非托管代码区中快速获取图像指定区域的像素信息 (可用)
/// </summary>
public static int[,] ColorsInt2(BitmapD bmp0, int x0, int y0, int width0, int height0) // 执行耗时: 51毫秒3微秒 // 执行耗时: 19毫秒1微秒 // 执行耗时: 25毫秒1微秒
{
bool needTransFormat = bmp0.PixelFormat != PixelFormat.Format32bppArgb ? true : false; // 是否需要进行格式转化
BitmapD bmp = !needTransFormat ? bmp0 : bmp0.Clone(new Rectangle(0, 0, bmp0.Width, bmp0.Height), PixelFormat.Format32bppArgb); // 非Argb格式,转化为该格式
int width = bmp.Width;
int height = bmp.Height;
int[,] colors = new int[width0, height0];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(x0, y0, width0, height0), ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
IntPtr ptr = bmpData.Scan0; // 获取在非托管内存中的位置
int ofs = 0;
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < height0; y++)
{
ofs = y * bmpData.Stride;
for (int x = 0; x < width0; x++)
{
//ofs = y * bmpData.Stride + x * 4; (单句计算当前偏移值)
按字节读取(可用)
//ofs = y * bmpData.Stride + x * 4;
//byte A = Marshal.ReadByte(ptr, ofs + 3);
//byte R = Marshal.ReadByte(ptr, ofs + 2);
//byte G = Marshal.ReadByte(ptr, ofs + 1);
//byte B = Marshal.ReadByte(ptr, ofs + 0);
//colors[x, y] = ToColor_Int(A, R, G, B);
//ofs += 4;
// 按Int32读取
colors[x, y] = Marshal.ReadInt32(ptr, ofs);
ofs += 4;
}
}
return colors;
}
finally
{
// 解锁内存区域
bmp.UnlockBits(bmpData);
if (needTransFormat) bmp.Dispose();
}
}
/// <summary>
/// 转化为Drawing.Bitmap (可用)
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap(int[,] color, int Width, int Height) // 执行耗时: 4毫秒0微秒 // 执行耗时: 28毫秒1微秒
{
BitmapD bitmap = new BitmapD(Width, Height, PixelFormat.Format32bppArgb);
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
int ofs = 0;
// 拷贝像素数据到数组
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Marshal.WriteInt32(bmpData.Scan0, ofs, color[x, y]);
ofs += 4;
}
}
// 解锁内存区域
bitmap.UnlockBits(bmpData);
return bitmap;
}
/// <summary>
/// 获取一维数组中的颜色值
/// </summary>
/// <returns></returns>
public static Color GetCorlor(int[] colors, int Width, int x, int y)
{
return Color.FromArgb(colors[y * Width + x]);
}
/// <summary>
/// byte数据转化为Int颜色值
/// </summary>
/// <param name="A"></param>
/// <param name="R"></param>
/// <param name="G"></param>
/// <param name="B"></param>
/// <returns></returns>
public static int ToColor_Int(byte A, byte R, byte G, byte B)
{
int C = 0;
C = C | A;
C = C << 8;
C = C | R;
C = C << 8;
C = C | G;
C = C << 8;
C = C | B;
return C;
}
#endregion
}
}
版本:2024-05-12
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using BitmapD = System.Drawing.Bitmap;
namespace Bitmap2.Sci
{
public class Bitmap
{
/// <summary>
/// Bitmap数据源
/// </summary>
public BitmapD bitmap;
/// <summary>
/// 图像宽度
/// </summary>
public int Width;
/// <summary>
/// 图像高度
/// </summary>
public int Height;
/// <summary>
/// 图像保存格式
/// </summary>
PixelFormat PixelFormat;
/// <summary>
/// 单个像素的位数
/// </summary>
int PixelBit;
/// <summary>
/// 单个像素的字节数
/// </summary>
int PixelBytes;
/// <summary>
/// 图像数据的总位数
/// </summary>
long PixelBitAll;
/// <summary>
/// 图像数据的总字节数
/// </summary>
int Length;
/// <summary>
/// Bitmap托管的内存数据
/// </summary>
byte[] Datas = null;
/// <summary>
/// 从Bitmap构造Bitmap2
/// </summary>
/// <param name="bitmap"></param>
public Bitmap(BitmapD bitmap0) // 执行耗时: 2毫秒0微秒
{
BitmapD bitmap = TypeFormat(bitmap0); // 图像格式化
this.bitmap = bitmap0;
Width = bitmap.Width; // 图像宽度
Height = bitmap.Height; // 图像高度
PixelFormat = bitmap.PixelFormat; // 图像保存格式
PixelBit = Image.GetPixelFormatSize(PixelFormat); // 单个像素的位数
PixelBytes = PixelBit / 8; // 单个像素的字节数
PixelBitAll = Width * Height * PixelBit; // 图像数据的总位数
Length = (int)(PixelBitAll / 8 + (PixelBitAll % 8 > 0 ? 1 : 0)); // 图像数据的总字节数
GetData();
bitmap = null;
}
~Bitmap()
{
if (bitmap != null)
{
bitmap.Dispose();
bitmap = null;
}
}
/// <summary>
/// 图像类型格式化为1位、8位、24位、或32位
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
private BitmapD TypeFormat(BitmapD bitmap)
{
int PixelBit = Image.GetPixelFormatSize(bitmap.PixelFormat); // 单个像素的位数
if (PixelBit == 1 || PixelBit == 8 || PixelBit == 24 || PixelBit == 32) return bitmap; //
else
{
PixelFormat type = PixelBit < 8 ? PixelFormat.Format8bppIndexed : PixelFormat.Format32bppArgb;
BitmapD tmp = bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), type); // 将其它位数的图像转化为8位或32位
return tmp;
}
}
/// <summary>
/// 获取图像对应的数据信息
/// </summary>
private void GetData()
{
Datas = new byte[Length];
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadOnly, PixelFormat);
// 拷贝像素数据到数组
Marshal.Copy(bmpData.Scan0, Datas, 0, Length);
// 解锁内存区域
bitmap.UnlockBits(bmpData);
}
/// <summary>
/// 获取像素位置处的数据
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
private byte[] GetPixelBytes(int x, int y)
{
byte[] Bytes = new byte[PixelBytes];
long sourceIndex = (y * Width + x) * PixelBytes; // 获取坐标(x,y)位置处,像素对应的数据位置
Array.Copy(Datas, sourceIndex, Bytes, 0, PixelBytes); // 获取像素对应数据
return Bytes;
}
/// <summary>
/// 获取二进制位信息
/// </summary>
/// <param name="x">列</param>
/// <param name="y">行</param>
/// <returns></returns>
private bool GetBit(int x, int y)
{
int bitIndex = (y * Width + x); // bit, 像素位置
int b = Datas[bitIndex / 8] ; // bit, 所在字节位置的字节数据
int bitIndex2 = bitIndex % 8; // bit, 在字节中的位置
if(bitIndex2 > 0) b = b << bitIndex2; // bit,移动到最左侧
b = b >> 7; // bit,移动到最右侧
return b == 1;
}
/// <summary>
/// 摘要:
/// 获取此 System.Drawing.Bitmap 中指定像素的颜色。
/// 参数:
/// x: 要检索的像素的 x 坐标。
/// y: 要检索的像素的 y 坐标。
/// </summary>
public Color GetPixel(int x, int y)
{
if (PixelBit == 1) return GetBit(x, y) ? Color.White : Color.Black; // 1位黑白图像
else
{
byte[] bytes = GetPixelBytes(x, y);
if (bytes.Length == 4) return Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]); // 4字节ARGB图像
else if (bytes.Length == 3) return Color.FromArgb(bytes[2], bytes[1], bytes[0]); // 3字节RGB图像
else return Color.FromArgb(bytes[0], bytes[0], bytes[0]); // 1字节灰度图像
}
}
int White = Color.White.ToArgb();
int Black = Color.Black.ToArgb();
/// <summary>
/// 获取像素对应的Int颜色值
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int GetPixel_Int(int x, int y)
{
if (PixelBit == 1) return GetBit(x, y) ? White : Black; // 1位黑白图像
else
{
byte[] bytes = GetPixelBytes(x, y);
if (bytes.Length == 4) return ToColor_Int(bytes[3], bytes[2], bytes[1], bytes[0]); // 4字节ARGB图像
else if (bytes.Length == 3) return ToColor_Int(255, bytes[2], bytes[1], bytes[0]); // 3字节RGB图像
else return ToColor_Int(255, bytes[0], bytes[0], bytes[0]); // 1字节灰度图像
}
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public BitmapD ToBitmap() // 执行耗时: 0微秒
{
return ToBitmap(Datas, Width, Height);
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public BitmapD ToBitmap32() // 执行耗时: 138毫秒7微秒
{
int[] colors = new int[Width * Height];
int i = 0;
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Color color = GetPixel(x, y);
colors[i++] = color.ToArgb();
}
}
return ToBitmap(colors, Width, Height);
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public BitmapD ToBitmapInt() // 执行耗时: 145毫秒8微秒
{
int[] colors = new int[Width * Height];
int i = 0;
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
colors[i++] = GetPixel_Int(x, y);
}
}
return ToBitmap(colors, Width, Height);
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public BitmapD ToBitmap_SetPixel() // 执行耗时: 1秒271毫秒72微秒
{
BitmapD pic = new BitmapD(Width, Height);
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Color color = GetPixel(x, y);
pic.SetPixel(x, y, color);
}
}
return pic;
}
#region 从内存中,一次获取所有像素
#region byte颜色值
/// <summary>
/// 从内存中快速获取图像像素数据(因图像有很多种格式,直接获取数据,用处不大)
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
private byte[] pixInfo(BitmapD bmp)
{
int width = bmp.Width;
int height = bmp.Height;
int pixelBits = Image.GetPixelFormatSize(bmp.PixelFormat); // 图像像素的保存位数
int allBits = width * height * pixelBits; // 图像数据的总位数
int allBytes = allBits / 8 + (allBits % 8 > 0 ? 1 : 0); // 图像数据的总字节数
byte[] datas = new byte[allBytes];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0; // 获取数据,非托管内存指针起点
Marshal.Copy(ptr, datas, 0, datas.Length); // 拷贝像素数据到数组
// 解锁内存区域
bmp.UnlockBits(bmpData);
return datas;
}
/// <summary>
/// 转化为Drawing.Bitmap
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap(byte[] colors, int Width, int Height) // 执行耗时: 0微秒
{
BitmapD bitmap = new BitmapD(Width, Height, PixelFormat.Format32bppArgb);
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
// 复制图像数据到图像对应的内存中
Marshal.Copy(colors, 0, bmpData.Scan0, colors.Length);
// 解锁内存区域
bitmap.UnlockBits(bmpData);
return bitmap;
}
#endregion
#region 获取Color颜色值、从Color生成图像
/// <summary>
/// 从非托管代码区中快速获取图像所有像素信息(可用)
/// </summary>
public static Color[,] Colors(BitmapD bmp0) // 执行耗时: 140毫秒8微秒 // 执行耗时: 52毫秒2微秒 // 执行耗时: 43毫秒2微秒
{
int pixelBits = Image.GetPixelFormatSize(bmp0.PixelFormat);
BitmapD bmp = pixelBits == 32 ? bmp0 : bmp0.Clone(new Rectangle(0, 0, bmp0.Width, bmp0.Height), PixelFormat.Format32bppArgb);
int width = bmp.Width;
int height = bmp.Height;
Color[,] colors = new Color[width, height];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
byte[] datas = new byte[width * height * 4];
Marshal.Copy(bmpData.Scan0, datas, 0, datas.Length); // 拷贝像素数据到数组
int i = 0;
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
colors[x, y] = Color.FromArgb(datas[i + 3], datas[i + 2], datas[i + 1], datas[i + 0]);
i = i + 4;
}
}
return colors;
}
finally
{
// 解锁内存区域
bmp.UnlockBits(bmpData);
if (pixelBits != 32) bmp.Dispose();
}
}
/// <summary>
/// 从非托管代码区中快速获取图像指定区域的像素信息
/// </summary>
public static Color[,] Colors(BitmapD bmp0, int x0, int y0, int width0, int height0) // 执行耗时: 51毫秒3微秒
{
int pixelBits = Image.GetPixelFormatSize(bmp0.PixelFormat);
BitmapD bmp = pixelBits == 32 ? bmp0 : bmp0.Clone(new Rectangle(0, 0, bmp0.Width, bmp0.Height), PixelFormat.Format32bppArgb);
int width = bmp.Width;
int height = bmp.Height;
Color[,] colors = new Color[width0, height0];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(x0, y0, width0, height0), ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
IntPtr ptr = bmpData.Scan0; // 获取在非托管内存中的位置
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < height0; y++)
{
for (int x = 0; x < width0; x++)
{
int ofs = y * bmpData.Stride + x * 4;
byte A = Marshal.ReadByte(ptr, ofs + 3);
byte R = Marshal.ReadByte(ptr, ofs + 2);
byte G = Marshal.ReadByte(ptr, ofs + 1);
byte B = Marshal.ReadByte(ptr, ofs + 0);
colors[x, y] = Color.FromArgb(A, R, G, B);
}
}
return colors;
}
finally
{
// 解锁内存区域
bmp.UnlockBits(bmpData);
if(pixelBits != 32) bmp.Dispose();
}
}
/// <summary>
/// 转化为Drawing.Bitmap (可用)
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap(Color[,] color, int Width, int Height) // 执行耗时: 74毫秒4微秒
{
BitmapD bitmap = new BitmapD(Width, Height, PixelFormat.Format32bppArgb);
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
int ofs = 0;
// 拷贝像素数据到数组
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
//Color c = color[x, y];
//Marshal.WriteInt32(bmpData.Scan0, ofs, ToColor_Int(c.A, c.R, c.G, c.B));
Marshal.WriteInt32(bmpData.Scan0, ofs, color[x, y].ToArgb());
ofs += 4;
}
}
// 解锁内存区域
bitmap.UnlockBits(bmpData);
return bitmap;
}
/// <summary>
/// 转化为Drawing.Bitmap(可用)
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap_SetPixel(Color[,] color, int Width, int Height) // 执行耗时: 1秒237毫秒70微秒
{
BitmapD pic = new BitmapD(Width, Height);
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
pic.SetPixel(x, y, color[x, y]);
}
}
return pic;
}
#endregion
#region Int32颜色值 (从低到高,每8位依次为BGRA)。二维数组
/// <summary>
/// 从非托管代码区中快速获取图像指定区域的像素信息 (可用)
/// </summary>
public static int[,] ColorsInt2(BitmapD bmp0, int x0, int y0, int width0, int height0) // 执行耗时: 51毫秒3微秒 // 执行耗时: 19毫秒1微秒 // 执行耗时: 25毫秒1微秒
{
int pixelBits = Image.GetPixelFormatSize(bmp0.PixelFormat);
BitmapD bmp = pixelBits == 32 ? bmp0 : bmp0.Clone(new Rectangle(0, 0, bmp0.Width, bmp0.Height), PixelFormat.Format32bppArgb);
int width = bmp.Width;
int height = bmp.Height;
int[,] colors = new int[width0, height0];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(x0, y0, width0, height0), ImageLockMode.ReadOnly, bmp.PixelFormat);
try
{
IntPtr ptr = bmpData.Scan0; // 获取在非托管内存中的位置
int ofs = 0;
// 获取所有(x, y)坐标位置的像素信息
for (int y = 0; y < height0; y++)
{
ofs = y * bmpData.Stride;
for (int x = 0; x < width0; x++)
{
//ofs = y * bmpData.Stride + x * 4; (单句计算当前偏移值)
按字节读取(可用)
//ofs = y * bmpData.Stride + x * 4;
//byte A = Marshal.ReadByte(ptr, ofs + 3);
//byte R = Marshal.ReadByte(ptr, ofs + 2);
//byte G = Marshal.ReadByte(ptr, ofs + 1);
//byte B = Marshal.ReadByte(ptr, ofs + 0);
//colors[x, y] = ToColor_Int(A, R, G, B);
//ofs += 4;
// 按Int32读取
colors[x, y] = Marshal.ReadInt32(ptr, ofs);
ofs += 4;
}
}
return colors;
}
finally
{
// 解锁内存区域
bmp.UnlockBits(bmpData);
if (pixelBits != 32) bmp.Dispose();
}
}
/// <summary>
/// 转化为Drawing.Bitmap (可用)
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap(int[,] color, int Width, int Height) // 执行耗时: 4毫秒0微秒 // 执行耗时: 28毫秒1微秒
{
BitmapD bitmap = new BitmapD(Width, Height, PixelFormat.Format32bppArgb);
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
int ofs = 0;
// 拷贝像素数据到数组
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Marshal.WriteInt32(bmpData.Scan0, ofs, color[x, y]);
ofs += 4;
}
}
// 解锁内存区域
bitmap.UnlockBits(bmpData);
return bitmap;
}
#endregion
#region Int32颜色值 (从低到高,每8位依次为BGRA)。一维数组
/// <summary>
/// 从非托管代码区中快速获取图像指定区域的像素信息(可用)
/// </summary>
public static int[] ColorsInt(BitmapD bmp0, int x0, int y0, int width0, int height0) // 执行耗时: 51毫秒3微秒 // 执行耗时: 22毫秒1微秒 // 执行耗时: 23毫秒1微秒 // 执行耗时: 4毫秒0微秒
{
int pixelBits = Image.GetPixelFormatSize(bmp0.PixelFormat);
BitmapD bmp = pixelBits == 32 ? bmp0 : bmp0.Clone(new Rectangle(0, 0, bmp0.Width, bmp0.Height), PixelFormat.Format32bppArgb);
int[] colors = new int[width0 * height0];
// 锁定位图的内存区域
BitmapData bmpData = bmp.LockBits(new Rectangle(x0, y0, width0, height0), ImageLockMode.ReadOnly, bmp.PixelFormat);
if (x0 == 0 && y0 == 0 && width0 == bmp0.Width && height0 == bmp0.Height)
{
Marshal.Copy(bmpData.Scan0, colors, 0, colors.Length); // 整体复制
}
else
{
int ofs = 0;
int i = 0;
for (int y = 0; y < height0; y++)
{
ofs = (y + y0) * bmpData.Stride; // 等效, ofs = (y + y0) * bmp.Width * 4; 获取的是每行开始处的字节偏移值(一个像素,4个字节)
for (int x = 0; x < width0; x++)
{
colors[i++] = Marshal.ReadInt32(bmpData.Scan0, ofs); // 逐个像素进行复制
ofs += 4;
}
}
}
// 解锁内存区域
bmp.UnlockBits(bmpData);
if (pixelBits != 32) bmp.Dispose();
return colors;
}
/// <summary>
/// 转化为Drawing.Bitmap(可用)
/// </summary>
/// <returns></returns>
public static BitmapD ToBitmap(int[] colors, int Width, int Height) // 执行耗时: 0微秒 // 执行耗时: 2毫秒0微秒
{
BitmapD bitmap = new BitmapD(Width, Height, PixelFormat.Format32bppArgb);
// 锁定位图的内存区域
BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
// 复制图像数据到图像对应的内存中
Marshal.Copy(colors, 0, bmpData.Scan0, colors.Length);
// 解锁内存区域
bitmap.UnlockBits(bmpData);
return bitmap;
}
/// <summary>
/// 获取一维数组中的颜色值
/// </summary>
public static byte[] GetCorlor_Byte(int[] colors, int Width, int x, int y) // 等效Color.Argb()
{
int color = colors[y * Width + x];
byte B = (byte)(color & 255);
color = color >> 8;
byte G = (byte)(color & 255);
color = color >> 8;
byte R = (byte)(color & 255);
color = color >> 8;
byte A = (byte)(color & 255);
return new byte[] { A, R, G, B };
}
/// <summary>
/// 获取一维数组中的颜色值
/// </summary>
public static int GetCorlor_Int(int[] colors, int Width, int x, int y)
{
return colors[y * Width + x];
}
/// <summary>
/// 获取一维数组中的颜色值
/// </summary>
/// <returns></returns>
public static Color GetCorlor(int[] colors, int Width, int x, int y)
{
return Color.FromArgb(colors[y * Width + x]);
}
/// <summary>
/// byte数据转化为Int颜色值
/// </summary>
/// <param name="A"></param>
/// <param name="R"></param>
/// <param name="G"></param>
/// <param name="B"></param>
/// <returns></returns>
public static int ToColor_Int(byte A, byte R, byte G, byte B)
{
int C = 0;
C = C | A;
C = C << 8;
C = C | R;
C = C << 8;
C = C | G;
C = C << 8;
C = C | B;
return C;
}
#endregion
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Bitmap2.Sci
{
/// <summary>
/// 统计代码运行时长(用于记录代码执行耗时信息)
/// </summary>
public class LogTime
{
/// <summary>
/// 示例
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void example(object sender, EventArgs e)
{
LogTime.Start();
// 待统计时长的代码...
string timeStr = LogTime.CurrentStackTrace();
MessageBox.Show(timeStr);
LogTime.End("自定义注释信息"); // LogTime.End();
}
static Dictionary<string, long> timeDic = new Dictionary<string, long>();
/// <summary>
/// 记录log的开始时间
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public static void Start(int num = 0)
{
string key = CurrentMethod(2) + System.Threading.Thread.CurrentThread.ManagedThreadId + "_" + num; // 获取调用Start()函数的函数名
timeDic.Add(key, DateTime.Now.Ticks); // 记录当前调用时间
}
/// <summary>
/// 记录指定log的结束时间
/// </summary>
public static void End(int num = 0, string msg = "")
{
long curTime = DateTime.Now.Ticks;
int threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
string key = CurrentMethod(2) + threadId + "_" + num; // 获取调用End()函数的函数名
if (timeDic.ContainsKey(key))
{
long preTime = timeDic[key]; // 获取Start()函数的调用时间
if (msg.Length > 0) msg = "(" + msg + ")";
string info = " " + CurrentMethod(2) + msg + " -> 执行耗时: " + getTimeSpan(curTime, preTime); // 生成耗时信息
ThreadPool.QueueUserWorkItem((state) => { Write(info, threadId); }); // 记录至log中
timeDic.Remove(key);
}
}
/// <summary>
/// 记录指定log的结束时间
/// </summary>
public static void End(string msg)
{
End(0, msg);
}
/// <summary>
/// 获取调用当前函数的方法名(索引1),
/// </summary>
/// <returns></returns>
public static string CurrentMethod(int index = 1)
{
StackTrace stackTrace = new StackTrace();
StackFrame stackFrame = stackTrace.GetFrame(index);
return ToString(stackFrame, true);
}
/// <summary>
/// 获取当前调用堆栈信息
/// </summary>
/// <returns></returns>
public static string CurrentStackTrace()
{
return ToString(new StackTrace());
}
private static string ToString(StackTrace stackTrace, bool simple = false)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < stackTrace.FrameCount; i++)
{
StackFrame stackFrame = stackTrace.GetFrame(i);
sb.AppendLine(ToString(stackFrame, simple));
}
return sb.ToString();
}
private static string ToString(StackFrame stackFrame, bool simple = false)
{
if (simple) return stackFrame.GetMethod() + " ";
else return stackFrame.GetFileName() + " -> " + stackFrame.GetMethod() + ",行号:" + stackFrame.GetFileLineNumber() + ",列号:" + stackFrame.GetFileColumnNumber();
}
static int[] unit = { 1000, 1000, 60, 60, 60, 24, 365 };
static string[] unitName = { "微秒", "毫秒", "秒", "分", "时", "天", "年" };
/// <summary>
/// 获取耗时时长
/// </summary>
/// <param name="curTime"></param>
/// <param name="preTime"></param>
/// <returns></returns>
private static string getTimeSpan(long curTime, long preTime)
{
long tickSpan = (curTime - preTime) / 10;
if (tickSpan < 0) tickSpan = -tickSpan;
string timeStr = "";
for (int i = 0; i < unit.Length; i++)
{
int unitI = unit[i];
if (tickSpan % unitI >= 0) timeStr = (tickSpan % unitI) + unitName[i] + timeStr;
if (tickSpan > unitI) tickSpan = tickSpan / unitI;
else break;
}
return timeStr;
}
/// <summary>
/// 向TimeLog中添加信息
/// </summary>
/// <param name="info"></param>
/// <param name="newLine"></param>
/// <param name="time"></param>
/// <returns></returns>
public static bool Write(string info, int threadid = 0, bool newLine = true, bool time = true)
{
try
{
string logPath = Application.StartupPath + "\\LogTime";
if (!Directory.Exists(logPath))
{
Directory.CreateDirectory(logPath);
}
string threadId = (threadid == 0 ? System.Threading.Thread.CurrentThread.ManagedThreadId : threadid) + "";
logPath = logPath + "\\" + DateTime.Now.ToString("yyyyMMdd_HH") + ((DateTime.Now.Minute / 5 * 5) + "").PadLeft(2, '0') + "00_" + threadId + ".txt"; // 每5分钟,输出至一个log文件中,不同线程输出至不同文件中
string data = info;
if (time) data = "[" + DateTime.Now.ToString("HH:mm:ss") + "] " + data;
if (newLine) data = "\r\n" + data;
File.AppendAllText(logPath, data, Encoding.Unicode);
return true;
}
catch (Exception)
{
return false;
}
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Bitmap2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//LogTime.example(null, null);
Test4();
}
private void Test4()
{
Sci.LogTime.Start(1);
string picPath = "pic\\2.png";
Bitmap pic = Bitmap.FromFile(picPath) as Bitmap; // 执行耗时: 29毫秒1微秒
Sci.LogTime.End(1, "载入图像");
//Sci.LogTime.Start(2);
//int[] colors = Sci.Bitmap.ColorsInt(pic, 0, 0, pic.Width, pic.Height);
//Sci.LogTime.End(2, "Sci.Bitmap.Colors(pic, 0, 0, pic.Width, pic.Height)");
//Sci.LogTime.Start(3);
//Bitmap pic3 = Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height);
//Sci.LogTime.End(3, "Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height)");
Sci.LogTime.Start(2);
int[] colors = Sci.Bitmap.ColorsInt(pic, pic.Width / 4, pic.Height / 4, pic.Width / 2, pic.Height / 2);
Sci.LogTime.End(2, "Sci.Bitmap.Colors(pic, 0, 0, pic.Width, pic.Height)");
Sci.LogTime.Start(3);
Bitmap pic3 = Sci.Bitmap.ToBitmap(colors, pic.Width / 2, pic.Height / 2);
Sci.LogTime.End(3, "Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height)");
Sci.LogTime.Start(4);
pic3.Save(picPath + "_2.png");
Sci.LogTime.End(4, "保存图像");
}
private void Test3()
{
Sci.LogTime.Start(1);
string picPath = "pic\\2.png";
Bitmap pic = Bitmap.FromFile(picPath) as Bitmap;
Sci.LogTime.End(1, "载入图像");
Sci.LogTime.Start(2);
int[,] colors = Sci.Bitmap.ColorsInt2(pic, pic.Width / 4, pic.Height / 4, pic.Width / 2, pic.Height / 2);
Sci.LogTime.End(2, "Sci.Bitmap.Colors(pic, 0, 0, pic.Width, pic.Height)");
Sci.LogTime.Start(3);
Bitmap pic3 = Sci.Bitmap.ToBitmap(colors, pic.Width / 2, pic.Height / 2);
Sci.LogTime.End(3, "Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height)");
//Sci.LogTime.Start(2);
//int[,] colors = Sci.Bitmap.ColorsInt2(pic, 0, 0, pic.Width, pic.Height);
//Sci.LogTime.End(2, "Sci.Bitmap.Colors(pic, 0, 0, pic.Width, pic.Height)");
//Sci.LogTime.Start(3);
//Bitmap pic3 = Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height);
//Sci.LogTime.End(3, "Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height)");
Sci.LogTime.Start(4);
pic3.Save(picPath + "_2.png");
Sci.LogTime.End(4, "保存图像");
}
private void Test2()
{
Sci.LogTime.Start(1);
string picPath = "pic\\2.png";
Bitmap pic = Bitmap.FromFile(picPath) as Bitmap;
Sci.LogTime.End(1, "载入图像");
Sci.LogTime.Start(2);
Color[,] colors = Sci.Bitmap.Colors(pic);
Sci.LogTime.End(2, "Sci.Bitmap.Colors(pic)");
Sci.LogTime.Start(3);
Bitmap pic3 = Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height);
Sci.LogTime.End(3, "Sci.Bitmap.ToBitmap(colors, pic.Width, pic.Height)");
Sci.LogTime.Start(4);
pic3.Save(picPath + "_2.png");
Sci.LogTime.End(4, "保存图像");
}
private void Test1()
{
Sci.LogTime.Start(1);
string picPath = "pic\\2.png";
Bitmap pic = Bitmap.FromFile(picPath) as Bitmap;
Sci.LogTime.End(1, "载入图像");
Sci.LogTime.Start(2);
Sci.Bitmap pic2 = new Sci.Bitmap(pic);
Sci.LogTime.End(2, "获取图像所有像素信息");
//Sci.LogTime.Start(3);
//Bitmap pic3 = pic2.ToBitmap32();
//Sci.LogTime.End(3, "像素信息转化回图像");
//Sci.LogTime.Start(3);
//Bitmap pic3 = pic2.ToBitmap33();
//Sci.LogTime.End(3, "像素信息转化回图像");
Sci.LogTime.Start(3);
Bitmap pic3 = pic2.ToBitmap_SetPixel();
Sci.LogTime.End(3, "像素信息转化回图像");
Sci.LogTime.Start(4);
pic3.Save(picPath + "_2.png");
Sci.LogTime.End(4, "保存图像");
}
}
}