DaFuWeng/assets/GlobalScript/ImagePack/ImagePack.ts

329 lines
12 KiB
TypeScript

import { _decorator, Asset, assetManager, BufferAsset, Component, error, Node, resources, TextAsset, Texture2D } from 'cc';
import { ReadStream } from '../Tool/ReadStream';
import * as pako from 'pako';
import { Img, ImgInfo, NpkInfo } from '../GlobalInterface/GlobalInterface';
const { ccclass, property } = _decorator;
type NewType = Img;
@ccclass('ImagePack')
export class ImagePack extends Component {
//全局单例类
private static instance: ImagePack;
private constructor() {
super();
}
public static getInstance(): ImagePack {
if (!ImagePack.instance) {
ImagePack.instance = new ImagePack();
}
return ImagePack.instance;
}
Key: Array<number> = [112, 117, 99, 104, 105, 107, 111, 110, 64, 110, 101, 111, 112, 108, 101, 32, 100, 117, 110, 103, 101, 111, 110, 32, 97, 110, 100, 32, 102, 105, 103, 104, 116, 101, 114, 32, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 0];
//NPK加载完成后的回调函数
LoadCallBack = undefined;
//NPK文件数量
private NpkCount = 0;
//已加载NPK文件数量
private LoadNpkCount = 0;
//Img的map Key:img路径 Value:Img结构体
private Map_Img: Map<string, NewType> = new Map<string, Img>();
//NPK的本地路径 对应的 NPK名字
private Npk_URL_Table: Map<string, string> = new Map<string, string>();
start() {
}
update(deltaTime: number) {
}
initSuccess(): void {
if (this.LoadCallBack) this.LoadCallBack();
}
BundleObject;
init(Func: Function): void {
//储存回调
this.LoadCallBack = Func;
assetManager.loadBundle('ImagePacks', (err, bundle) => {
this.BundleObject = bundle;
this.LoadNpk();
});
}
NpkHasImg: Map<string, Array<string>> = new Map<string, Array<string>>();
LoadNpk(): void {
this.BundleObject.loadDir("", BufferAsset, (err, contents: Array<BufferAsset>) => {
//记录NPK文件数量
this.NpkCount = contents.length;
console.log(this.NpkCount);
contents.forEach(content => {
let ImgArr: Array<string> = [];
const Buf = new Uint8Array(content.buffer());
const Ro = new ReadStream(Buf);
//文件头
const Header = Ro.GetString();
if (Header == "NeoplePack_Bill") {
//读取img数量
const ImageCount = Ro.GetInt();
let ImgList: NpkInfo[] = new Array<NpkInfo>(ImageCount);
for (let i = 0; i < ImageCount; i++) {
ImgList[i] = {
Offset: Ro.GetInt(),
Length: Ro.GetInt(),
Path: Ro.ReadInfo(this.Key),
}
}
for (let i = 0; i < ImageCount; i++) {
ImgArr.push(ImgList[i].Path);
let Buf: Img = {
ImgOffset: ImgList[i].Offset,
ImgSize: ImgList[i].Length,
Img_Index: i,
BelongsFile: content.nativeUrl,
ImgName: ImgList[i].Path,
Png_List: null,
Png_Count: 0
}
this.Map_Img.set(ImgList[i].Path, Buf);
}
this.NpkHasImg.set(content.name, ImgArr);
}
//完成一个加载
this.LoadNpkCount = this.LoadNpkCount + 1;
//把本地路径和NPK名称挂钩一下
this.Npk_URL_Table.set(content.nativeUrl, content.name);
//载入完成以后需要释放
assetManager.releaseAsset(content);
//加载完成
if (this.LoadNpkCount == this.NpkCount) {
this.initSuccess();
}
});
});
}
LoadImgToMem(ImgObj: Img, func: Function) {
//获取路径 如果不存在直接返回
const Path = this.Npk_URL_Table.get(ImgObj.BelongsFile);
if (!Path) return;
this.BundleObject.load(Path, BufferAsset, (err, content) => {
const Buf = new Uint8Array(content.buffer());
const Ro = new ReadStream(Buf);
Ro.Seekg(ImgObj.ImgOffset);
//Img头
const Header = Ro.GetString();
//开始读图片
if (Header == "Neople Img File") {
//索引表大小
const TableLength = Ro.GetLongInt();
//img 版本 4字节
const ver = Ro.GetInt();
//img 帧数
const IndexCount = Ro.GetInt();
ImgObj.Png_Count = IndexCount;
let PngArr: ImgInfo[] = [];
for (let index = 0; index < IndexCount; index++) {
let ImgBuf: ImgInfo = {};
//图片格式
ImgBuf.Type = Ro.GetInt();
if (ImgBuf.Type == 17) {
//引用贴图
const IndexBuf = Ro.GetInt();
ImgBuf.Offset = PngArr[index - 1].Offset;
ImgBuf.Type = 17;
ImgBuf.QuoteIndex = IndexBuf;
ImgBuf.Size = PngArr[index - 1].Size;
PngArr.push(ImgBuf);
continue;
}
//压缩类型
ImgBuf.CmpType = Ro.GetInt();
//宽度
ImgBuf.Width = Ro.GetInt();
//高度
ImgBuf.Height = Ro.GetInt();
//大小
ImgBuf.Size = Ro.GetInt();
//Xpos
ImgBuf.Xpos = Ro.GetInt();
//Ypos
ImgBuf.Ypos = Ro.GetInt();
//帧域X
ImgBuf.FrameXpos = Ro.GetInt();
//帧域Y
ImgBuf.FrameYpos = Ro.GetInt();
if (index == 0) {
ImgBuf.Offset = 0 + ImgObj.ImgOffset + Number(TableLength) + 32;
} else {
ImgBuf.Offset = PngArr[index - 1].Offset + PngArr[index - 1].Size;
}
PngArr.push(ImgBuf);
}
for (let index = 0; index < IndexCount; index++) {
let PngObj = PngArr[index];
//引用贴图
if (PngObj.Type == 17) {
const QuoteIndexBuf = PngObj.QuoteIndex;
PngArr[index] = PngArr[QuoteIndexBuf];
}
}
for (let index = 0; index < IndexCount; index++) {
let PngObj = PngArr[index];
Ro.Seekg(PngObj.Offset);
//PNG压缩原始数据
let DataBuf = Ro.GetBufferByLength(PngObj.Size);
//图片数据应有大小
let PngBufSize = PngObj.Width * PngObj.Height * 4;
// 使用pako 解压 zlib的inflate函数解压缩数据
let Bsf;
try {
Bsf = pako.inflate(DataBuf);
}
catch (error) {
Bsf = DataBuf;
}
if (PngObj.Type != 16) {
let PngByteSize = Bsf.length * 2;
PngObj.PNGdata = new Uint8Array(PngByteSize);
for (let e = 0; e < PngByteSize; e += 4) {
let BarBuf = new Uint8Array(2);
let Pos = (e / 4) * 2;
BarBuf[0] = Bsf[Pos];
BarBuf[1] = Bsf[Pos + 1];
this.ReadColor(BarBuf, PngObj, e);
}
}
else {
PngObj.PNGdata = new Uint8Array(Bsf.length);
for (let index = 0; index < Bsf.length; index += 4) {
PngObj.PNGdata[index] = Bsf[index + 2];
PngObj.PNGdata[index + 1] = Bsf[index + 1];
PngObj.PNGdata[index + 2] = Bsf[index];
PngObj.PNGdata[index + 3] = Bsf[index + 3];
}
}
}
ImgObj.Png_List = PngArr;
func(ImgObj);
}
//载入完成以后需要释放
assetManager.releaseAsset(content);
});
}
ReadColor(Bar: Uint8Array, PngObj: ImgInfo, Offset: number) {
let a: number = 0;
let r: number = 0;
let g: number = 0;
let b: number = 0;
switch (PngObj.Type) {
case 0x0e:
a = Bar[1] >> 7;
r = (Bar[1] >> 2) & 0x1f;
g = (Bar[0] >> 5) | ((Bar[1] & 3) << 3);
b = Bar[0] & 0x1f;
a = a * 0xff;
r = (r << 3) | (r >> 2);
g = (g << 3) | (g >> 2);
b = (b << 3) | (b >> 2);
break;
case 0x0f:
a = Bar[1] & 0xf0;
r = (Bar[1] & 0xf) << 4;
g = Bar[0] & 0xf0;
b = (Bar[0] & 0xf) << 4;
break;
default:
console.log(PngObj.Type);
break;
}
PngObj.PNGdata[Offset + 0] = r;
PngObj.PNGdata[Offset + 1] = g;
PngObj.PNGdata[Offset + 2] = b;
PngObj.PNGdata[Offset + 3] = a;
}
//读取Img数据
ReadNpkTable(imgname: string, func: Function): boolean {
let ImgObj: Img = this.Map_Img.get(imgname);
if (ImgObj) {
//没有图片数据 需要加载
if (ImgObj.Png_List == null) {
//加载Img进内存
this.LoadImgToMem(ImgObj, func);
return true;
}
else {
func(ImgObj);
return true;
}
}
return false;
}
LoadNpkImgCount = 0;
//读取Npk数据
ReadNpkFile(npkname: string, func: Function): number {
let ImgArr = this.NpkHasImg.get(npkname);
ImgArr.forEach(imgname => {
let ImgObj: Img = this.Map_Img.get(imgname);
if (ImgObj) {
//没有图片数据 需要加载
if (ImgObj.Png_List == null) {
//加载Img进内存
this.LoadImgToMem(ImgObj, func);
}
else {
func(ImgObj);
}
}
});
return ImgArr.length;
}
ReleaseNpkTable(p: Img): void {
// implementation
}
}