pvz一代特殊圖像格式分析——texTV系列

聲明:本教程內(nèi)容包含:ptx2X系列編碼解碼、ptxPS3系列圖像查看、texTV系列編碼解碼、texiOS系列編碼解碼、txz圖像編碼解碼,若你根據(jù)本教程寫出了對應工具,請務必注明是參考了本教程。
一代在TV版和iOS版均出現(xiàn)過tex格式,不過兩種tex文件結構并不相同,這里介紹TV版的tex格式,后續(xù)更新iOS版格式介紹。
使用十六進制編輯器打開TV版中的crazydave-atlas1.tex,可以看到0x0開始的8個字節(jié)顯然是文件魔數(shù)(在文件起始位置用于標識文件類型的內(nèi)容),0x8開始4個字節(jié)應該都是00,猜測0xC開始4字節(jié)和0x10開始4字節(jié)的內(nèi)容是圖像寬度或高度,0x14開始的12個字節(jié)暫時不知道是什么意思,0x20開始的4字節(jié)內(nèi)容正好是文件大小-0x30,也就是從0x30開始到文件末的大小,后面跟著12字節(jié)的00。

0x30出現(xiàn)了78 9C,正好是zlib壓縮的文件魔數(shù),于是刪除掉前面0x30的數(shù)據(jù),對整個后續(xù)內(nèi)容進行zlib解壓,得到了一個大小為1708032字節(jié)的文件,1708032=512*1668*2,也就是說2字節(jié)=1像素rgba顏色,而根據(jù)圖像名字來看應該是戴夫圖像,這張圖像在dz解包中出現(xiàn)過半透明的像素,使用rgb565或rgba5551來存儲不合適,所以猜測圖像為rgba4444壓縮。用此格式將其轉為png后,得到圖像如圖,發(fā)現(xiàn)圖像輪廓沒問題,但是顏色有問題。

于是使用十六進制編輯器打開解壓后的文件,發(fā)現(xiàn)開頭都是FF 0F,而此圖像左上角一開始就是透明的,所以alpha通道肯定對應那個0,猜測其為argb4444存儲,對應方式解碼后,得到正確圖像。

texTV共有兩種格式,02為argb8888,03為argb4444,格式02的只有一張圖片。
C#代碼實現(xiàn):
? ? ? ? //編碼
? ? ? ??public static void Save(Bitmap Pic, string outFile, int format)
? ? ? ? {
? ? ? ? ? ? if (format > 3 || format < 2)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? throw new Exception("錯誤的格式類型:texTV" + format);
? ? ? ? ? ? }
? ? ? ? ? ? HexWriter HW = HexWriter.Create("temp");
? ? ? ? ? ? HW.SetPosition(0x0);
? ? ? ? ? ? switch (format)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? ? ? Save_A8R8G8B8(HW, Pic);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? ? ? Save_A4R4G4B4(HW, Pic);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? HW.Close();
? ? ? ? ? ? Zlib.Compress("temp", "temp2");
? ? ? ? ? ? HexWriter HW2 = HexWriter.Create(outFile);
? ? ? ? ? ? HW2.SetPosition(0x0);
? ? ? ? ? ? HW2.WriteUInt16(0x4553);
? ? ? ? ? ? HW2.WriteUInt16(0x5958);
? ? ? ? ? ? HW2.WriteUInt16(0x4554);
? ? ? ? ? ? HW2.WriteUInt16(0x58);
? ? ? ? ? ? HW2.WriteUInt32(0x0);
? ? ? ? ? ? HW2.WriteUInt32((ushort)Pic.Width);
? ? ? ? ? ? HW2.WriteUInt32((ushort)Pic.Height);
? ? ? ? ? ? HW2.WriteUInt32((ushort)format);
? ? ? ? ? ? HW2.WriteUInt32(0x1);
? ? ? ? ? ? HW2.WriteUInt32(0x1);
? ? ? ? ? ? HexReader HR = HexReader.Create("temp2");
? ? ? ? ? ? HW2.WriteInt64(HR.GetSize());
? ? ? ? ? ? HW2.WriteInt64(0x0);
? ? ? ? ? ? HR.SetPosition(0x0);
? ? ? ? ? ? HW2.WriteBytes(HR.ReadAll());
? ? ? ? ? ? HR.Close();
? ? ? ? ? ? HW2.Close();
? ? ? ? ? ? File.Delete("temp");
? ? ? ? ? ? File.Delete("temp2");
? ? ? ? }
? ? ? ? static void Save_A4R4G4B4(HexWriter HW, Bitmap img)
? ? ? ? {
? ? ? ? ? ? int height = img.Height;
? ? ? ? ? ? int width = img.Width;
? ? ? ? ? ? Color temp2;
? ? ? ? ? ? for (int i = 0; i < height; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int j = 0; j < width; j++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? temp2 = img.GetPixel(j, i);
? ? ? ? ? ? ? ? ? ? HW.WriteUInt16((ushort)(((temp2.A & 0xF0) << 8) + ((temp2.B & 0xF0) >> 4) + (temp2.G & 0xF0) + ((temp2.R & 0xF0) << 4)));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? static void Save_A8R8G8B8(HexWriter HW, Bitmap img)
? ? ? ? {
? ? ? ? ? ? int height = img.Height;
? ? ? ? ? ? int width = img.Width;
? ? ? ? ? ? Color temp2;
? ? ? ? ? ? for (int i = 0; i < height; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int j = 0; j < width; j++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? temp2 = img.GetPixel(j, i);
? ? ? ? ? ? ? ? ? ? HW.WriteByte(temp2.B);
? ? ? ? ? ? ? ? ? ? HW.WriteByte(temp2.G);
? ? ? ? ? ? ? ? ? ? HW.WriteByte(temp2.R);
? ? ? ? ? ? ? ? ? ? HW.WriteByte(temp2.A);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //編碼
? ? ? ? public static Bitmap Get(string fileName)
? ? ? ? {
? ? ? ? ? ? ? ? HexReader HR = HexReader.Create(fileName);
? ? ? ? ? ? ? ? //這是TV版tex
? ? ? ? ? ? ? ? HR.SetPosition(0xC);
? ? ? ? ? ? ? ? int width = HR.ReadInt32();
? ? ? ? ? ? ? ? int height = HR.ReadInt32();
? ? ? ? ? ? ? ? int format = HR.ReadInt32();
? ? ? ? ? ? ? ? HR.AddPosition(0x18);
? ? ? ? ? ? ? ? FileStream a = new FileStream("temp", FileMode.Create);
? ? ? ? ? ? ? ? HR.CopyTo(a);
? ? ? ? ? ? ? ? a.Close();
? ? ? ? ? ? ? ? Zlib.Decompress("temp", "temp2");
? ? ? ? ? ? ? ? Bitmap ans;
? ? ? ? ? ? ? ? HexReader c = HexReader.Create("temp2");
? ? ? ? ? ? ? ? switch (format)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? case 2:
? ? ? ? ? ? ? ? ? ? ? ? ans = Get_A8R8G8B8(c, height, width);
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? case 3:
? ? ? ? ? ? ? ? ? ? ? ? ans = Get_A4R4G4B4(c, height, width);
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? ans = null;
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? c.Close();
? ? ? ? ? ? ? ? File.Delete("temp");
? ? ? ? ? ? ? ? File.Delete("temp2");
? ? ? ? ? ? ? ? return ans;
? ? ? ? }
? ? ? ? static Bitmap Get_A8R8G8B8(HexReader HR, int height, int width)
? ? ? ? {
? ? ? ? ? ? Bitmap img = new Bitmap(width, height);
? ? ? ? ? ? byte a;
? ? ? ? ? ? byte r;
? ? ? ? ? ? byte g;
? ? ? ? ? ? byte b;
? ? ? ? ? ? LockBitmap img2 = new LockBitmap(img);
? ? ? ? ? ? img2.LockBits();
? ? ? ? ? ? for (int i = 0; i < height; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int j = 0; j < width; j++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? b = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? g = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? r = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? a = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? img2.SetPixel(j, i, Color.FromArgb(a, r, g, b));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? img2.UnlockBits();
? ? ? ? ? ? return img;
? ? ? ? }
? ? ? ? static Bitmap Get_A4R4G4B4(HexReader HR, int height, int width)
? ? ? ? {
? ? ? ? ? ? Bitmap img = new Bitmap(width, height);
? ? ? ? ? ? int a;
? ? ? ? ? ? int r;
? ? ? ? ? ? int g;
? ? ? ? ? ? int b;
? ? ? ? ? ? byte temp;
? ? ? ? ? ? LockBitmap img2 = new LockBitmap(img);
? ? ? ? ? ? img2.LockBits();
? ? ? ? ? ? for (int i = 0; i < height; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int j = 0; j < width; j++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? temp = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? g = ((temp & 0xF0) >> 4) * 17;
? ? ? ? ? ? ? ? ? ? b = (temp & 0xF) * 17;
? ? ? ? ? ? ? ? ? ? temp = HR.ReadByte();
? ? ? ? ? ? ? ? ? ? a = ((temp & 0xF0) >> 4) * 17;
? ? ? ? ? ? ? ? ? ? r = (temp & 0xF) * 17;
? ? ? ? ? ? ? ? ? ? img2.SetPixel(j, i, Color.FromArgb(a, r, g, b));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? img2.UnlockBits();
? ? ? ? ? ? return img;
? ? ? ? }