void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string relativePath) { struct dirent* dp; struct stat stat_p; DIR *dirp = opendir(fullPath.c_str()); if (dirp) { while ((dp = readdir(dirp)) != NULL) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { continue; } //stat to check for dir type (reiserfs fix) std::string fileN = fullPath + "/" + dp->d_name; if (stat(fileN.c_str(), &stat_p) == 0) { if (dp->d_type == DT_DIR || stat_p.st_mode & S_IFDIR) { std::string tmpPath = relativePath; if (tmpPath.size() > 0) { tmpPath += "/"; } CreateSkeletonHeaderImpl(xbtf, fullPath + DIR_SEPARATOR + dp->d_name, tmpPath + dp->d_name); } else if (DecoderManager::IsSupportedGraphicsFile(dp->d_name)) { std::string fileName = ""; if (relativePath.size() > 0) { fileName += relativePath; fileName += "/"; } fileName += dp->d_name; CXBTFFile file; file.SetPath(fileName); xbtf.GetFiles().push_back(file); } } } closedir(dirp); } else { fprintf(stderr, "Error opening %s (%s)\n", fullPath.c_str(), strerror(errno)); } }
int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags, bool dupecheck) { map<string,unsigned int> hashes; vector<unsigned int> dupes; CXBTF xbtf; CreateSkeletonHeader(xbtf, InputDir); dupes.resize(xbtf.GetFiles().size()); if (!dupecheck) { for (unsigned int i=0;i<dupes.size();++i) dupes[i] = i; } CXBTFWriter writer(xbtf, OutputFile); if (!writer.Create()) { printf("Error creating file\n"); return 1; } std::vector<CXBTFFile>& files = xbtf.GetFiles(); for (size_t i = 0; i < files.size(); i++) { struct MD5Context ctx; MD5Init(&ctx); CXBTFFile& file = files[i]; std::string fullPath = InputDir; fullPath += file.GetPath(); std::string output = file.GetPath(); output = output.substr(0, 40); while (output.size() < 46) output += ' '; if (!IsGIF(fullPath.c_str())) { // Load the image SDL_Surface* image = IMG_Load(fullPath.c_str()); if (!image) { printf("...unable to load image %s\n", file.GetPath()); continue; } bool skip=false; printf("%s", output.c_str()); if (dupecheck) { MD5Update(&ctx,(const uint8_t*)image->pixels,image->h*image->pitch); if (checkDupe(&ctx,hashes,dupes,i)) { printf("**** duplicate of %s\n", files[dupes[i]].GetPath()); file.GetFrames().insert(file.GetFrames().end(), files[dupes[i]].GetFrames().begin(), files[dupes[i]].GetFrames().end()); skip = true; } } if (!skip) { CXBTFFrame frame = createXBTFFrame(image, writer, maxMSE, flags); printf("%s%c (%d,%d @ %"PRIu64" bytes)\n", GetFormatString(frame.GetFormat()), frame.HasAlpha() ? ' ' : '*', frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize()); file.SetLoop(0); file.GetFrames().push_back(frame); } SDL_FreeSurface(image); } else { int gnAG = AG_LoadGIF(fullPath.c_str(), NULL, 0); AG_Frame* gpAG = new AG_Frame[gnAG]; AG_LoadGIF(fullPath.c_str(), gpAG, gnAG); printf("%s\n", output.c_str()); bool skip=false; if (dupecheck) { for (int j = 0; j < gnAG; j++) MD5Update(&ctx, (const uint8_t*)gpAG[j].surface->pixels, gpAG[j].surface->h * gpAG[j].surface->pitch); if (checkDupe(&ctx,hashes,dupes,i)) { printf("**** duplicate of %s\n", files[dupes[i]].GetPath()); file.GetFrames().insert(file.GetFrames().end(), files[dupes[i]].GetFrames().begin(), files[dupes[i]].GetFrames().end()); skip = true; } } if (!skip) { for (int j = 0; j < gnAG; j++) { printf(" frame %4i ", j); CXBTFFrame frame = createXBTFFrame(gpAG[j].surface, writer, maxMSE, flags); frame.SetDuration(gpAG[j].delay); file.GetFrames().push_back(frame); printf("%s%c (%d,%d @ %"PRIu64" bytes)\n", GetFormatString(frame.GetFormat()), frame.HasAlpha() ? ' ' : '*', frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize()); } } AG_FreeSurfaces(gpAG, gnAG); delete [] gpAG; file.SetLoop(0); } } if (!writer.UpdateHeader(dupes)) { printf("Error writing header to file\n"); return 1; } if (!writer.Close()) { printf("Error closing file\n"); return 1; } return 0; }
int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags, bool dupecheck) { map<string,unsigned int> hashes; vector<unsigned int> dupes; CXBTF xbtf; CreateSkeletonHeader(xbtf, InputDir); dupes.resize(xbtf.GetFiles().size()); if (!dupecheck) { for (unsigned int i=0;i<dupes.size();++i) dupes[i] = i; } CXBTFWriter writer(xbtf, OutputFile); if (!writer.Create()) { fprintf(stderr, "Error creating file\n"); return 1; } std::vector<CXBTFFile>& files = xbtf.GetFiles(); for (size_t i = 0; i < files.size(); i++) { struct MD5Context ctx; MD5Init(&ctx); CXBTFFile& file = files[i]; std::string fullPath = InputDir; fullPath += file.GetPath(); std::string output = file.GetPath(); output = output.substr(0, 40); while (output.size() < 46) output += ' '; DecodedFrames frames; bool loaded = DecoderManager::LoadFile(fullPath, frames); if (!loaded) { fprintf(stderr, "...unable to load image %s\n", file.GetPath()); continue; } printf("%s\n", output.c_str()); bool skip=false; if (dupecheck) { for (unsigned int j = 0; j < frames.frameList.size(); j++) MD5Update(&ctx, (const uint8_t*)frames.frameList[j].rgbaImage.pixels, frames.frameList[j].rgbaImage.height * frames.frameList[j].rgbaImage.pitch); if (checkDupe(&ctx,hashes,dupes,i)) { printf("**** duplicate of %s\n", files[dupes[i]].GetPath()); file.GetFrames().insert(file.GetFrames().end(), files[dupes[i]].GetFrames().begin(), files[dupes[i]].GetFrames().end()); skip = true; } } if (!skip) { for (unsigned int j = 0; j < frames.frameList.size(); j++) { printf(" frame %4i ", j); CXBTFFrame frame = createXBTFFrame(frames.frameList[j].rgbaImage, writer, maxMSE, flags); frame.SetDuration(frames.frameList[j].delay); file.GetFrames().push_back(frame); printf("%s%c (%d,%d @ %"PRIu64" bytes)\n", GetFormatString(frame.GetFormat()), frame.HasAlpha() ? ' ' : '*', frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize()); } } DecoderManager::FreeDecodedFrames(frames); file.SetLoop(0); } if (!writer.UpdateHeader(dupes)) { fprintf(stderr, "Error writing header to file\n"); return 1; } if (!writer.Close()) { fprintf(stderr, "Error closing file\n"); return 1; } return 0; }