void TexturePacker::PackToMultipleTextures(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defList) { if (defList.size() != 1) if (CommandLineParser::Instance()->GetVerbose())printf("* ERROR: failed to pack to multiple textures\n"); for (int i = 0; i < (int)sortVector.size(); ++i) { DefinitionFile * defFile = sortVector[i].defFile; int frame = sortVector[i].frameIndex; if (CommandLineParser::Instance()->GetVerbose())printf("[MultiPack] prepack: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); } std::vector<ImagePacker*> & packers = usedPackers; /* // OLD PACKING ALGORITHM ImagePacker * currentPacker = new ImagePacker(Rect2i::Make(0, 0, 1024, 1024)); packers.push_back(currentPacker); // Packing of sorted by size images for (int i = 0; i < sortVector.size(); ++i) { DefinitionFile * defFile = sortVector[i].defFile; int frame = sortVector[i].frameIndex; printf("[MultiPack] pack: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); bool packed = false; for (int packerIndex = 0; packerIndex < packers.size(); ++packerIndex) { if (packers[packerIndex]->AddImage(Size2i::Make(defFile->frameRects[frame].dx, defFile->frameRects[frame].dy), &defFile->frameRects[frame])) { packed = true; printf("[MultiPack] added to packer: %d\n", packerIndex); break; } } if (!packed) { currentPacker = new ImagePacker(Rect2i::Make(0, 0, 1024, 1024)); packers.push_back(currentPacker); if (!currentPacker->AddImage(Size2i::Make(defFile->frameRects[frame].dx, defFile->frameRects[frame].dy), &defFile->frameRects[frame])) { printf("*** FATAL ERROR: image is too big: imageSize: %d, %d\n", defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); return; }else { printf("[MultiPack] added to packer: %d\n", packers.size() - 1); } } } */ /* // ALGO #2 std::vector<SizeSortItem> sortVectorWork = sortVector; while(sortVectorWork.size() > 0) { // try to pack for each resolution int maxPackedObjects = 0; //int bestResolution = 1025 * 1025; printf("* Packing tries started: "); ImagePacker * bestPackerForThisStep = 0; std::vector<SizeSortItem> newWorkVector; for (int yResolution = 8; yResolution <= 1024; yResolution *= 2) for (int xResolution = 8; xResolution <= 1024; xResolution *= 2) { Rect2i textureRect = Rect2i::Make(0, 0, xResolution, yResolution); ImagePacker * packer = new ImagePacker(textureRect); std::vector<SizeSortItem> tempSortVector = sortVectorWork; int n = TryToPackFromSortVector(packer, tempSortVector); if (n > maxPackedObjects) { maxPackedObjects = n; SafeDelete(bestPackerForThisStep); bestPackerForThisStep = packer; newWorkVector = tempSortVector; } } sortVectorWork = newWorkVector; packers.push_back(bestPackerForThisStep); } */ std::vector<SizeSortItem> sortVectorWork = sortVector; while(sortVectorWork.size() > 0) { // try to pack for each resolution float maxValue = 0.0f; //int bestResolution = 1025 * 1025; if (CommandLineParser::Instance()->GetVerbose())printf("* Packing tries started: "); ImagePacker * bestPackerForThisStep = 0; std::vector<SizeSortItem> newWorkVector; for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { if (CommandLineParser::Instance()->IsFlagSet("--pvr") && (xResolution != yResolution))continue; if ((onlySquareTextures) && (xResolution != yResolution))continue; Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); ImagePacker * packer = new ImagePacker(textureRect); std::vector<SizeSortItem> tempSortVector = sortVectorWork; float n = TryToPackFromSortVectorWeight(packer, tempSortVector); if (n > maxValue) { maxValue = n; SafeDelete(bestPackerForThisStep); bestPackerForThisStep = packer; newWorkVector = tempSortVector; } } sortVectorWork = newWorkVector; packers.push_back(bestPackerForThisStep); } if (CommandLineParser::Instance()->GetVerbose())printf("* Writing %d final textures \n", (int)packers.size()); std::vector<PngImageExt*> finalImages; for (int imageIndex = 0; imageIndex < (int)packers.size(); ++imageIndex) { PngImageExt * image = new PngImageExt(); ImagePacker * packer = packers[imageIndex]; image->Create(packer->GetRect().dx, packer->GetRect().dy); finalImages.push_back(image); } for (std::list<DefinitionFile*>::iterator defi = defList.begin(); defi != defList.end(); ++defi) { DefinitionFile * defFile = *defi; for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i * destRect; ImagePacker * foundPacker = 0; int packerIndex = 0; char name[256]; for (packerIndex = 0; packerIndex < (int)packers.size(); ++packerIndex) { destRect = packers[packerIndex]->SearchRectForPtr(&defFile->frameRects[frame]); if (destRect) { foundPacker = packers[packerIndex]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); break; } } if (foundPacker) { if (CommandLineParser::Instance()->GetVerbose())printf("[MultiPack] pack to texture: %d\n", packerIndex); PngImageExt image; image.Read(name); finalImages[packerIndex]->DrawImage(destRect->x, destRect->y, &image); if (CommandLineParser::Instance()->IsFlagSet("--debug")) { finalImages[packerIndex]->DrawRect(*destRect, 0xFF0000FF); } } } } for (int image = 0; image < (int)packers.size(); ++image) { char temp[256]; sprintf(temp, "texture%d.png", image); std::string textureName = std::string(outputPath) + std::string(temp); finalImages[image]->Write(textureName.c_str()); } for (std::list<DefinitionFile*>::iterator defi = defList.begin(); defi != defList.end(); ++defi) { DefinitionFile * defFile = *defi; std::string textureName = std::string(outputPath) + std::string("texture"); if (!WriteMultipleDefinition(excludeFolder, outputPath, "texture", defFile)) { printf("* ERROR: failed to write definition\n"); } } }
void TexturePacker::PackToTexturesSeparate(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defsList) { lastPackedPacker = 0; int textureIndex = 0; for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { sortVector.clear(); DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { SizeSortItem sortItem; sortItem.imageSize = defFile->frameRects[frame].dx * defFile->frameRects[frame].dy; sortItem.defFile = defFile; sortItem.frameIndex = frame; sortVector.push_back(sortItem); } std::sort(sortVector.begin(), sortVector.end(), sortFn); // try to pack for each resolution int bestResolution = (maxTextureSize + 1) * (maxTextureSize + 1); int bestXResolution, bestYResolution; if (CommandLineParser::Instance()->GetVerbose()) printf("* Packing tries started: "); for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); if (xResolution * yResolution < bestResolution) if (TryToPack(textureRect, defsList)) { bestResolution = xResolution * yResolution; bestXResolution = xResolution; bestYResolution = yResolution; } } if (CommandLineParser::Instance()->GetVerbose()) printf("\n"); if (bestResolution != (maxTextureSize + 1) * (maxTextureSize + 1)) { char textureNameWithIndex[50]; sprintf(textureNameWithIndex, "texture%d", textureIndex++); std::string textureName = std::string(outputPath) + std::string(textureNameWithIndex); if (CommandLineParser::Instance()->GetVerbose()) printf("* Writing final texture (%d x %d): %s\n", bestXResolution, bestYResolution , textureName.c_str()); PngImageExt finalImage; finalImage.Create(bestXResolution, bestYResolution); // Writing for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i *destRect = lastPackedPacker->SearchRectForPtr(&defFile->frameRects[frame]); if (!destRect)printf("*** ERROR Can't find rect for frame\n"); char name[256]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); PngImageExt image; image.Read(name); finalImage.DrawImage(destRect->x, destRect->y, &image); } if (!WriteDefinition(excludeFolder, outputPath, textureNameWithIndex, defFile)) { printf("* ERROR: failed to write definition\n"); } char textureExtension[5] = "png"; if (CommandLineParser::Instance()->IsFlagSet("--pvr"))strcpy(textureExtension, "pvr"); textureName += std::string(".") + textureExtension; finalImage.Write(textureName.c_str()); } } }
void TexturePacker::PackToTextures(const char * excludeFolder, const char* outputPath, std::list<DefinitionFile*> & defsList) { lastPackedPacker = 0; for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { SizeSortItem sortItem; sortItem.imageSize = defFile->frameRects[frame].dx * defFile->frameRects[frame].dy; sortItem.defFile = defFile; sortItem.frameIndex = frame; sortVector.push_back(sortItem); } } // for (int i = 0; i < sortVector.size(); ++i) // { // DefinitionFile * defFile = sortVector[i].defFile; // int frame = sortVector[i].frameIndex; // printf("[SinglePack] before sort: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); // } std::sort(sortVector.begin(), sortVector.end(), sortFn); // for (int i = 0; i < sortVector.size(); ++i) // { // DefinitionFile * defFile = sortVector[i].defFile; // int frame = sortVector[i].frameIndex; // printf("[SinglePack] after sort: %s frame: %d w:%d h:%d\n", defFile->filename.c_str(), frame, defFile->frameRects[frame].dx, defFile->frameRects[frame].dy); // } // try to pack for each resolution int bestResolution = (maxTextureSize + 1) * (maxTextureSize + 1); int bestXResolution, bestYResolution; if (CommandLineParser::Instance()->GetVerbose()) printf("* Packing tries started: "); bool isPvr = false; if (CommandLineParser::Instance()->IsFlagSet("--pvr")) isPvr = true; for (int yResolution = 8; yResolution <= maxTextureSize; yResolution *= 2) for (int xResolution = 8; xResolution <= maxTextureSize; xResolution *= 2) { if ((isPvr) && (xResolution != yResolution))continue; if ((onlySquareTextures) && (xResolution != yResolution))continue; Rect2i textureRect = Rect2i(0, 0, xResolution, yResolution); if (xResolution * yResolution < bestResolution) if (TryToPack(textureRect, defsList)) { bestResolution = xResolution * yResolution; bestXResolution = xResolution; bestYResolution = yResolution; } } if (CommandLineParser::Instance()->GetVerbose()) printf("\n"); if (bestResolution != (maxTextureSize + 1) * (maxTextureSize + 1)) { std::string textureName = std::string(outputPath) + std::string("texture"); if (CommandLineParser::Instance()->GetVerbose()) printf("* Writing final texture (%d x %d): %s\n", bestXResolution, bestYResolution , textureName.c_str()); PngImageExt finalImage; finalImage.Create(bestXResolution, bestYResolution); // Writing for (std::list<DefinitionFile*>::iterator dfi = defsList.begin(); dfi != defsList.end(); ++dfi) { DefinitionFile * defFile = *dfi; for (int frame = 0; frame < defFile->frameCount; ++frame) { Rect2i *destRect = lastPackedPacker->SearchRectForPtr(&defFile->frameRects[frame]); if (!destRect)printf("*** ERROR Can't find rect for frame\n"); char name[256]; std::string withoutExt = defFile->filename.substr(0, defFile->filename.length() - 4); snprintf(name, 256, "%s%d.png", withoutExt.c_str(), frame); PngImageExt image; image.Read(name); finalImage.DrawImage(destRect->x, destRect->y, &image); if (CommandLineParser::Instance()->IsFlagSet("--debug")) { finalImage.DrawRect(*destRect, 0xFF0000FF); } } if (!WriteDefinition(excludeFolder, outputPath, "texture", defFile)) { printf("* ERROR: failed to write definition\n"); } } char textureExtension[5] = "png"; if (CommandLineParser::Instance()->IsFlagSet("--pvr"))strcpy(textureExtension, "pvr"); textureName += std::string(".") + textureExtension; finalImage.Write(textureName.c_str()); } else { // PackToMultipleTextures(excludeFolder, outputPath, defsList); } }
bool DefinitionFile::LoadPNGDef(const std::string & _filename, const std::string & pathToProcess) { if (CommandLineParser::Instance()->GetVerbose())printf("* Load PNG Definition: %s\n", _filename.c_str()); FILE * fp = fopen(_filename.c_str(), "rt"); fscanf(fp, "%d", &frameCount); String path; String name; CommandLineParser::SplitFilePath(_filename, path, name); String nameWithoutExt = name.substr(0, name.length() - 7); String corespondingPngImage = path + String("/") + nameWithoutExt + String(".png"); filename = pathToProcess + String("/") + nameWithoutExt + String(".txt"); PngImageExt image; image.Read(corespondingPngImage.c_str()); spriteWidth = image.GetWidth() / frameCount; spriteHeight = image.GetHeight(); // String dirWrite = path + String("/$process/"); // mkdir(dirWrite.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (CommandLineParser::Instance()->GetVerbose())printf("* frameCount: %d spriteWidth: %d spriteHeight: %d\n", frameCount, spriteWidth, spriteHeight); frameRects = new Rect2i[frameCount]; for (int k = 0; k < frameCount; ++k) { PngImageExt frameX; frameX.Create(spriteWidth, spriteHeight); frameX.DrawImage(0, 0, &image, Rect2i(k * spriteWidth, 0, spriteWidth, spriteHeight)); Rect2i reducedRect; frameX.FindNonOpaqueRect(reducedRect); if (CommandLineParser::Instance()->GetVerbose())printf("%s - reduced_rect(%d %d %d %d)\n", nameWithoutExt.c_str(), reducedRect.x, reducedRect.y, reducedRect.dx, reducedRect.dy); /*if (k == 1) { for (int y = 0; y < spriteWidth; ++y) { for (int x = 0; x < spriteWidth; ++x) { printf("%02x ", frameX.GetPixel(x, y)[3]); } printf("\n"); } }*/ PngImageExt frameX2; frameX2.Create(reducedRect.dx, reducedRect.dy); frameX2.DrawImage(0, 0, &frameX, reducedRect); char number[10]; sprintf(number, "%d", k); String fileWrite = pathToProcess + String("/") + nameWithoutExt + String(number) + String(".png"); frameX2.Write(fileWrite.c_str()); frameRects[k].x = reducedRect.x; frameRects[k].y = reducedRect.y; frameRects[k].dx = reducedRect.dx; frameRects[k].dy = reducedRect.dy; if (CommandLineParser::Instance()->IsFlagSet("--add0pixel")) { }else if (CommandLineParser::Instance()->IsFlagSet("--add1pixel")) { frameRects[k].dx++; frameRects[k].dy++; } else if (CommandLineParser::Instance()->IsFlagSet("--add2pixel")) { frameRects[k].dx+=2; frameRects[k].dy+=2; } else if (CommandLineParser::Instance()->IsFlagSet("--add4pixel")) { frameRects[k].dx+=4; frameRects[k].dy+=4; }else { frameRects[k].dx++; frameRects[k].dy++; } } fclose(fp); return true; }