bool writeImage(const std::string& path, Img& img) { if (endsWith(path, ".ptx")) { // make sure it's a power of two if (!checkPowerOfTwo(img)) return 0; // write ptx face-zero image std::string error; PtexWriter* ptx = PtexWriter::open(path.c_str(), Ptex::mt_quad, img.dt, img.nchan, img.achan, 1, error); if (!ptx) { std::cerr << error << std::endl; return 0; } ptx->setBorderModes(opt.uMode, opt.vMode); // write image top-down (flipped) int rowlen = img.w * img.nchan * Ptex::DataSize(img.dt); char* toprow = (char*) img.data + (img.h-1) * rowlen; Ptex::Res res(PtexUtils::floor_log2(img.w), PtexUtils::floor_log2(img.h)); int adjfaces[4], adjedges[4]; if (opt.uMode == Ptex::m_periodic) { adjfaces[0] = 0; adjfaces[2] = 0; adjedges[0] = 2; adjedges[2] = 0; } else { adjfaces[0] = -1; adjfaces[2] = -1; adjedges[0] = 0; adjedges[2] = 0; } if (opt.vMode == Ptex::m_periodic) { adjfaces[1] = 0; adjfaces[3] = 0; adjedges[1] = 3; adjedges[3] = 1; } else { adjfaces[1] = -1; adjfaces[3] = -1; adjedges[1] = 0; adjedges[3] = 0; } Ptex::FaceInfo finfo(res, adjfaces, adjedges); ptx->writeFace(0, finfo, toprow, -rowlen); // write meta data for (std::map<std::string,std::string>::iterator iter = opt.meta.begin(), end = opt.meta.end(); iter != end; iter++) { ptx->writeMeta(iter->first.c_str(), iter->second.c_str()); } bool ok = ptx->close(error); if (!ok) { std::cerr << error << std::endl; } ptx->release(); return ok; } else { return img.save(path); } }
bool writeEnvcube(const std::string& path, Img images[6]) { if (endsWith(path, ".env")) { std::cerr << "Writing prman envcube files (.env) not yet supported: " << path << "\n"; return 0; } if (!endsWith(path, ".penv")) { std::cerr << "Unsupported envcube file format: " << path << "\n"; return 0; } // check that all faces have the same format, and power-of-two size Ptex::DataType dt = images[0].dt; int nchan = images[0].nchan; int achan = images[0].achan; for (int i = 1; i < 6; i++) { if (images[i].dt != dt || images[i].nchan != nchan || images[i].achan != achan) { std::cerr << "Cube face image format mismatch\n"; return 0; } if (!checkPowerOfTwo(images[i])) return 0; } // build face info int adjfaces[6][4] = { { 3, 5, 2, 4 }, // px { 3, 4, 2, 5 }, // nx { 4, 0, 5, 1 }, // py { 5, 0, 4, 1 }, // ny { 3, 0, 2, 1 }, // pz { 3, 1, 2, 0 } // nz }; int adjedges[6][4] = { { 1, 3, 1, 1 }, // px { 3, 3, 3, 1 }, // nx { 2, 2, 2, 2 }, // py { 0, 0, 0, 0 }, // ny { 2, 3, 0, 1 }, // pz { 0, 3, 2, 1 } // nz }; Ptex::FaceInfo fi[6]; for (int i = 0; i < 6; i++) { int w = images[i].w, h = images[i].h; Ptex::Res res(PtexUtils::floor_log2(w), PtexUtils::floor_log2(h)); fi[i] = Ptex::FaceInfo(res, adjfaces[i], adjedges[i]); } // write file std::string error; PtexWriter* w = PtexWriter::open(opt.dst.c_str(), Ptex::mt_quad, dt, nchan, achan, 6, error); if (!w) { std::cerr << error << std::endl; return 0; } for (int i = 0; i < 6; i++) { w->writeFace(i, fi[i], images[i].data); } bool ok = w->close(error); if (!ok) std::cerr << error << "\n"; w->release(); return ok; }
int main(int /*argc*/, char** /*argv*/) { static Ptex::Res res[] = { Ptex::Res(8,7), Ptex::Res(1,2), Ptex::Res(3,1), Ptex::Res(5,4), Ptex::Res(9,8), Ptex::Res(2,4), Ptex::Res(6,2), Ptex::Res(7,4), Ptex::Res(2,1)}; static int adjedges[][4] = {{ 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }, { 2, 3, 0, 1 }}; static int adjfaces[][4] ={{ 3, 1, -1, -1 }, { 4, 2, -1, 0 }, { 5, -1, -1, 1 }, { 6, 4, 0, -1 }, { 7, 5, 1, 3 }, { 8, -1, 2, 4 }, { -1, 7, 3, -1 }, { -1, 8, 4, 6 }, { -1, -1, 5, 7 }}; int nfaces = sizeof(res)/sizeof(res[0]); Ptex::DataType dt = Ptex::dt_half; #define DTYPE PtexHalf int alpha = -1; int nchan = 3; Ptex::String error; PtexWriter* w = PtexWriter::open("test.ptx", Ptex::mt_quad, dt, nchan, alpha, nfaces, error); if (!w) { std::cerr << error.c_str() << std::endl; return 1; } int size = 0; for (int i = 0; i < nfaces; i++) size = std::max(size, res[i].size()); size *= Ptex::DataSize(dt) * nchan; void* buff = malloc(size); for (int i = 0; i < nfaces; i++) { memset(buff, 0, size); DTYPE* fbuff = (DTYPE*)buff; int ures = res[i].u(), vres = res[i].v(); for (int v = 0; v < vres; v++) { for (int u = 0; u < ures; u++) { float c = (u ^ v) & 1; fbuff[(v*ures+u)*nchan] = u/float(ures-1); fbuff[(v*ures+u)*nchan+1] = v/float(vres-1); fbuff[(v*ures+u)*nchan+2] = c; } } w->writeFace(i, Ptex::FaceInfo(res[i], adjfaces[i], adjedges[i]), buff); } free(buff); char* sval = "a str val"; int ndvals = 3; double dvals_buff[3] = { 1.1,2.2,3.3 }; double* dvals = dvals_buff; int nivals = 4; int16_t ivals[4] = { 2, 4, 6, 8 }; char* xval = 0; writeMeta(w, sval, dvals, ndvals, ivals, nivals, xval); if (!w->close(error)) { std::cerr << error.c_str() << std::endl; return 1; } w->release(); if (!checkMeta("test.ptx", sval, dvals, ndvals, ivals, nivals, xval)) return 1; // add some incremental edits w = PtexWriter::edit("test.ptx", true, Ptex::mt_quad, dt, nchan, alpha, nfaces, error); sval = "a string value"; dvals[2] = 0; writeMeta(w, sval, dvals, ndvals, 0, 0, 0); if (!w->close(error)) { std::cerr << error.c_str() << std::endl; return 1; } w->release(); if (!checkMeta("test.ptx", sval, dvals, ndvals, ivals, nivals, xval)) return 1; // add some non-incremental edits, including some large meta data ndvals = 500; dvals = (double*)malloc(ndvals * sizeof(dvals[0])); for (int i = 0; i < ndvals; i++) dvals[i] = i; w = PtexWriter::edit("test.ptx", false, Ptex::mt_quad, dt, nchan, alpha, nfaces, error); xval = "another string value"; writeMeta(w, 0, dvals, ndvals, 0, 0, xval); if (!w->close(error)) { std::cerr << error.c_str() << std::endl; return 1; } w->release(); if (!checkMeta("test.ptx", sval, dvals, ndvals, ivals, nivals, xval)) return 1; return 0; }