RTMP/Assets/Bitmap.cs

171 lines
7.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.IO;
using System.Runtime.InteropServices;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
namespace ZC
{
public static class Bitmap
{
public const int FileHeaderSize = 14;
public const int ImageHeaderSize = 40;
// bmp文件头
[StructLayout(LayoutKind.Explicit)]
struct BitmapFileHeader
{
[FieldOffset(0)] public ushort bfType; // 19778必须是BM字符串对应的十六进制为0x4d42,十进制为19778
[FieldOffset(2)] public uint bfSize; // 文件大小
[FieldOffset(6)] public ushort bfReserved1; // 0
[FieldOffset(8)] public ushort bfReserved2; // 0
[FieldOffset(10)] public uint bfOffBits; // 从文件头到像素数据的偏移,也就是这两个结构体的大小之和
}
// bmp图像头
[StructLayout(LayoutKind.Sequential)]
struct BitmapImageHeader
{
public uint biSize; // 此结构体的大小
public int biWidth; // 图像的宽
public int biHeight; // 图像的高
public ushort biPlanes; // 1
public ushort biBitCount; // 24
public uint biCompression; // 0
public uint biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits
public int biXPelsPerMeter; // 0
public int biYPelsPerMeter; // 0
public uint biClrUsed; // 0
public uint biClrImportant; // 0
}
public static void EncodeToBitmap(NativeArray<byte> srcArray, int offset, int count, int width, int height,
Allocator allocator, out NativeArray<byte> destArray)
{
unsafe
{
int dataActualCount = count;
destArray = new NativeArray<byte>(FileHeaderSize + ImageHeaderSize + dataActualCount, allocator);
BitmapFileHeader fileHeader = new BitmapFileHeader()
{
bfType = 19778,
bfSize = (uint)(FileHeaderSize + ImageHeaderSize + dataActualCount),
bfOffBits = (uint)(FileHeaderSize + ImageHeaderSize)
};
BitmapImageHeader imageHeader = new BitmapImageHeader()
{
biSize = (uint)ImageHeaderSize,
biWidth = width,
biHeight = height,
biPlanes = 1,
biBitCount = 24,
biSizeImage = (uint)dataActualCount,
};
var dest = NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(destArray);
var src = NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(srcArray);
var fileHeaderPtr = &fileHeader;
var imageHeaderPtr = &imageHeader;
UnsafeUtility.MemCpy(dest, fileHeaderPtr, FileHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + FileHeaderSize), imageHeaderPtr, ImageHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + FileHeaderSize + ImageHeaderSize), src, dataActualCount);
}
}
public static void EncodeToBitmap(NativeArray<byte> srcArray, byte[] destArray, int offset, int count,
int width, int height)
{
if (!srcArray.IsCreated)
throw new NullReferenceException("srcArray is null");
if (destArray == null)
throw new NullReferenceException("destArray is null");
unsafe
{
int dataActualCount = count;
BitmapFileHeader fileHeader = new BitmapFileHeader()
{
bfType = 19778,
bfSize = (uint)(FileHeaderSize + ImageHeaderSize + dataActualCount),
bfOffBits = (uint)(FileHeaderSize + ImageHeaderSize)
};
BitmapImageHeader imageHeader = new BitmapImageHeader()
{
biSize = (uint)ImageHeaderSize,
biWidth = width,
biHeight = height,
biPlanes = 1,
biBitCount = 24,
biSizeImage = (uint)dataActualCount,
};
var dest = UnsafeUtility.PinGCArrayAndGetDataAddress(destArray, out var handle);
try
{
var src = NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(srcArray);
var fileHeaderPtr = &fileHeader;
var imageHeaderPtr = &imageHeader;
UnsafeUtility.MemCpy(dest, fileHeaderPtr, FileHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + FileHeaderSize), imageHeaderPtr, ImageHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + FileHeaderSize + ImageHeaderSize), src, dataActualCount);
}
finally
{
UnsafeUtility.ReleaseGCObject(handle);
}
}
}
public static void SaveToDisk(string filePath, NativeArray<byte> data, int offset, int count, int width,
int height)
{
unsafe
{
int dataActualCount = count;
var fileHeaderSize = 14;
var imageHeaderSize = 40;
byte[] bytes = new byte[fileHeaderSize + imageHeaderSize + dataActualCount];
var span = bytes.AsSpan();
var dest = UnsafeUtility.AddressOf(ref span.GetPinnableReference());
BitmapFileHeader fileHeader = new BitmapFileHeader()
{
bfType = 19778,
bfSize = (uint)(fileHeaderSize + imageHeaderSize + dataActualCount),
bfOffBits = (uint)(fileHeaderSize + imageHeaderSize)
};
BitmapImageHeader imageHeader = new BitmapImageHeader()
{
biSize = (uint)imageHeaderSize,
biWidth = width,
biHeight = height,
biPlanes = 1,
biBitCount = 24,
biSizeImage = (uint)dataActualCount,
};
var arrayPtr = (nint)NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(data);
var fileHeaderPtr = &fileHeader;
var imageHeaderPtr = &imageHeader;
UnsafeUtility.MemCpy(dest, fileHeaderPtr, fileHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + fileHeaderSize), imageHeaderPtr, imageHeaderSize);
UnsafeUtility.MemCpy((void*)((nint)dest + fileHeaderSize + imageHeaderSize), (void*)arrayPtr,
dataActualCount);
File.WriteAllBytes(filePath, bytes);
}
}
public static void LoadFromBmp(string filePath)
{
unsafe
{
var readAllBytes = File.ReadAllBytes(filePath);
var src = UnsafeUtility.AddressOf(ref readAllBytes.AsSpan().GetPinnableReference());
BitmapFileHeader fileHeader = new BitmapFileHeader();
BitmapImageHeader imageHeader = new BitmapImageHeader();
UnsafeUtility.MemCpy(&fileHeader, src, 14);
UnsafeUtility.MemCpy(&imageHeader, (void*)((nint)src + 14), 40);
}
}
}
}