int _tmain(int argc, _TCHAR* argv[]) { #else int main(int argc, char **argv) { #endif if(argc != 2 && argc != 3) { fprintf(stderr, "Usage: sc <img1>\n"); return 1; } int spSize = 5; if(argc == 3) { sscanf(argv[2], "%d", &spSize); } ImageFile imgFile (argv[1]); if(!imgFile.Load()) { fprintf(stderr, "Error loading file: %s\n", argv[1]); return 1; } FasTC::Image<> *img = imgFile.GetImage(); const int kWidth = img->GetWidth(); const int kHeight = img->GetHeight(); const int nPixels = kWidth * kHeight; const uint32 pixelBufSz = nPixels * sizeof(FasTC::Pixel); FasTC::Pixel *pixels = new FasTC::Pixel[pixelBufSz]; memcpy(pixels, img->GetPixels(), pixelBufSz); uint32 *rawPixels = new uint32[kWidth * kHeight]; for(int i = 0; i < nPixels; i++) { // Pixels are stored as little endian ARGB, so we want ABGR pixels[i].Shuffle(0x6C); // 01 10 11 00 rawPixels[i] = pixels[i].Pack(); } int *labels = new int[nPixels]; int numLabels; SLIC slic; slic.PerformSLICO_ForGivenStepSize( rawPixels, kWidth, kHeight, labels, numLabels, spSize, 1.0); std::unordered_map<uint32, Region> regions; CollectPixels(kWidth, kHeight, pixels, labels, regions); std::cout << "Num regions: " << regions.size() << std::endl; for(auto &r : regions) { r.second.Compress(); r.second.Reconstruct(); } for(int i = 0; i < nPixels; i++) { pixels[i] = regions[labels[i]].GetNextPixel(); pixels[i].Shuffle(0x6C); } std::vector<Partition<4, 4> > partitions; EnumerateBPTC(partitions); std::cout << partitions.size() << " 4x4 BPTC partitions" << std::endl; VpTree<Partition<4, 4>, Partition<4, 4>::Distance> vptree; vptree.create(partitions); // Just to test, find the partition close to half 0 half 1.. Partition<4, 4> test; for(uint32 i = 0; i < 16; i++) { if(i < 8) { test[i] = 0; } else { test[i] = 1; } } vector<Partition<4, 4> > closest; vptree.search(test, 1, &closest, NULL); std::cout << closest[0].GetIndex() << std::endl; BPTCC::CompressionSettings settings; settings.m_NumSimulatedAnnealingSteps = 0; settings.m_ShapeSelectionFn = ChosePresegmentedShape<4, 4>; SelectionInfo info(vptree, labels, kWidth, kHeight); settings.m_ShapeSelectionUserData = &info; uint8 *outBuf = new uint8[kWidth * kHeight]; FasTC::CompressionJob cj( FasTC::eCompressionFormat_BPTC, reinterpret_cast<const uint8 *>(pixels), outBuf, static_cast<uint32>(kWidth), static_cast<uint32>(kHeight)); StopWatch sw; sw.Start(); BPTCC::Compress(cj, settings); sw.Stop(); std::cout << "Compression time: " << sw.TimeInMilliseconds() << "ms" << std::endl; CompressedImage ci(kWidth, kHeight, FasTC::eCompressionFormat_BPTC, outBuf); FasTC::Image<> outImg(kWidth, kHeight, pixels); std::cout << "PSNR: " << outImg.ComputePSNR(&ci) << "db" << std::endl; ImageFile outImgFile("out.png", eFileFormat_PNG, outImg); outImgFile.Write(); delete [] labels; delete [] rawPixels; delete [] pixels; return 0; }
int main(int argc, char **argv) { int fileArg = 1; if(fileArg == argc) { PrintUsage(); exit(1); } char decompressedOutput[256]; decompressedOutput[0] = '\0'; bool bNoDecompress = false; int numJobs = 0; int quality = 50; int numThreads = 1; int numCompressions = 1; bool bUseSIMD = false; bool bSaveLog = false; bool bUseAtomics = false; bool bUsePVRTexLib = false; bool bUseNVTT = false; bool bVerbose = false; FasTC::ECompressionFormat format = FasTC::eCompressionFormat_BPTC; bool knowArg = false; do { knowArg = false; if(strcmp(argv[fileArg], "-n") == 0) { fileArg++; if(fileArg == argc || (numCompressions = atoi(argv[fileArg])) < 0) { PrintUsage(); exit(1); } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-f") == 0) { fileArg++; if(fileArg == argc) { PrintUsage(); exit(1); } else { if(!strcmp(argv[fileArg], "PVRTC")) { format = FasTC::eCompressionFormat_PVRTC4; } else if(!strcmp(argv[fileArg], "PVRTCLib")) { format = FasTC::eCompressionFormat_PVRTC4; bUsePVRTexLib = true; } else if(!strcmp(argv[fileArg], "BPTCLib")) { format = FasTC::eCompressionFormat_BPTC; bUseNVTT = true; } else if(!strcmp(argv[fileArg], "ETC1")) { format = FasTC::eCompressionFormat_ETC1; } else if(!strcmp(argv[fileArg], "DXT1")) { format = FasTC::eCompressionFormat_DXT1; } else if(!strcmp(argv[fileArg], "DXT5")) { format = FasTC::eCompressionFormat_DXT5; } } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-d") == 0) { fileArg++; if(fileArg == argc) { PrintUsage(); exit(1); } else { size_t sz = 255; sz = ::std::min(sz, static_cast<size_t>(strlen(argv[fileArg]))); memcpy(decompressedOutput, argv[fileArg], sz + 1); } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-nd") == 0) { fileArg++; bNoDecompress = true; knowArg = true; continue; } if(strcmp(argv[fileArg], "-l") == 0) { fileArg++; bSaveLog = true; knowArg = true; continue; } if(strcmp(argv[fileArg], "-v") == 0) { fileArg++; bVerbose = true; knowArg = true; continue; } if(strcmp(argv[fileArg], "-simd") == 0) { fileArg++; bUseSIMD = true; knowArg = true; continue; } if(strcmp(argv[fileArg], "-t") == 0) { fileArg++; if(fileArg == argc || (numThreads = atoi(argv[fileArg])) < 1) { PrintUsage(); exit(1); } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-q") == 0) { fileArg++; if(fileArg == argc || (quality = atoi(argv[fileArg])) < 0) { PrintUsage(); exit(1); } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-j") == 0) { fileArg++; if(fileArg == argc || (numJobs = atoi(argv[fileArg])) < 0) { PrintUsage(); exit(1); } fileArg++; knowArg = true; continue; } if(strcmp(argv[fileArg], "-a") == 0) { fileArg++; bUseAtomics = true; knowArg = true; continue; } } while(knowArg && fileArg < argc); if(fileArg == argc) { PrintUsage(); exit(1); } char basename[256]; ExtractBasename(argv[fileArg], basename, 256); ImageFile file (argv[fileArg]); if(!file.Load()) { fprintf(stderr, "Error loading file: %s\n", argv[fileArg]); return 1; } FasTC::Image<> img(*file.GetImage()); if(bVerbose) { fprintf(stdout, "Entropy: %.5f\n", img.ComputeEntropy()); fprintf(stdout, "Mean Local Entropy: %.5f\n", img.ComputeMeanLocalEntropy()); } std::ofstream logFile; ThreadSafeStreambuf streamBuf(logFile); std::ostream logStream(&streamBuf); if(bSaveLog) { char logname[256]; sprintf(logname, "%s.log", basename); logFile.open(logname); } SCompressionSettings settings; settings.format = format; settings.bUseSIMD = bUseSIMD; settings.bUseAtomics = bUseAtomics; settings.iNumThreads = numThreads; settings.iQuality = quality; settings.iNumCompressions = numCompressions; settings.iJobSize = numJobs; settings.bUsePVRTexLib = bUsePVRTexLib; settings.bUseNVTT = bUseNVTT; if(bSaveLog) { settings.logStream = &logStream; } else { settings.logStream = NULL; } CompressedImage *ci = CompressImage(&img, settings); if(NULL == ci) { fprintf(stderr, "Error compressing image!\n"); return 1; } double PSNR = img.ComputePSNR(ci); if(PSNR > 0.0) { fprintf(stdout, "PSNR: %.3f\n", PSNR); } else { fprintf(stderr, "Error computing PSNR\n"); } if(bVerbose) { double SSIM = img.ComputeSSIM(ci); if(SSIM > 0.0) { fprintf(stdout, "SSIM: %.9f\n", SSIM); } else { fprintf(stderr, "Error computing SSIM\n"); } } if(!bNoDecompress) { if(decompressedOutput[0] != '\0') { memcpy(basename, decompressedOutput, 256); } else if(format == FasTC::eCompressionFormat_BPTC) { strcat(basename, "-bptc.png"); } else if(format == FasTC::eCompressionFormat_PVRTC4) { strcat(basename, "-pvrtc-4bpp.png"); } else if(format == FasTC::eCompressionFormat_DXT1) { strcat(basename, "-dxt1.png"); } else if(format == FasTC::eCompressionFormat_ETC1) { strcat(basename, "-etc1.png"); } EImageFileFormat fmt = ImageFile::DetectFileFormat(basename); ImageFile cImgFile (basename, fmt, *ci); cImgFile.Write(); } // Cleanup delete ci; if(bSaveLog) { logFile.close(); } return 0; }