//SFFV2 从索引获取图像数据 public byte[] getSprDataV2(int index, out byte[] pp, FI_FORMAT type, bool loadPal = true) { byte[] sprData; byte[] palData = null; int sprSize; IntPtr dib; sprMsgV2 spr = getSprMsgV2(index); if (spr.dataLen == 0) { //链接型图像 return(getSprDataV2(spr.linkIndex, out pp, type)); } seek((spr.flags == 1 ? msgV2.tdataOffset : msgV2.ldataOffset) + spr.dataOffset); //压缩算法(fmt)常量声明这里省略了,直接使用值 //0 无压缩 //2 Rle8压缩 //3 Rle5压缩 几乎不会用到 直接省略 //4 Lz5压缩 //10 PNG8 //11 PNG24 //12 PNG32 if (spr.fmt == 0) { sprData = br.ReadBytes(spr.dataLen); } else { sprSize = br.ReadInt32(); //解压后的校验长度,这里省略了校验 sprData = br.ReadBytes(spr.dataLen - 4); } switch (spr.fmt) { case 0: if (loadPal) { palData = getPalData(spr.palIndex); } pp = palData; break; case 2: sprData = sffV2Decompress.unRle8(sprData); if (loadPal) { palData = getPalData(spr.palIndex); } pp = palData; break; case 4: sprData = sffV2Decompress.unLz5(sprData); if (loadPal) { palData = getPalData(spr.palIndex); } pp = palData; break; case 10: //压缩算法为PNG算法时读取的数据默认都是一个完整的PNG文件 可以直接载入 palData = getPalData(spr.palIndex); dib = FI.LoadFromMemory(sprData, FI_FORMAT.FIF_PNG); //PNG8调色板校正 RGBQUAD *pale = FI.GetPalette(dib); for (int n = 0; n < 256; n++) { pale [n].Red = palData [n * 4]; pale [n].Green = palData [n * 4 + 1]; pale [n].Blue = palData [n * 4 + 2]; } FI.SaveToMemory(dib, ref sprData, type); pp = palData; return(sprData); case 11: case 12: pp = null; return(sprData); default: sprData = new byte[0]; pp = new byte[0]; return(sprData); } if (type != FI_FORMAT.FIF_UNKNOWN) { //对于无压缩、Rle8和Lz5压缩的图像读取的数据是原始的像素数据 不能直接载入 dib = FI.ConvertFromRawBits(sprData, spr.width, spr.height, spr.width, 8, 0, 0, 0, true); RGBQUAD *pal = FI.GetPalette(dib); int colorNum = palData.Length / 4; for (int n = 0; n < colorNum; n++) { pal [n].Red = palData [n * 4]; pal [n].Green = palData [n * 4 + 1]; pal [n].Blue = palData [n * 4 + 2]; } FI.SaveToMemory(dib, ref sprData, type); FI.Free(dib); return(sprData); } else { return(sprData); } }
//SFFV1 从索引获取指定图像数据 public byte[] getSprDataV1(int index, out byte[] pp, FI_FORMAT type) { int offset = msgV1.sprOffset; sprMsgV1 spr = new sprMsgV1(); byte[] facePalData = new byte[0]; byte[] palData = new byte[0]; byte[] sprData = new byte[0]; for (int i = 0; i < msgV1.sprNum; i++) { seek(offset); offset = br.ReadInt32(); spr.pcxDataLen = br.ReadInt32(); spr.x = br.ReadInt16(); spr.y = br.ReadInt16(); spr.group = br.ReadUInt16(); spr.index = br.ReadUInt16(); spr.linkIndex = br.ReadUInt16(); spr.palType = br.ReadByte(); if (i == 0) { //第一张图强制为独立色表 spr.palType = 0; } seek(13, SeekOrigin.Current); if ((spr.group == 0 && spr.index == 0 || spr.group == 9000 && spr.index == 0) && facePalData.Length != 0) { //0,0和9000,0强制为独立色表,且使用第一张色表 palData = facePalData; } if (i == index) { if (spr.pcxDataLen == 0) { //链接型图像 return(getSprDataV1(spr.linkIndex, out pp, type)); } sprData = br.ReadBytes(spr.pcxDataLen); if (type != FI_FORMAT.FIF_UNKNOWN) { IntPtr dib = FI.LoadFromMemory(sprData, FI_FORMAT.FIF_PCX); if (spr.palType == 1) { RGBQUAD *pal = FI.GetPalette(dib); for (int n = 0; n < 256; n++) { pal[n].Red = palData[n * 3]; pal[n].Green = palData[n * 3 + 1]; pal[n].Blue = palData[n * 3 + 2]; } } FI.SaveToMemory(dib, ref sprData, type); //释放图像流 FI.Free(dib); } pp = palData; return(sprData); } else { if (spr.palType == 0) { //读取PCX尾部色表数据 seek(spr.pcxDataLen - 768, SeekOrigin.Current); palData = br.ReadBytes(768); if (i == 0) { //保留第一张图的色表 facePalData = palData; } } } } pp = null; return(null); }