版权声明:本文为博主 ( 黃彥霖 ) 原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38884324/article/details/80612470
前言 :
Unity 3D 的 Texturd2D 只有 PNG, JPG, EXR 這三種編碼,如果你想要 BMP 編碼,無外乎只能依靠第三方庫,不然就是自己實作編碼器…
我這裡採取了後者,俗話說不要重複造輪子,但這句對我行不通…,因為我要的是 ” 跨平台 ” 阿,你的輪子可以跨平台 ? ( 笑 ) ,弄懂算法,你想要移植到哪個平台都行,Android / Linux / Windows / iOS / MacOSX / 嵌入式系統 / 單晶片 / FPGA …. ,最好有哪個第三方 Library 這些系統都能跨拉哈,因為我的工作比較特殊,會同時做 軟件 & 硬件 ,所以弄懂算法然後跨平台是必須的。但是如果沒有特殊原因,能用第三方庫就用的三方庫吧,畢竟也省時省力。
對了,建議你可以一起看我之前寫的文章 ” BMP解碼器 ”
https://blog.csdn.net/weixin_38884324/article/details/80609858
然後我們先來看執行結果吧 !
執行結果 :
好吧,我承認這張有放跟沒放一樣… 基本上執行後就會輸出一張 BMP 格式的圖片…
C # :
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class NewBehaviourScript2 : MonoBehaviour
{
public Texture2D inputImg; // 請從外面拉一張圖片進來 ( # 重要 : 請記得將圖片設置為"可讀寫")
void Start()
{
int fileSize = SaveToBMP("C:/FFMPEG/XXX.bmp", inputImg); // 保存到這路徑,按照你自己的需求改吧
print("保存成功,檔案大小:" + fileSize);
}
byte[] file;
// return : 保存 BMP 後,返回文件大小
int SaveToBMP(string savePath, Texture2D img)
{
// --------------------------------------------------------------------------
// 計算圖像寬度佔多少 Byte
// BMP 規定圖像寬度 Byte 數量必須是4的倍數,不足處末尾全補零
int yu = img.width * 3 % 4;
yu = yu != 0 ? 4 - yu : yu;
int bytePerLine = img.width * 3 + yu;
// --------------------------------------------------------------------------
// 初始化一些參數
int fileHeaderSize = 14; // 文件標頭大小
int infoHeaderSize = 40; // 訊息標頭大小
int headerSize = fileHeaderSize + infoHeaderSize;
int allColorSize = bytePerLine * img.height; // 圖像總 Byte 數量
int fileSize = headerSize + allColorSize; // 檔案最終大小
file = new byte[fileSize];
// --------------------------------------------------------------------------
// BMP File : File Header
file[0] = 0x42; // ASCII : B
file[1] = 0x4D; // ASCII : M
SetIntTo4Byte(0x0002, fileSize); // File Size
SetIntTo4Byte(0x000A, headerSize); // 頭檔大小
// --------------------------------------------------------------------------
// BMP File : Info Header
SetIntTo4Byte(0x000E, infoHeaderSize); // Info Headder Size
SetIntTo4Byte(0x0012, img.width); // Width
SetIntTo4Byte(0x0016, img.height); // Height
SetIntTo2Byte(0x001A, 1); // Planes
SetIntTo2Byte(0x001C, 24); // BitCount
SetIntTo4Byte(0x001E, 0); // Compression : 壓縮方式設為不壓縮
SetIntTo4Byte(0x0022, allColorSize); // SizeImage : 圖像大小 (不包含標頭)
SetIntTo4Byte(0x0026, 3780); // XPelsPerMeter
SetIntTo4Byte(0x002A, 3780); // YPelsPerMeter
SetIntTo4Byte(0x002E, 0); // ClrUsed
SetIntTo4Byte(0x0032, 0); // ClrImportant
// --------------------------------------------------------------------------
// BMP File : Colors Data
Color32[] colors = inputImg.GetPixels32();
for (int y = 0, k = 0; y < img.height; y++)
{
for (int x = 0, i = 0; x < img.width; x++, k++)
{
Color32 color = colors[k];
int index = headerSize + y * bytePerLine;
file[index + i++] = color.b;
file[index + i++] = color.g;
file[index + i++] = color.r;
}
}
File.WriteAllBytes(savePath, file);
return fileSize;
}
void SetIntTo2Byte(int offset, int value)
{
file[offset] = (byte)(value & 0x000000FF);
file[offset + 1] = (byte)((value & 0x0000FF00) >> 8);
}
void SetIntTo4Byte(int offset, int value)
{
file[offset] = (byte)(value & 0x000000FF);
file[offset + 1] = (byte)((value & 0x0000FF00) >> 8);
file[offset + 2] = (byte)((value & 0x00FF0000) >> 16);
file[offset + 3] = (byte)((value & 0xFF000000) >> 24);
}
}