Go to the documentation of this file.
   84         static std::string tmpdir;
 
   85         static int initialized = 0;
 
   90             DWORD result = ::GetTempPath(0, (LPTSTR) L
"");
 
   92                 std::vector<TCHAR> tempPath(result + 1);
 
   93                 result = ::GetTempPath(
static_cast<DWORD
>(tempPath.size()), &tempPath[0]);
 
   94                 if (result > 0 && result <= tempPath.size())
 
   95                     tmpdir = std::string(tempPath.begin(),
 
   96                                          tempPath.begin() + 
static_cast<std::size_t
>(result));
 
  102             const char* t = getenv(
"TEMP");
 
  103             if (!t) t = getenv(
"TMP");
 
  114         static int count = 0;
 
  115         s << tmpdir << 
"/" << 
"PtexTmp" << _getpid() << 
"_" << ++count;
 
  117         return fopen((
char*) tmppath.c_str(), 
"wb+");
 
  120         tmppath = tmpdir + 
"/PtexTmpXXXXXX";
 
  121         int fd = mkstemp(&tmppath[0]);
 
  122         return fdopen(fd, 
"w+");
 
  126     std::string 
fileError(
const char* message, 
const char* path)
 
  128         std::stringstream str;
 
  129         str << message << path << 
"\n" << strerror(errno);
 
  138             error = 
"PtexWriter doesn't currently support big-endian cpu's";
 
  143             error = 
"PtexWriter error: Invalid mesh type";
 
  148             error = 
"PtexWriter error: Invalid data type";
 
  152         if (nchannels <= 0) {
 
  153             error = 
"PtexWriter error: Invalid number of channels";
 
  157         if (alphachan != -1 && (alphachan < 0 || alphachan >= nchannels)) {
 
  158             error = 
"PtexWriter error: Invalid alpha channel";
 
  169                              int nchannels, 
int alphachan, 
int nfaces,
 
  172     if (!
checkFormat(mt, dt, nchannels, alphachan, error))
 
  176                                            mt, dt, nchannels, alphachan, nfaces,
 
  188                              int nchannels, 
int alphachan, 
int nfaces,
 
  191     if (!
checkFormat(mt, dt, nchannels, alphachan, error))
 
  195     FILE* fp = fopen(path, 
"rb+");
 
  196     if (!fp && errno != ENOENT) {
 
  197         error = 
fileError(
"Can't open ptex file for update: ", path).c_str();
 
  202     if (incremental && fp) {
 
  203         w = 
new PtexIncrWriter(path, fp, mt, dt, nchannels, alphachan, nfaces);
 
  217             bool headerMatch = (mt == tex->
meshType() &&
 
  223                 std::stringstream str;
 
  224                 str << 
"PtexWriter::edit error: header doesn't match existing file, " 
  225                     << 
"conversions not currently supported";
 
  226                 error = str.str().
c_str();
 
  255         if (!w->
close(error)) 
return 0;
 
  263                                int nchannels, 
int alphachan, 
int nfaces,
 
  290     deflateInit(&
_zstream, compress ? Z_DEFAULT_COMPRESSION : 0);
 
  306         std::cerr << error.
c_str() << std::endl;
 
  332         setError(
"PtexWriter error: faceid out of range");
 
  337         setError(
"PtexWriter error: asymmetric face res not supported for triangle textures");
 
  352         f.flags &= FaceInfo::flag_subface;
 
  356     f.flags |= (uint8_t)flags;
 
  400     for (
int i = 0; i < nkeys; i++) {
 
  403         data->
getKey(i, key, type);
 
  422                 const int16_t* val=0;
 
  429                 const int32_t* val=0;
 
  454                                  const void* value, 
int size)
 
  456     if (strlen(key) > 255) {
 
  457         std::stringstream str;
 
  458         str << 
"PtexWriter error: meta data key too long (max=255) \"" << key << 
"\"";
 
  463         std::stringstream str;
 
  464         str << 
"PtexWriter error: meta data size <= 0 for \"" << key << 
"\"";
 
  467     std::map<std::string,int>::iterator iter = 
_metamap.find(key);
 
  471         index = iter->second;
 
  483     memcpy(&m.
data[0], value, size);
 
  502     if (!fwrite(data, size, 1, fp)) {
 
  503         setError(
"PtexWriter error: file write failed");
 
  514     _zstream.next_in = (Bytef*) 
const_cast<void*
>(data);
 
  520         int zresult = deflate(&
_zstream, finishArg ? Z_FINISH : Z_NO_FLUSH);
 
  522         if (sizeval > 0) 
writeBlock(fp, buff, sizeval);
 
  523         if (zresult == Z_STREAM_END) 
break;
 
  524         if (zresult != Z_OK) {
 
  525             setError(
"PtexWriter error: data compression internal error");
 
  528         if (!finishArg && 
_zstream.avail_out != 0)
 
  533     if (!finishArg) 
return 0;
 
  535     int total = (int)
_zstream.total_out;
 
  543     if (!fread(data, size, 1, fp)) {
 
  544         setError(
"PtexWriter error: temp file read failed");
 
  553     if (size <= 0) 
return 0;
 
  554     fseeko(src, pos, SEEK_SET);
 
  559         if (!fread(buff, nbytes, 1, src)) {
 
  560             setError(
"PtexWriter error: temp file read failed");
 
  575     if (ntileslog2 == 0) 
return faceres;
 
  581     int n = faceres.ulog2 + faceres.vlog2 - ntileslog2;
 
  586     tileres.ulog2 = (int8_t)
PtexUtils::min(
int((n+1)/2), int(faceres.ulog2));
 
  587     tileres.vlog2 = (int8_t)
PtexUtils::min(
int(n - tileres.ulog2), int(faceres.vlog2));
 
  607     int ures = res.u(), vres = res.v();
 
  610     char* buff = useNew ? 
new char [blockSize] : (
char*)alloca(blockSize);
 
  625     if (useNew) 
delete [] buff;
 
  634     int ntilesu = res.ntilesu(tileres);
 
  635     int ntilesv = res.ntilesv(tileres);
 
  636     int ntiles = ntilesu * ntilesv;
 
  645         std::vector<FaceDataHeader> tileHeader(ntiles);
 
  646         int tileures = tileres.u();
 
  647         int tilevres = tileres.v();
 
  649         int tilevstride = tilevres*stride;
 
  654         const char* rowp = (
const char*) data;
 
  655         const char* rowpend = rowp + ntilesv * tilevstride;
 
  656         for (; rowp != rowpend; rowp += tilevstride) {
 
  657             const char* p = rowp;
 
  658             const char* pend = p + ntilesu * tileustride;
 
  659             for (; p != pend; tdh++, p += tileustride) {
 
  676         totalsize += 
writeBlock(fp, &tileres, 
sizeof(Res));
 
  677         totalsize += 
writeBlock(fp, &tileheadersize, 
sizeof(tileheadersize));
 
  693     Ptex::Res newres((int8_t)(res.ulog2-1), (int8_t)(res.vlog2-1));
 
  696     char* buff = useNew ? 
new char [buffsize] : (
char*)alloca(buffsize);
 
  702     if (useNew) 
delete [] buff;
 
  709     uint8_t keysize = uint8_t(val.
key.size()+1);
 
  711     uint32_t datasize = uint32_t(val.
data.size());
 
  717     int memsize = int(
sizeof(keysize) + (
size_t)keysize + 
sizeof(
datatype)
 
  718                    + 
sizeof(datasize) + datasize);
 
  725                                int nchannels, 
int alphachan, 
int nfaces, 
bool genmipmaps)
 
  729       _genmipmaps(genmipmaps),
 
  746     for (
int i = 0; i < nfaces; i++) 
_faceinfo[i].flags = uint8_t(-1);
 
  748     _levels.front().pos.resize(nfaces);
 
  749     _levels.front().fdh.resize(nfaces);
 
  750     _rpos.resize(nfaces);
 
  796         unlink(
_path.c_str());
 
  798             error = 
fileError(
"Can't write to ptex file: ", 
_path.c_str()).c_str();
 
  811     if (stride == 0) stride = f.res.u()*
_pixelSize;
 
  833         int rowlen = f.res.u() * 
_pixelSize, nrows = f.res.v();
 
  834         temp = 
new uint8_t [rowlen * nrows];
 
  857     if (temp) 
delete [] temp;
 
  908                     char* data = 
new char [size];
 
  920                 _faceinfo[i].flags = FaceInfo::flag_constant;
 
  936     FILE* newfp = fopen(
_newpath.c_str(), 
"wb+");
 
  954     FilePos levelInfoPos = ftello(newfp);
 
  963         int nfaces = int(level.
fdh.size());
 
  970         for (
int fi = 0; fi < nfaces; fi++)
 
  972                                             level.
fdh[fi].blocksize());
 
  985     fseeko(newfp, levelInfoPos, SEEK_SET);
 
  989     fseeko(newfp, 0, SEEK_SET);
 
  999     for (
int faceid = 0, n = 
int(
_faceinfo.size()); faceid < n; faceid++) {
 
 1001         if (!f.isConstant()) 
continue;
 
 1005         bool isConst = 
true;
 
 1007         int nedges = isTriangle ? 3 : 4;
 
 1008         for (
int eid = 0; isConst && (eid < nedges); eid++) {
 
 1009             bool prevWasSubface = f.isSubface();
 
 1010             int prevFid = faceid;
 
 1013             int afid = f.adjface(eid);
 
 1014             int aeid = f.adjedge(eid);
 
 1016             const int maxcount = 10; 
 
 1017             while (afid != faceid && afid >= 0 && ++count < maxcount) {
 
 1020                 if (!af.isConstant() ||
 
 1022                 { isConst = 
false; 
break; }
 
 1025                 bool isSubface = af.isSubface();
 
 1026                 bool isT = !isTriangle && prevWasSubface && !isSubface && af.adjface(aeid) == prevFid;
 
 1028                 prevWasSubface = isSubface;
 
 1032                 aeid = (aeid + 1) % nedges;
 
 1033                 afid = af.adjface(aeid);
 
 1034                 aeid = af.adjedge(aeid);
 
 1045                     aeid = (aeid - 1 + nedges) % nedges;
 
 1046                     afid = f.adjface(aeid);
 
 1047                     aeid = f.adjedge(aeid);
 
 1049                     while (afid != faceid && afid >= 0 && ++count < maxcount) {
 
 1052                         if (!af.isConstant() ||
 
 1054                         { isConst = 
false; 
break; }
 
 1058                         aeid = (aeid - 1 + nedges) % nedges;
 
 1059                         afid = af.adjface(aeid);
 
 1060                         aeid = af.adjedge(aeid);
 
 1063                         bool isSubface = af.isSubface();
 
 1064                         if (isSubface && !prevWasSubface) {
 
 1065                             aeid = (aeid + 3) % 4;
 
 1066                             afid = af.adjface(aeid);
 
 1067                             aeid = (af.adjedge(aeid) + 3) % 4;
 
 1069                         prevWasSubface = isSubface;
 
 1074         if (isConst) f.flags |= FaceInfo::flag_nbconstant;
 
 1091     for (
int rfaceid = nfaces-1, cutoffres = 
MinReductionLog2; rfaceid >= 0; rfaceid--) {
 
 1096         while (
min > cutoffres) {
 
 1098             int size = rfaceid+1;
 
 1101             level.
pos.resize(size);
 
 1102             level.
fdh.resize(size);
 
 1110     for (
int i = 0; i < nfaces; i++)
 
 1113     char* buff = 
new char [buffsize];
 
 1115     int nlevels = int(
_levels.size());
 
 1116     for (
int i = 1; i < nlevels; i++) {
 
 1118         int nextsize = (i+1 < nlevels)? 
int(
_levels[i+1].fdh.size()) : 0;
 
 1119         for (
int rfaceid = 0, size = 
int(level.
fdh.size()); rfaceid < size; rfaceid++) {
 
 1123             res.ulog2 = (int8_t)(res.ulog2 - i);
 
 1124             res.vlog2 = (int8_t)(res.vlog2 - i);
 
 1129             fseeko(
_tmpfp, 0, SEEK_END);
 
 1135             if (rfaceid < nextsize) {
 
 1145     fseeko(
_tmpfp, 0, SEEK_END);
 
 1152     std::vector<MetaEntry*> lmdEntries; 
 
 1155     for (
int i = 0, n = (
int)
_metadata.size(); i < n; i++) {
 
 1157 #ifndef PTEX_NO_LARGE_METADATA_BLOCKS 
 1160             lmdEntries.push_back(&e);
 
 1178     int nLmd = (int)lmdEntries.size();
 
 1181         std::vector<FilePos> lmdoffset(nLmd);
 
 1182         std::vector<uint32_t> lmdzipsize(nLmd);
 
 1183         for (
int i = 0; i < nLmd; i++) {
 
 1185             lmdoffset[i] = ftello(
_tmpfp);
 
 1190         for (
int i = 0; i < nLmd; i++) {
 
 1192             uint8_t keysize = uint8_t(e->
key.size()+1);
 
 1194             uint32_t datasize = (uint32_t)e->
data.size();
 
 1195             uint32_t zipsize = lmdzipsize[i];
 
 1203                 (uint32_t)(
sizeof(keysize) + (size_t)keysize + 
sizeof(
datatype) +
 
 1204                            sizeof(datasize) + 
sizeof(zipsize));
 
 1209         for (
int i = 0; i < nLmd; i++) {
 
 1219                                int nchannels, 
int alphachan, 
int nfaces)
 
 1232         std::stringstream str;
 
 1233         str << 
"Not a ptex file: " << path;
 
 1244         std::stringstream str;
 
 1245         str << 
"PtexWriter::edit error: header doesn't match existing file, " 
 1246             << 
"conversions not currently supported";
 
 1254         std::stringstream str;
 
 1255         str << 
"Error reading extended header: " << path;
 
 1261     fseeko(
_fp, 0, SEEK_END);
 
 1272     if (stride == 0) stride = f.res.u()*
_pixelSize;
 
 1290     writeBlank(
_fp, 
sizeof(edittype) + 
sizeof(editsize) + 
sizeof(efdh));
 
 1293     uint8_t* constval = 
new uint8_t [
_pixelSize];
 
 1298         int rowlen = f.res.u() * 
_pixelSize, nrows = f.res.v();
 
 1299         uint8_t* temp = 
new uint8_t [rowlen * nrows];
 
 1329     fseeko(
_fp, pos, SEEK_SET);
 
 1333     fseeko(
_fp, 0, SEEK_END);
 
 1346     editsize = (uint32_t)
sizeof(efdh) + 
_pixelSize;
 
 1373     writeBlank(
_fp, 
sizeof(edittype) + 
sizeof(editsize) + 
sizeof(emdh));
 
 1376     for (
size_t i = 0, n = 
_metadata.size(); i < n; i++) {
 
 1387     fseeko(
_fp, pos, SEEK_SET);
 
 1391     fseeko(
_fp, 0, SEEK_END);
 
  
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
bool storeFaceInfo(int faceid, FaceInfo &dest, const FaceInfo &src, int flags=0)
Res calcTileRes(Res faceres)
virtual bool writeFace(int faceid, const FaceInfo &f, const void *data, int stride)
virtual void writeMeta(const char *key, const char *value)
Write a string as meta data.
std::map< std::string, int > _metamap
Pixel resolution of a given texture.
std::vector< LevelRec > _levels
bool checkFormat(Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, Ptex::String &error)
@ mdt_int32
Signed 32-bit integer.
virtual Ptex::BorderMode vBorderMode()=0
Mode for filtering texture access beyond mesh border.
void writeReduction(FILE *fp, const void *data, int stride, Res res)
virtual int numChannels()=0
Number of channels stored in file.
void writeConstFaceBlock(FILE *fp, const void *data, FaceDataHeader &fdh)
#define PTEX_NAMESPACE_END
void deinterleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
virtual int alphaChannel()=0
Index of alpha channel (if any).
#define PtexFileMinorVersion
void getError(Ptex::String &error)
@ dt_float
Single-precision (32-bit) floating point.
std::vector< uint32_t > _faceids_r
virtual ~PtexWriterBase()
bool ok(Ptex::String &error)
@ m_clamp
texel access is clamped to border
int writeZipBlock(FILE *fp, const void *data, int size, bool finish=true)
int DataSize(DataType dt)
Look up size of given data type (in bytes).
int writeMetaDataBlock(FILE *fp, MetaEntry &val)
Automatically acquire and release lock within enclosing scope.
virtual bool hasEdits()=0
True if the file has edit blocks.
virtual bool close(Ptex::String &error)
Close the file.
virtual void setBorderModes(Ptex::BorderMode uBorderMode, Ptex::BorderMode vBorderMode)
Set border modes.
static const int MinReductionLog2
@ mdt_double
Double-precision (32-bit) floating point.
void writeFaceData(FILE *fp, const void *data, int stride, Res res, FaceDataHeader &fdh)
void generateReductions()
std::vector< FilePos > _rpos
DataType
Type of data stored in texture file.
virtual Ptex::MeshType meshType()=0
Type of mesh for which texture data is defined.
@ mdt_int8
Signed 8-bit integer.
Information about a face, as stored in the Ptex file header.
void storeConstValue(int faceid, const void *data, int stride, Res res)
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
virtual bool close(Ptex::String &error)=0
Close the file.
#define PtexFileMajorVersion
static bool applyEdits(const char *path, Ptex::String &error)
Apply edits to a file.
virtual int numFaces()=0
Number of faces stored in file.
std::vector< FaceDataHeader > fdh
@ dt_uint16
Unsigned, 16-bit integer.
int copyBlock(FILE *dst, FILE *src, FilePos pos, int size)
bool isConstant() const
Determine if face is constant (by checking a flag).
virtual bool hasMipMaps()=0
True if the file has mipmaps.
@ dt_uint8
Unsigned, 8-bit integer.
std::vector< uint8_t > _constdata
virtual bool writeFace(int faceid, const FaceInfo &f, const void *data, int stride)
PtexMainWriter(const char *path, PtexTexture *tex, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, bool genmipmaps)
virtual bool writeConstantFace(int faceid, const FaceInfo &f, const void *data)
virtual bool hasEdits()
True if the file has edit blocks.
static PtexWriter * edit(const char *path, bool incremental, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, Ptex::String &error, bool genmipmaps=true)
Open an existing texture file for writing.
virtual ~PtexIncrWriter()
PtexIncrWriter(const char *path, FILE *fp, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces)
void flagConstantNeighorhoods()
virtual ~PtexMainWriter()
Interface for writing data to a ptex file.
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
@ mt_triangle
Mesh is triangle-based.
MetaDataType
Type of meta data entry.
std::string fileError(const char *message, const char *path)
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
int writeBlank(FILE *fp, int size)
Smart-pointer for acquiring and releasing API objects.
DataType datatype() const
void setError(const std::string &error)
Interface for reading data from a ptex file.
FILE * OpenTempFile(std::string &tmppath)
virtual void setEdgeFilterMode(Ptex::EdgeFilterMode edgeFilterMode)
Set edge filter mode.
std::vector< MetaEntry > _metadata
@ mdt_string
Null-terminated string.
int size() const
Total size of specified texture in texels (u * v).
virtual Ptex::BorderMode uBorderMode()=0
Mode for filtering texture access beyond mesh border.
virtual void addMetaData(const char *key, MetaDataType t, const void *value, int size)
void writeMetaData(FILE *fp)
int u() const
U resolution in texels.
uint32_t floor_log2(uint32_t x)
std::vector< FilePos > pos
virtual bool close(Ptex::String &error)
Close the file.
const int MetaDataThreshold
virtual void * getData()=0
Access the data from this data block.
std::vector< uint32_t > _rfaceids
virtual Ptex::EdgeFilterMode edgeFilterMode()=0
Mode for filtering textures across edges.
bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
int writeBlock(FILE *fp, const void *data, int size)
int readBlock(FILE *fp, void *data, int size)
void average(const void *src, int sstride, int uw, int vw, void *dst, DataType dt, int nchan)
@ mdt_int16
Signed 16-bit integer.
virtual PtexMetaData * getMetaData()
Access meta data.
std::vector< uint8_t > data
virtual Ptex::DataType dataType()=0
Type of data stored in file.
void writeFaceBlock(FILE *fp, const void *data, int stride, Res res, FaceDataHeader &fdh)
Res res
Resolution of face.
PtexUtils::ReduceFn * _reduceFn
@ mdt_float
Single-precision (32-bit) floating point.
Public API classes for reading, writing, caching, and filtering Ptex files.
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
@ mt_quad
Mesh is quad-based.
PtexWriterBase(const char *path, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, bool compress)
const char * c_str() const
virtual bool writeConstantFace(int faceid, const FaceInfo &f, const void *data)
static PtexWriter * open(const char *path, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, Ptex::String &error, bool genmipmaps=true)
Open a new texture file for writing.
MeshType
Type of base mesh for which the textures are defined.
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
std::vector< FaceInfo > _faceinfo
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
virtual bool close(Ptex::String &error)
Close the file.
void reduce(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void encodeDifference(void *data, int size, DataType dt)