加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
BitmapHelper.cs 6.92 KB
一键复制 编辑 原始数据 按行查看 历史
泡泡大龙王 提交于 2022-04-28 18:48 . 第一次
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BitmapPtr
{
class BitmapHelper
{
public static byte[] Bitmap2Byte(Bitmap bitmap, out int width, out int height,
out int img_stride, out int img_depth, out PixelFormat img_PixelFormat)
{
byte[] destination;
width = bitmap.Width;
height = bitmap.Height;
img_stride = 0;
img_PixelFormat = bitmap.PixelFormat;
img_depth = Bitmap.GetPixelFormatSize(img_PixelFormat); //8,24,32
try
{
Rectangle rect = new Rectangle(0, 0, width, height);
BitmapData bitmapdata = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
img_stride = bitmapdata.Stride; //stride指图像一行的字节数(Width * depth + padding)
int length = bitmapdata.Stride * bitmap.Height;
destination = new byte[length];
Marshal.Copy(bitmapdata.Scan0, destination, 0, length);
bitmap.UnlockBits(bitmapdata);
}
catch
{
destination = null;
}
return destination;
}
public static Bitmap ByteToBitmap(byte[] img_bytes, int img_width, int img_height, PixelFormat PixelFormat)
{
try
{
Rectangle rect = new Rectangle(0, 0, img_width, img_height);
Bitmap bitmap = new Bitmap(img_width, img_height, PixelFormat);
BitmapData bitmapdata = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat);
IntPtr destination = bitmapdata.Scan0;
Marshal.Copy(img_bytes, 0, destination, bitmapdata.Stride * img_height);
bitmap.UnlockBits(bitmapdata);
return bitmap;
}
catch (Exception ex)
{
MessageBox.Show($"ByteToBitmap error:{ex.Message}");
return null;
}
}
public static byte[] Color2GrayByte(byte[] bmpbype, int width, int height, int img_stride, int img_depth)
{
byte[] Graybytes = new byte[img_stride * height]; //Graybytes长度加一个字节可以避免pi指针在24位深度下的越界风险。
int padding = img_stride - width * img_depth / 8; //得到Padding,行末需要跳过去
//灰度计算公式
//Gray = (30 * Red + 59 *Green + 11 * Blue) / 100;
//其中77,150,28分别除以256,即为上文的三个系数。
//gray = (30 * p[0] + 59 * p[1] + 11 * p[2]) / 100; //RGB
unsafe
{
byte gray = 0;
uint* pi;
//https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/fixed-statement
//在 fixed 语句中初始化的指针为只读变量。 如果想要修改指针值,必须声明第二个指针变量,并修改它。不能修改在 fixed 语句中声明的变量。
fixed (byte* p0 = bmpbype)
{
byte* p = p0;
fixed (byte* t0 = Graybytes)
{
byte* t = t0;
switch (img_depth)
{
case 32: //32位深度,BGRA排列
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//gray = (byte)((77 * p[0] + 150 * p[1] + 28 * p[2]) >> 8); //最大值65025/255=255
gray = (byte)((38 * p[0] + 75 * p[1] + 15 * p[2]) >> 7); //最大值65025/255=255
//t[0] = gray;t[1] = gray;t[2] = gray;t[3] = 255; //Alpha通道填充成白色
//使用int指针,一次写入四个字节。
pi = (uint*)t;
pi[0] = (uint)((gray) | (gray << 8) | (gray << 16) | 0xFF000000); //argb
//保留 t[0] = p[0];t[1] = p[1];t[2] = p[2];t[3] = 255; //Alpha通道填充成白色
//保留 pi[0] = (uint)((p[0]) | (p[1] << 8) | (p[2] << 16) | 0xFF000000); //argb
p += 4; t += 4;
}
if (padding > 0)
{
p += padding;
t += padding;
}
}
break;
case 24: //24位深度,BGR排列
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
gray = (byte)((38 * p[2] + 75 * p[1] + 15 * p[1]) >> 7);
t[0] = gray; t[1] = gray; t[2] = gray;
//Graybytes没有加一个字节,pi越界有风险。
//pi = (uint*)t;
//pi[0] = (uint)((gray) | (gray << 8) | (gray << 16));
p += 3;
t += 3;
}
if (padding > 0)
{
p += padding;
t += padding;
}
}
break;
case 8:
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
t[0] = p[0];
p++; t++;
}
if (padding > 0)
{
p += padding;
t += padding;
}
}
break;
default:
break;
}
}
}
}
return Graybytes;
}
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化