结果消耗的时间太长,我郁闷
听说把图片打包了读取时间会大大减少
什么是图片打包? 如何打包?
有谁给点代码或者资料看看嘛
15 个解决方案
#1
就是从硬盘快速读入大量图片
有什么方法 或者资料看啊
有什么方法 或者资料看啊
#2
没用过,不知道
但是好像是用什么工具把图片等资源做成专门的格式,然后在需要的时候一次性读取出来
但是好像是用什么工具把图片等资源做成专门的格式,然后在需要的时候一次性读取出来
#3
打包就是把一堆文件搞到一个文件里。
要说把图片打包了读取时间会大大减少。打了包后在磁盘存取效率上会有一些优势,但说到大大减少,那是没可能的。
暴雪的资源都是打包的,每个游戏里肯定都有一些巨大的文件,也就是打包的资源,包括图片声音等等等等,网上有暴雪的资源查看工具的。
要说把图片打包了读取时间会大大减少。打了包后在磁盘存取效率上会有一些优势,但说到大大减少,那是没可能的。
暴雪的资源都是打包的,每个游戏里肯定都有一些巨大的文件,也就是打包的资源,包括图片声音等等等等,网上有暴雪的资源查看工具的。
#4
我现在就是要读取一些地图文件 很巨大。
如何让读取时间变短点?
如果是打包
要怎么打包?
50多张png的图片
我打包后如何读取?
我只用过一些封装好的方法读取图片文件 (参数就是一个图片的文件名。)
没有自己写 过方法。
如何让读取时间变短点?
如果是打包
要怎么打包?
50多张png的图片
我打包后如何读取?
我只用过一些封装好的方法读取图片文件 (参数就是一个图片的文件名。)
没有自己写 过方法。
#5
如果是图像本身很大,那么就要考虑是不是把大图切成小图,每次只读取需要显示的那部分图像,而不是每次都读整个图。
如何打包的问题,记得网上有暴雪的打包格式的分析,搜搜就知道了。
最简单的打包方法就是头上一个索引,然后把其他文件都合并到一个文件里,在索引里记录各个文件的位置长度就是了。
如何打包的问题,记得网上有暴雪的打包格式的分析,搜搜就知道了。
最简单的打包方法就是头上一个索引,然后把其他文件都合并到一个文件里,在索引里记录各个文件的位置长度就是了。
#6
能贴点代码看看吗,
比如是2张png的图 打包
用C++
比如是2张png的图 打包
用C++
#7
或者在DX9里面实现~
#8
最简单的就是把所有图片都放合并为一个文件,然后生成一个配置文件,这个配置文件保存每一张图片在那个合并后的文件中的位置和大小,读的时候由于只打开一个文件,相比打开多个图片文件会快点
#9
“图片打包”说的是把多张图片平铺合成为一张图片吧?对于零碎的小图片来说很有用。
#10
我这几天也在跟图片打包打交道。
我说一下自己的愚见。
图片打包就是通过像fopen()、fwrite()、fread()等函数,把N个图片数据读取进来,然后再写到一个文件中的过程。
这里有一个问题就是图片的数据是什么样子,我也不知道是什么样子,不过肯定是一些二进制或十六进制的数吧。用fread把图片数据读进文件流后,再定义一个文件输出流,用于写文件,你可以开始向这个输出流写一点标记,比如写一个struct文件头数据,里面记录要写的图片数据的格式,比如大小,宽读,索引,之类的,写完再写一个struct结构体数据,当做第1个图片的索引信息,然后写入第1个图片数据,然后再写下一个图片的索引,再写下一个图片的数据……
我说的比较乱,比较散,你听个大概就可以了,我这里在列一下我的封包文件的格式:
文件开始:
struct 文件头
struct 第1个图片的索引
struct 第2个图片的索引
struct 第3个图片的索引
……
Data: 第1个图片数据
Data: 第2个图片数据
Data: 第3个图片数据
……
文件结束:
你可能会问,把这么一堆图片数据写进去,那怎么解包,怎么读出来呢?
答案就在上面这个写法上,为什么要像这样写?我先说一下这个使用流程,说完,你可能就会明白。
1:写文件头,并确定一共要写多少个图片进来,这样可以确定索引结构体的数量
2:确定了图片索引结构的数量后,直接跳到sizeof(图片索引结构)*图片数量 + sizeof(文件头) 这个地方并记下第1个结构索引所对应的图片数据(第1个图片)的位置。 这句话明白么?如果你明白的话,你就懂了。
3:然后再回到第1个索引处,记下第1个图片索引数据(就是在上一步记录的那个位置写),写完第1个图片数据后,紧接着再记录当前的图片索引,以便于下一次再用这个地址写第2个图片。
4:和3一样,就是要处理下一索引,及其图片数据
如果这个流程还是看不懂,仔细看看上面的文件结构,我开始就是琢磨这个结构,才写出来的。
如果想要代码,我这有现成的,代码很简短,很容易看懂,要是想要的话,加我QQ:1491839
我说一下自己的愚见。
图片打包就是通过像fopen()、fwrite()、fread()等函数,把N个图片数据读取进来,然后再写到一个文件中的过程。
这里有一个问题就是图片的数据是什么样子,我也不知道是什么样子,不过肯定是一些二进制或十六进制的数吧。用fread把图片数据读进文件流后,再定义一个文件输出流,用于写文件,你可以开始向这个输出流写一点标记,比如写一个struct文件头数据,里面记录要写的图片数据的格式,比如大小,宽读,索引,之类的,写完再写一个struct结构体数据,当做第1个图片的索引信息,然后写入第1个图片数据,然后再写下一个图片的索引,再写下一个图片的数据……
我说的比较乱,比较散,你听个大概就可以了,我这里在列一下我的封包文件的格式:
文件开始:
struct 文件头
struct 第1个图片的索引
struct 第2个图片的索引
struct 第3个图片的索引
……
Data: 第1个图片数据
Data: 第2个图片数据
Data: 第3个图片数据
……
文件结束:
你可能会问,把这么一堆图片数据写进去,那怎么解包,怎么读出来呢?
答案就在上面这个写法上,为什么要像这样写?我先说一下这个使用流程,说完,你可能就会明白。
1:写文件头,并确定一共要写多少个图片进来,这样可以确定索引结构体的数量
2:确定了图片索引结构的数量后,直接跳到sizeof(图片索引结构)*图片数量 + sizeof(文件头) 这个地方并记下第1个结构索引所对应的图片数据(第1个图片)的位置。 这句话明白么?如果你明白的话,你就懂了。
3:然后再回到第1个索引处,记下第1个图片索引数据(就是在上一步记录的那个位置写),写完第1个图片数据后,紧接着再记录当前的图片索引,以便于下一次再用这个地址写第2个图片。
4:和3一样,就是要处理下一索引,及其图片数据
如果这个流程还是看不懂,仔细看看上面的文件结构,我开始就是琢磨这个结构,才写出来的。
如果想要代码,我这有现成的,代码很简短,很容易看懂,要是想要的话,加我QQ:1491839
#11
// Pack.h
#ifndef _FILEPACK_
#define _FILEPACK_
#include <windows.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
enum FIleFormat
{
BMP,
JPG,
PNG,
TGA,
};
// 文件头 (20 bytes total)
struct XMHHeader
{
XMHHeader()
{
m_Signature = 0;
m_Width = 0;
m_Height = 0;
m_FrameCount = 1;
m_Version = 1000;
m_Reserved = 0;
}
DWORD m_Signature; // 文件标识:"XMHH"
DWORD m_Width; // 图片使用
DWORD m_Height; // 图片使用
WORD m_FrameCount; // 帧数
WORD m_Version; // 版本信息
DWORD m_Reserved; // 保留字
};
// 图像的索引信息 (20 bytes total)
struct ImgIndex
{
ImgIndex()
{
m_FileIndex = 0;
m_FileSize = 0;
m_FIleFormat = JPG;
}
DWORD m_FileIndex; // 排在所有XMH_MultiTexIndex信息字节的后面,该索引是每帧数据尾部的字节大小
DWORD m_FileSize;
DWORD m_FIleFormat; // 图片格式
DWORD m_Width;
DWORD m_Height;
};
class CFilePack
{
public:
CFilePack();
~CFilePack();
// -----------------------------------------------------------------
bool LoadFileDate(const char* szDirectory);
int GetFileCount() const { return m_VecFileName.size(); }
vector<string> GetVecFileName() const { return m_VecFileName; } // 获得文件名容器
string GetCurrtFolderPath() const { return m_CurrtFolderPath; } // 获得当前文件路径
void SetPackFolderPath(string szDirectory) { m_PackFolderPath = szDirectory; }
void SetUnPackFolderPath(string szDirectory) { m_UnPackFolderPath = szDirectory; }
// -----------------------------------------------------------------
bool Pack(const char* szPackFile); // 封包
bool UnPack(const char* szPackFile); // 解包
private:
vector<string> m_VecFileName; // 保存文件名的容器
string m_CurrtFolderPath; // 当前文件所在的文件夹路径
string m_PackFolderPath; // 封包文件的目录
string m_UnPackFolderPath; // 解包文件的目录
};
#endif
// Pack.cpp
#include "FilePack.h"
CFilePack::CFilePack()
{
}
CFilePack::~CFilePack()
{
}
bool CFilePack::LoadFileDate(const char* szDirectory)
{
if (!szDirectory) return false;
m_CurrtFolderPath = szDirectory; // 记录当前文件所在的文件夹路径
m_PackFolderPath = szDirectory;
m_UnPackFolderPath = szDirectory;
string strCurrtFile = szDirectory;
strCurrtFile += "\\*.*"; // 定位到该目录的第一个文件(“.”即根目录)
WIN32_FIND_DATA FileData;
HANDLE hFind = FindFirstFile(strCurrtFile.c_str(), &FileData); // 返回根目录的句柄
if (hFind == INVALID_HANDLE_VALUE) return false;
m_VecFileName.clear();
string strTemCheck; // 用于存放FileData.cFileName,判断其后缀名
// 绕过"."和".."
while (1)
{
if (strcmp(FileData.cFileName, ".")!=0 && strcmp(FileData.cFileName,"..")!=0 && (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
{
strTemCheck = FileData.cFileName;
string::size_type pos = strTemCheck.rfind(".");
strTemCheck.erase(strTemCheck.begin(), strTemCheck.begin()+pos); // 只保留后缀
// 只保存合法的格式文件
if (strTemCheck == string(".bmp") || strTemCheck == string(".BMP") ||
strTemCheck == string(".jpg") || strTemCheck == string(".JPG") ||
strTemCheck == string(".gif") || strTemCheck == string(".GIF") ||
strTemCheck == string(".png") || strTemCheck == string(".PNG") ||
strTemCheck == string(".tga") || strTemCheck == string(".TGA"))
{
m_VecFileName.push_back(FileData.cFileName);
}
}
// 查找下一个文件,若查找完所有文件,则执行该语句块
if (!FindNextFile(hFind, &FileData))
{
if (GetLastError() != ERROR_NO_MORE_FILES) return false;
break;
}
}
if (!FindClose (hFind)) return false;
return true;
}
// 封包
bool CFilePack::Pack(const char* szPackFile)
{
if (m_VecFileName.empty()) return false;
string temPackFile = m_PackFolderPath;
temPackFile += "\\";
temPackFile += szPackFile;
FILE* pFile = fopen(temPackFile.c_str(), "wb");
if (!pFile) return false;
XMHHeader header;
header.m_Signature = 'HHWX';
header.m_FrameCount = m_VecFileName.size();
fwrite(&header, sizeof(XMHHeader), 1, pFile); // 写文件头
fseek(pFile, sizeof(ImgIndex)*header.m_FrameCount, SEEK_CUR); // 从当前指针处偏移
ImgIndex fileIndex;
fileIndex.m_FileIndex = ftell(pFile); // 记录最后一帧后的索引(该索引代表该帧的数据位置)
FILE* infile;
string strCurrtFile;;
for (int i=0; i<header.m_FrameCount; i++)
{
// 给当前待打包的文件名加上路径:资源\待打包 + \ + muhon_1.jpg
strCurrtFile = m_CurrtFolderPath;
strCurrtFile += "\\";
strCurrtFile += m_VecFileName[i];
infile = fopen(strCurrtFile.c_str(), "rb");
if (!infile) return false;
fseek(infile, 0L, SEEK_END);
fileIndex.m_FileSize = ftell(infile); // 记录当前帧大小
rewind(infile);
fseek(pFile, sizeof(ImgIndex)*i+sizeof(XMHHeader), SEEK_SET); // 从开始处偏移到第i个索引字节
fwrite(&fileIndex, sizeof(ImgIndex), 1, pFile); // 记录当前帧的索引结构信息
fseek(pFile, fileIndex.m_FileIndex, SEEK_SET); // 从开始处,偏移到当前帧的索引位置,准备记录文件数据
BYTE* pData = new BYTE[fileIndex.m_FileSize];
fread(pData, fileIndex.m_FileSize, 1, infile);
for (int i=0; i<(int)fileIndex.m_FileSize; i++)
{
pData[i] ^= 25362847; // 文件数据加密
}
fwrite(pData, fileIndex.m_FileSize, 1, pFile); // 写入文件数据
fileIndex.m_FileIndex = ftell(pFile); // 记录当前帧数据的所在索引(此索引将成为下一帧写数据的位置)
delete [] pData;
pData = NULL;
fclose(infile);
infile = NULL;
}
fclose(pFile);
return true;
}
// 解包
bool CFilePack::UnPack(const char* szPackFile)
{
CreateDirectory(m_UnPackFolderPath.c_str(), NULL); // 创建目录
FILE* pFile = fopen(szPackFile, "rb");
if (!pFile) return false;
XMHHeader header;
fread(&header, sizeof(XMHHeader), 1, pFile); // 读文件头
ImgIndex fileIndex;
FILE* outfile;
string strCurrtFile;;
char saveNum[50];
for (int i=0; i<header.m_FrameCount; i++)
{
fseek(pFile, sizeof(ImgIndex)*i+sizeof(XMHHeader), SEEK_SET); // 从开始处偏移到第i个索引字节
fread(&fileIndex, sizeof(ImgIndex), 1, pFile); // 读文件索引
strCurrtFile = m_UnPackFolderPath;
strCurrtFile += "\\";
string tempPackName = szPackFile;
string::size_type pos = tempPackName.rfind(".");
tempPackName.erase(tempPackName.begin()+pos, tempPackName.end());
pos = tempPackName.rfind("\\");
pos++;
tempPackName.erase(tempPackName.begin(), tempPackName.begin()+pos);
strCurrtFile += tempPackName;
strCurrtFile += "_";
sprintf_s(saveNum, "%d", i);
strCurrtFile += saveNum;
if (fileIndex.m_FIleFormat == JPG)
{
strCurrtFile += ".jpg";
}
outfile = fopen(strCurrtFile.c_str(), "wb");
fseek(pFile, fileIndex.m_FileIndex, SEEK_SET); // 定位到当前帧数据的索引位置
BYTE* pData = new BYTE[fileIndex.m_FileSize];
fread(pData, fileIndex.m_FileSize, 1, pFile); // 读当前帧的数据
for (int i=0; i<(int)fileIndex.m_FileSize; i++)
{
pData[i] ^= 25362847; // 文件数据解密
}
fwrite(pData, fileIndex.m_FileSize, 1, outfile); // 写出当前文件
delete [] pData;
pData = NULL;
fclose(outfile);
outfile = NULL;
}
fclose(pFile);
return true;
}
// main.cpp
#include <iostream>
#include "FilePack.h"
using namespace std;
int main()
{
CFilePack filePack;
filePack.LoadFileDate("资源\\待打包");
filePack.SetPackFolderPath("资源");
filePack.Pack("text.xmh");
filePack.SetUnPackFolderPath("资源\\解包后");
filePack.UnPack("资源\\text.xmh");
cout << endl;
system("pause");
return 0;
}
#12
如果你使用的是WINDOWS系统,试试文件映射技术,这技术读文件的速度比普通文件操作不知快了多少倍,几GB的文件读取都很快
#13
我不知道怎么读图片。没有接触过这么底层的东西
我以前只是包含了一个库或者什么的。
然后用一个LoadImage(“文件名”)
这样的方法去读了一个图片 然后保存到一个image类的指针里面
如果按照这样的打包了
我不管最后得到了的是什么自定义的文件
我解包了之后如何用?
我以前只是包含了一个库或者什么的。
然后用一个LoadImage(“文件名”)
这样的方法去读了一个图片 然后保存到一个image类的指针里面
如果按照这样的打包了
我不管最后得到了的是什么自定义的文件
我解包了之后如何用?
#14
用一个ReadFile() 吗
#15
想听听怎么实现。。
#1
就是从硬盘快速读入大量图片
有什么方法 或者资料看啊
有什么方法 或者资料看啊
#2
没用过,不知道
但是好像是用什么工具把图片等资源做成专门的格式,然后在需要的时候一次性读取出来
但是好像是用什么工具把图片等资源做成专门的格式,然后在需要的时候一次性读取出来
#3
打包就是把一堆文件搞到一个文件里。
要说把图片打包了读取时间会大大减少。打了包后在磁盘存取效率上会有一些优势,但说到大大减少,那是没可能的。
暴雪的资源都是打包的,每个游戏里肯定都有一些巨大的文件,也就是打包的资源,包括图片声音等等等等,网上有暴雪的资源查看工具的。
要说把图片打包了读取时间会大大减少。打了包后在磁盘存取效率上会有一些优势,但说到大大减少,那是没可能的。
暴雪的资源都是打包的,每个游戏里肯定都有一些巨大的文件,也就是打包的资源,包括图片声音等等等等,网上有暴雪的资源查看工具的。
#4
我现在就是要读取一些地图文件 很巨大。
如何让读取时间变短点?
如果是打包
要怎么打包?
50多张png的图片
我打包后如何读取?
我只用过一些封装好的方法读取图片文件 (参数就是一个图片的文件名。)
没有自己写 过方法。
如何让读取时间变短点?
如果是打包
要怎么打包?
50多张png的图片
我打包后如何读取?
我只用过一些封装好的方法读取图片文件 (参数就是一个图片的文件名。)
没有自己写 过方法。
#5
如果是图像本身很大,那么就要考虑是不是把大图切成小图,每次只读取需要显示的那部分图像,而不是每次都读整个图。
如何打包的问题,记得网上有暴雪的打包格式的分析,搜搜就知道了。
最简单的打包方法就是头上一个索引,然后把其他文件都合并到一个文件里,在索引里记录各个文件的位置长度就是了。
如何打包的问题,记得网上有暴雪的打包格式的分析,搜搜就知道了。
最简单的打包方法就是头上一个索引,然后把其他文件都合并到一个文件里,在索引里记录各个文件的位置长度就是了。
#6
能贴点代码看看吗,
比如是2张png的图 打包
用C++
比如是2张png的图 打包
用C++
#7
或者在DX9里面实现~
#8
最简单的就是把所有图片都放合并为一个文件,然后生成一个配置文件,这个配置文件保存每一张图片在那个合并后的文件中的位置和大小,读的时候由于只打开一个文件,相比打开多个图片文件会快点
#9
“图片打包”说的是把多张图片平铺合成为一张图片吧?对于零碎的小图片来说很有用。
#10
我这几天也在跟图片打包打交道。
我说一下自己的愚见。
图片打包就是通过像fopen()、fwrite()、fread()等函数,把N个图片数据读取进来,然后再写到一个文件中的过程。
这里有一个问题就是图片的数据是什么样子,我也不知道是什么样子,不过肯定是一些二进制或十六进制的数吧。用fread把图片数据读进文件流后,再定义一个文件输出流,用于写文件,你可以开始向这个输出流写一点标记,比如写一个struct文件头数据,里面记录要写的图片数据的格式,比如大小,宽读,索引,之类的,写完再写一个struct结构体数据,当做第1个图片的索引信息,然后写入第1个图片数据,然后再写下一个图片的索引,再写下一个图片的数据……
我说的比较乱,比较散,你听个大概就可以了,我这里在列一下我的封包文件的格式:
文件开始:
struct 文件头
struct 第1个图片的索引
struct 第2个图片的索引
struct 第3个图片的索引
……
Data: 第1个图片数据
Data: 第2个图片数据
Data: 第3个图片数据
……
文件结束:
你可能会问,把这么一堆图片数据写进去,那怎么解包,怎么读出来呢?
答案就在上面这个写法上,为什么要像这样写?我先说一下这个使用流程,说完,你可能就会明白。
1:写文件头,并确定一共要写多少个图片进来,这样可以确定索引结构体的数量
2:确定了图片索引结构的数量后,直接跳到sizeof(图片索引结构)*图片数量 + sizeof(文件头) 这个地方并记下第1个结构索引所对应的图片数据(第1个图片)的位置。 这句话明白么?如果你明白的话,你就懂了。
3:然后再回到第1个索引处,记下第1个图片索引数据(就是在上一步记录的那个位置写),写完第1个图片数据后,紧接着再记录当前的图片索引,以便于下一次再用这个地址写第2个图片。
4:和3一样,就是要处理下一索引,及其图片数据
如果这个流程还是看不懂,仔细看看上面的文件结构,我开始就是琢磨这个结构,才写出来的。
如果想要代码,我这有现成的,代码很简短,很容易看懂,要是想要的话,加我QQ:1491839
我说一下自己的愚见。
图片打包就是通过像fopen()、fwrite()、fread()等函数,把N个图片数据读取进来,然后再写到一个文件中的过程。
这里有一个问题就是图片的数据是什么样子,我也不知道是什么样子,不过肯定是一些二进制或十六进制的数吧。用fread把图片数据读进文件流后,再定义一个文件输出流,用于写文件,你可以开始向这个输出流写一点标记,比如写一个struct文件头数据,里面记录要写的图片数据的格式,比如大小,宽读,索引,之类的,写完再写一个struct结构体数据,当做第1个图片的索引信息,然后写入第1个图片数据,然后再写下一个图片的索引,再写下一个图片的数据……
我说的比较乱,比较散,你听个大概就可以了,我这里在列一下我的封包文件的格式:
文件开始:
struct 文件头
struct 第1个图片的索引
struct 第2个图片的索引
struct 第3个图片的索引
……
Data: 第1个图片数据
Data: 第2个图片数据
Data: 第3个图片数据
……
文件结束:
你可能会问,把这么一堆图片数据写进去,那怎么解包,怎么读出来呢?
答案就在上面这个写法上,为什么要像这样写?我先说一下这个使用流程,说完,你可能就会明白。
1:写文件头,并确定一共要写多少个图片进来,这样可以确定索引结构体的数量
2:确定了图片索引结构的数量后,直接跳到sizeof(图片索引结构)*图片数量 + sizeof(文件头) 这个地方并记下第1个结构索引所对应的图片数据(第1个图片)的位置。 这句话明白么?如果你明白的话,你就懂了。
3:然后再回到第1个索引处,记下第1个图片索引数据(就是在上一步记录的那个位置写),写完第1个图片数据后,紧接着再记录当前的图片索引,以便于下一次再用这个地址写第2个图片。
4:和3一样,就是要处理下一索引,及其图片数据
如果这个流程还是看不懂,仔细看看上面的文件结构,我开始就是琢磨这个结构,才写出来的。
如果想要代码,我这有现成的,代码很简短,很容易看懂,要是想要的话,加我QQ:1491839
#11
// Pack.h
#ifndef _FILEPACK_
#define _FILEPACK_
#include <windows.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
enum FIleFormat
{
BMP,
JPG,
PNG,
TGA,
};
// 文件头 (20 bytes total)
struct XMHHeader
{
XMHHeader()
{
m_Signature = 0;
m_Width = 0;
m_Height = 0;
m_FrameCount = 1;
m_Version = 1000;
m_Reserved = 0;
}
DWORD m_Signature; // 文件标识:"XMHH"
DWORD m_Width; // 图片使用
DWORD m_Height; // 图片使用
WORD m_FrameCount; // 帧数
WORD m_Version; // 版本信息
DWORD m_Reserved; // 保留字
};
// 图像的索引信息 (20 bytes total)
struct ImgIndex
{
ImgIndex()
{
m_FileIndex = 0;
m_FileSize = 0;
m_FIleFormat = JPG;
}
DWORD m_FileIndex; // 排在所有XMH_MultiTexIndex信息字节的后面,该索引是每帧数据尾部的字节大小
DWORD m_FileSize;
DWORD m_FIleFormat; // 图片格式
DWORD m_Width;
DWORD m_Height;
};
class CFilePack
{
public:
CFilePack();
~CFilePack();
// -----------------------------------------------------------------
bool LoadFileDate(const char* szDirectory);
int GetFileCount() const { return m_VecFileName.size(); }
vector<string> GetVecFileName() const { return m_VecFileName; } // 获得文件名容器
string GetCurrtFolderPath() const { return m_CurrtFolderPath; } // 获得当前文件路径
void SetPackFolderPath(string szDirectory) { m_PackFolderPath = szDirectory; }
void SetUnPackFolderPath(string szDirectory) { m_UnPackFolderPath = szDirectory; }
// -----------------------------------------------------------------
bool Pack(const char* szPackFile); // 封包
bool UnPack(const char* szPackFile); // 解包
private:
vector<string> m_VecFileName; // 保存文件名的容器
string m_CurrtFolderPath; // 当前文件所在的文件夹路径
string m_PackFolderPath; // 封包文件的目录
string m_UnPackFolderPath; // 解包文件的目录
};
#endif
// Pack.cpp
#include "FilePack.h"
CFilePack::CFilePack()
{
}
CFilePack::~CFilePack()
{
}
bool CFilePack::LoadFileDate(const char* szDirectory)
{
if (!szDirectory) return false;
m_CurrtFolderPath = szDirectory; // 记录当前文件所在的文件夹路径
m_PackFolderPath = szDirectory;
m_UnPackFolderPath = szDirectory;
string strCurrtFile = szDirectory;
strCurrtFile += "\\*.*"; // 定位到该目录的第一个文件(“.”即根目录)
WIN32_FIND_DATA FileData;
HANDLE hFind = FindFirstFile(strCurrtFile.c_str(), &FileData); // 返回根目录的句柄
if (hFind == INVALID_HANDLE_VALUE) return false;
m_VecFileName.clear();
string strTemCheck; // 用于存放FileData.cFileName,判断其后缀名
// 绕过"."和".."
while (1)
{
if (strcmp(FileData.cFileName, ".")!=0 && strcmp(FileData.cFileName,"..")!=0 && (!(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
{
strTemCheck = FileData.cFileName;
string::size_type pos = strTemCheck.rfind(".");
strTemCheck.erase(strTemCheck.begin(), strTemCheck.begin()+pos); // 只保留后缀
// 只保存合法的格式文件
if (strTemCheck == string(".bmp") || strTemCheck == string(".BMP") ||
strTemCheck == string(".jpg") || strTemCheck == string(".JPG") ||
strTemCheck == string(".gif") || strTemCheck == string(".GIF") ||
strTemCheck == string(".png") || strTemCheck == string(".PNG") ||
strTemCheck == string(".tga") || strTemCheck == string(".TGA"))
{
m_VecFileName.push_back(FileData.cFileName);
}
}
// 查找下一个文件,若查找完所有文件,则执行该语句块
if (!FindNextFile(hFind, &FileData))
{
if (GetLastError() != ERROR_NO_MORE_FILES) return false;
break;
}
}
if (!FindClose (hFind)) return false;
return true;
}
// 封包
bool CFilePack::Pack(const char* szPackFile)
{
if (m_VecFileName.empty()) return false;
string temPackFile = m_PackFolderPath;
temPackFile += "\\";
temPackFile += szPackFile;
FILE* pFile = fopen(temPackFile.c_str(), "wb");
if (!pFile) return false;
XMHHeader header;
header.m_Signature = 'HHWX';
header.m_FrameCount = m_VecFileName.size();
fwrite(&header, sizeof(XMHHeader), 1, pFile); // 写文件头
fseek(pFile, sizeof(ImgIndex)*header.m_FrameCount, SEEK_CUR); // 从当前指针处偏移
ImgIndex fileIndex;
fileIndex.m_FileIndex = ftell(pFile); // 记录最后一帧后的索引(该索引代表该帧的数据位置)
FILE* infile;
string strCurrtFile;;
for (int i=0; i<header.m_FrameCount; i++)
{
// 给当前待打包的文件名加上路径:资源\待打包 + \ + muhon_1.jpg
strCurrtFile = m_CurrtFolderPath;
strCurrtFile += "\\";
strCurrtFile += m_VecFileName[i];
infile = fopen(strCurrtFile.c_str(), "rb");
if (!infile) return false;
fseek(infile, 0L, SEEK_END);
fileIndex.m_FileSize = ftell(infile); // 记录当前帧大小
rewind(infile);
fseek(pFile, sizeof(ImgIndex)*i+sizeof(XMHHeader), SEEK_SET); // 从开始处偏移到第i个索引字节
fwrite(&fileIndex, sizeof(ImgIndex), 1, pFile); // 记录当前帧的索引结构信息
fseek(pFile, fileIndex.m_FileIndex, SEEK_SET); // 从开始处,偏移到当前帧的索引位置,准备记录文件数据
BYTE* pData = new BYTE[fileIndex.m_FileSize];
fread(pData, fileIndex.m_FileSize, 1, infile);
for (int i=0; i<(int)fileIndex.m_FileSize; i++)
{
pData[i] ^= 25362847; // 文件数据加密
}
fwrite(pData, fileIndex.m_FileSize, 1, pFile); // 写入文件数据
fileIndex.m_FileIndex = ftell(pFile); // 记录当前帧数据的所在索引(此索引将成为下一帧写数据的位置)
delete [] pData;
pData = NULL;
fclose(infile);
infile = NULL;
}
fclose(pFile);
return true;
}
// 解包
bool CFilePack::UnPack(const char* szPackFile)
{
CreateDirectory(m_UnPackFolderPath.c_str(), NULL); // 创建目录
FILE* pFile = fopen(szPackFile, "rb");
if (!pFile) return false;
XMHHeader header;
fread(&header, sizeof(XMHHeader), 1, pFile); // 读文件头
ImgIndex fileIndex;
FILE* outfile;
string strCurrtFile;;
char saveNum[50];
for (int i=0; i<header.m_FrameCount; i++)
{
fseek(pFile, sizeof(ImgIndex)*i+sizeof(XMHHeader), SEEK_SET); // 从开始处偏移到第i个索引字节
fread(&fileIndex, sizeof(ImgIndex), 1, pFile); // 读文件索引
strCurrtFile = m_UnPackFolderPath;
strCurrtFile += "\\";
string tempPackName = szPackFile;
string::size_type pos = tempPackName.rfind(".");
tempPackName.erase(tempPackName.begin()+pos, tempPackName.end());
pos = tempPackName.rfind("\\");
pos++;
tempPackName.erase(tempPackName.begin(), tempPackName.begin()+pos);
strCurrtFile += tempPackName;
strCurrtFile += "_";
sprintf_s(saveNum, "%d", i);
strCurrtFile += saveNum;
if (fileIndex.m_FIleFormat == JPG)
{
strCurrtFile += ".jpg";
}
outfile = fopen(strCurrtFile.c_str(), "wb");
fseek(pFile, fileIndex.m_FileIndex, SEEK_SET); // 定位到当前帧数据的索引位置
BYTE* pData = new BYTE[fileIndex.m_FileSize];
fread(pData, fileIndex.m_FileSize, 1, pFile); // 读当前帧的数据
for (int i=0; i<(int)fileIndex.m_FileSize; i++)
{
pData[i] ^= 25362847; // 文件数据解密
}
fwrite(pData, fileIndex.m_FileSize, 1, outfile); // 写出当前文件
delete [] pData;
pData = NULL;
fclose(outfile);
outfile = NULL;
}
fclose(pFile);
return true;
}
// main.cpp
#include <iostream>
#include "FilePack.h"
using namespace std;
int main()
{
CFilePack filePack;
filePack.LoadFileDate("资源\\待打包");
filePack.SetPackFolderPath("资源");
filePack.Pack("text.xmh");
filePack.SetUnPackFolderPath("资源\\解包后");
filePack.UnPack("资源\\text.xmh");
cout << endl;
system("pause");
return 0;
}
#12
如果你使用的是WINDOWS系统,试试文件映射技术,这技术读文件的速度比普通文件操作不知快了多少倍,几GB的文件读取都很快
#13
我不知道怎么读图片。没有接触过这么底层的东西
我以前只是包含了一个库或者什么的。
然后用一个LoadImage(“文件名”)
这样的方法去读了一个图片 然后保存到一个image类的指针里面
如果按照这样的打包了
我不管最后得到了的是什么自定义的文件
我解包了之后如何用?
我以前只是包含了一个库或者什么的。
然后用一个LoadImage(“文件名”)
这样的方法去读了一个图片 然后保存到一个image类的指针里面
如果按照这样的打包了
我不管最后得到了的是什么自定义的文件
我解包了之后如何用?
#14
用一个ReadFile() 吗
#15
想听听怎么实现。。