77     FILE* OpenTempFile(std::string& tmppath)
 
   83         static std::string tmpdir;
 
   84         static int initialized = 0;
 
   89             DWORD result = ::GetTempPath(0, (LPTSTR) L
"");
 
   91                 std::vector<TCHAR> tempPath(result + 1);
 
   92                 result = ::GetTempPath(static_cast<DWORD>(tempPath.size()), &tempPath[0]);
 
   93                 if (result > 0 && result <= tempPath.size())
 
   94                     tmpdir = std::string(tempPath.begin(), 
 
   95                                          tempPath.begin() + 
static_cast<std::size_t
>(result));
 
  101             const char* t = getenv(
"TEMP");
 
  102             if (!t) t = getenv(
"TMP");
 
  113         static int count = 0;
 
  114         s << tmpdir << 
"/" << 
"PtexTmp" << _getpid() << 
"_" << ++count;
 
  116         return fopen((
char*) tmppath.c_str(), 
"wb+");
 
  119         tmppath = tmpdir + 
"/PtexTmpXXXXXX";
 
  120         int fd = mkstemp((
char*) tmppath.c_str());
 
  121         return fdopen(fd, 
"w+");
 
  125     std::string fileError(
const char* message, 
const char* path)
 
  127         std::stringstream str;
 
  128         str << message << path << 
"\n" << strerror(errno);
 
  137             error = 
"PtexWriter doesn't currently support big-endian cpu's";
 
  142             error = 
"PtexWriter error: Invalid mesh type";
 
  147             error = 
"PtexWriter error: Invalid data type";
 
  151         if (nchannels <= 0) {
 
  152             error = 
"PtexWriter error: Invalid number of channels";
 
  156         if (alphachan != -1 && (alphachan < 0 || alphachan >= nchannels)) {
 
  157             error = 
"PtexWriter error: Invalid alpha channel";
 
  168                              int nchannels, 
int alphachan, 
int nfaces,
 
  171     if (!checkFormat(mt, dt, nchannels, alphachan, error))
 
  175                                            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;
 
  264                                int nchannels, 
int alphachan, 
int nfaces,
 
  291     deflateInit(&
_zstream, compress ? Z_DEFAULT_COMPRESSION : 0);
 
  308         std::cerr << error.
c_str() << std::endl;
 
  334         setError(
"PtexWriter error: faceid out of range");
 
  339         setError(
"PtexWriter error: asymmetric face res not supported for triangle textures");
 
  358     f.
flags |= (uint8_t)flags;
 
  402     for (
int i = 0; i < nkeys; i++) {
 
  405         data->
getKey(i, key, type);
 
  424                 const int16_t* val=0;
 
  431                 const int32_t* val=0;
 
  456                                  const void* value, 
int size)
 
  458     if (strlen(key) > 255) {
 
  459         std::stringstream str;
 
  460         str << 
"PtexWriter error: meta data key too long (max=255) \"" << key << 
"\"";
 
  465         std::stringstream str;
 
  466         str << 
"PtexWriter error: meta data size <= 0 for \"" << key << 
"\"";
 
  469     std::map<std::string,int>::iterator iter = 
_metamap.find(key);
 
  473         index = iter->second;
 
  485     memcpy(&m.
data[0], value, size);
 
  504     if (!fwrite(data, size, 1, fp)) {
 
  505         setError(
"PtexWriter error: file write failed");
 
  522         int zresult = deflate(&
_zstream, finish ? Z_FINISH : Z_NO_FLUSH);
 
  525         if (zresult == Z_STREAM_END) 
break;
 
  526         if (zresult != Z_OK) {
 
  527             setError(
"PtexWriter error: data compression internal error");
 
  530         if (!finish && 
_zstream.avail_out != 0)
 
  535     if (!finish) 
return 0;
 
  537     int total = (int)
_zstream.total_out;
 
  545     if (!fread(data, size, 1, fp)) {
 
  546         setError(
"PtexWriter error: temp file read failed");
 
  555     if (size <= 0) 
return 0;
 
  556     fseeko(src, pos, SEEK_SET);
 
  561         if (!fread(buff, nbytes, 1, src)) {
 
  562             setError(
"PtexWriter error: temp file read failed");
 
  577     if (ntileslog2 == 0) 
return faceres;
 
  583     int n = faceres.
ulog2 + faceres.
vlog2 - ntileslog2;
 
  609     int ures = res.
u(), vres = res.
v();
 
  612     char* buff = useMalloc ? (
char*) malloc(blockSize) : (
char*)alloca(blockSize);
 
  627     if (useMalloc) free(buff);
 
  636     int ntilesu = res.
ntilesu(tileres);
 
  637     int ntilesv = res.
ntilesv(tileres);
 
  638     int ntiles = ntilesu * ntilesv;
 
  647         std::vector<FaceDataHeader> tileHeader(ntiles);
 
  648         int tileures = tileres.
u();
 
  649         int tilevres = tileres.
v();
 
  651         int tilevstride = tilevres*stride;
 
  656         const char* rowp = (
const char*) data;
 
  657         const char* rowpend = rowp + ntilesv * tilevstride;
 
  658         for (; rowp != rowpend; rowp += tilevstride) {
 
  659             const char* p = rowp;
 
  660             const char* pend = p + ntilesu * tileustride;
 
  661             for (; p != pend; tdh++, p += tileustride) {
 
  679         totalsize += 
writeBlock(fp, &tileheadersize, 
sizeof(tileheadersize));
 
  698     char* buff = useMalloc ? (
char*) malloc(buffsize) : (
char*)alloca(buffsize);
 
  704     if (useMalloc) free(buff);
 
  711     uint8_t keysize = uint8_t(val.
key.size()+1);
 
  713     uint32_t datasize = uint32_t(val.
data.size());
 
  719     int memsize = int(
sizeof(keysize) + (
size_t)keysize + 
sizeof(datatype)
 
  720                    + 
sizeof(datasize) + datasize);
 
  727                                int nchannels, 
int alphachan, 
int nfaces, 
bool genmipmaps)
 
  731       _genmipmaps(genmipmaps),
 
  748     for (
int i = 0; i < nfaces; i++) 
_faceinfo[i].flags = uint8_t(-1);
 
  750     _levels.front().pos.resize(nfaces);
 
  751     _levels.front().fdh.resize(nfaces);
 
  752     _rpos.resize(nfaces);
 
  795         unlink(
_path.c_str());
 
  797             error = fileError(
"Can't write to ptex file: ", 
_path.c_str()).c_str();
 
  833         temp = (uint8_t*) malloc(rowlen * nrows);
 
  856     if (temp) free(temp);
 
  907                     void* data = malloc(size);
 
  935     FILE* newfp = fopen(
_newpath.c_str(), 
"wb+");
 
  953     FilePos levelInfoPos = ftello(newfp);
 
  962         int nfaces = int(level.
fdh.size());
 
  969         for (
int fi = 0; fi < nfaces; fi++)
 
  971                                             level.
fdh[fi].blocksize());
 
  984     fseeko(newfp, levelInfoPos, SEEK_SET);
 
  988     fseeko(newfp, 0, SEEK_SET);
 
  998     for (
int faceid = 0, n = 
int(
_faceinfo.size()); faceid < n; faceid++) {
 
 1004         bool isConst = 
true;
 
 1006         int nedges = isTriangle ? 3 : 4;
 
 1007         for (
int eid = 0; eid < nedges; eid++) {
 
 1009             int prevFid = faceid;
 
 1014             const int maxcount = 10; 
 
 1015             while (afid != faceid) {
 
 1020                 if (afid < 0 || ++count == maxcount)
 
 1021                 { isConst = 
false; 
break; }
 
 1027                 { isConst = 
false; 
break; }
 
 1032                 bool isT = !isTriangle && prevWasSubface && !isSubface && af.
adjface(aeid) == prevFid;
 
 1033                 std::swap(prevFid, afid);
 
 1034                 prevWasSubface = isSubface;
 
 1040                     peid = (peid + 3) % 4;
 
 1043                     aeid = (aeid + 3) % 4;
 
 1047                     aeid = (aeid + 1) % nedges;
 
 1052             if (!isConst) 
break;
 
 1071     for (
int rfaceid = nfaces-1, cutoffres = 
MinReductionLog2; rfaceid >= 0; rfaceid--) {
 
 1076         while (min > cutoffres) {
 
 1078             int size = rfaceid+1;
 
 1081             level.
pos.resize(size);
 
 1082             level.
fdh.resize(size);
 
 1090     for (
int i = 0; i < nfaces; i++)
 
 1093     char* buff = (
char*) malloc(buffsize);
 
 1095     int nlevels = int(
_levels.size());
 
 1096     for (
int i = 1; i < nlevels; i++) {
 
 1098         int nextsize = (i+1 < nlevels)? 
int(
_levels[i+1].fdh.size()) : 0;
 
 1099         for (
int rfaceid = 0, size = 
int(level.
fdh.size()); rfaceid < size; rfaceid++) {
 
 1109             fseeko(
_tmpfp, 0, SEEK_END);
 
 1115             if (rfaceid < nextsize) {
 
 1125     fseeko(
_tmpfp, 0, SEEK_END);
 
 1132     std::vector<MetaEntry*> lmdEntries; 
 
 1135     for (
int i = 0, n = (
int)
_metadata.size(); i < n; i++) {
 
 1137 #ifndef PTEX_NO_LARGE_METADATA_BLOCKS 
 1140             lmdEntries.push_back(&e);
 
 1158     int nLmd = (int)lmdEntries.size();
 
 1161         std::vector<FilePos> lmdoffset(nLmd);
 
 1162         std::vector<uint32_t> lmdzipsize(nLmd);
 
 1163         for (
int i = 0; i < nLmd; i++) {
 
 1165             lmdoffset[i] = ftello(
_tmpfp);
 
 1170         for (
int i = 0; i < nLmd; i++) {
 
 1172             uint8_t keysize = uint8_t(e->
key.size()+1);
 
 1174             uint32_t datasize = (uint32_t)e->
data.size();
 
 1175             uint32_t zipsize = lmdzipsize[i];
 
 1183                 (uint32_t)(
sizeof(keysize) + (size_t)keysize + 
sizeof(datatype) +
 
 1184                            sizeof(datasize) + 
sizeof(zipsize));
 
 1189         for (
int i = 0; i < nLmd; i++) {
 
 1199                                int nchannels, 
int alphachan, 
int nfaces)
 
 1212         std::stringstream str;
 
 1213         str << 
"Not a ptex file: " << path;
 
 1224         std::stringstream str;
 
 1225         str << 
"PtexWriter::edit error: header doesn't match existing file, " 
 1226             << 
"conversions not currently supported";
 
 1234         std::stringstream str;
 
 1235         str << 
"Error reading extended header: " << path;
 
 1241     fseeko(
_fp, 0, SEEK_END);
 
 1270     writeBlank(
_fp, 
sizeof(edittype) + 
sizeof(editsize) + 
sizeof(efdh));
 
 1273     uint8_t* constval = (uint8_t*) malloc(
_pixelSize);
 
 1279         uint8_t* temp = (uint8_t*) malloc(rowlen * nrows);
 
 1309     fseeko(
_fp, pos, SEEK_SET);
 
 1313     fseeko(
_fp, 0, SEEK_END);
 
 1326     editsize = (uint32_t)
sizeof(efdh) + 
_pixelSize;
 
 1353     writeBlank(
_fp, 
sizeof(edittype) + 
sizeof(editsize) + 
sizeof(emdh));
 
 1356     for (
size_t i = 0, n = 
_metadata.size(); i < n; i++) {
 
 1367     fseeko(
_fp, pos, SEEK_SET);
 
 1371     fseeko(
_fp, 0, SEEK_END);
 
Single-precision (32-bit) floating point. 
virtual Ptex::BorderMode vBorderMode()=0
Mode for filtering texture access beyond mesh border. 
int ntilesv(Res tileres) const 
Determine the number of tiles in the v direction for the given tile res. 
int adjface(int eid) const 
Access an adjacent face id. The eid value must be 0..3. 
virtual int numChannels()=0
Number of channels stored in file. 
Interface for writing data to a ptex file. 
void getError(Ptex::String &error)
bool storeFaceInfo(int faceid, FaceInfo &dest, const FaceInfo &src, int flags=0)
virtual ~PtexWriterBase()
virtual bool close(Ptex::String &error)
Close the file. 
virtual void release()
Release resources held by this pointer (pointer becomes invalid). 
void writeReduction(FILE *fp, const void *data, int stride, Res res)
static void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
virtual bool hasEdits()
True if the file has edit blocks. 
virtual void release()
Release resources held by this pointer (pointer becomes invalid). 
bool isConstant() const 
Determine if face is constant (by checking a flag). 
Unsigned, 16-bit integer. 
static int DataSize(DataType dt)
Look up size of given data type (in bytes). 
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face. 
virtual bool hasEdits()=0
True if the file has edit blocks. 
std::vector< FaceDataHeader > fdh
PtexUtils::ReduceFn * _reduceFn
void writeFaceData(FILE *fp, const void *data, int stride, Res res, FaceDataHeader &fdh)
static void reduceTri(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
static const int AllocaMax
DataType
Type of data stored in texture file. 
static const int HeaderSize
void writeMetaData(FILE *fp)
static void average(const void *src, int sstride, int ures, int vres, void *dst, DataType dt, int nchannels)
bool ok(Ptex::String &error)
std::vector< uint32_t > _rfaceids
virtual void setBorderModes(Ptex::BorderMode uBorderMode, Ptex::BorderMode vBorderMode)
Set border modes. 
virtual bool writeConstantFace(int faceid, const FaceInfo &f, const void *data)
Write constant texture data for a face. 
void storeConstValue(int faceid, const void *data, int stride, Res res)
static void copy(const void *src, int sstride, void *dst, int dstride, int nrows, int rowlen)
static const int LevelInfoSize
virtual PtexMetaData * getMetaData()
Access meta data. 
std::vector< FaceInfo > _faceinfo
void generateReductions()
virtual bool close(Ptex::String &error)
Close the file. 
MetaDataType
Type of meta data entry. 
int v() const 
V resolution in texels. 
virtual int alphaChannel()=0
Index of alpha channel (if any). 
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. 
static const int MinReductionLog2
int writeMetaDataBlock(FILE *fp, MetaEntry &val)
#define PtexFileMinorVersion
int32_t adjfaces[4]
Adjacent faces (-1 == no adjacent face). 
void setError(const std::string &error)
virtual Ptex::MeshType meshType()=0
Type of mesh for which texture data is defined. 
int writeZipBlock(FILE *fp, const void *data, int size, bool finish=true)
static const int ExtHeaderSize
int u() const 
U resolution in texels. 
int8_t vlog2
log base 2 of v resolution, in texels 
static void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
int ntilesu(Res tileres) const 
Determine the number of tiles in the u direction for the given tile res. 
virtual bool writeConstantFace(int faceid, const FaceInfo &f, const void *data)
Write constant texture data for a face. 
static const int MetaDataThreshold
Single-precision (32-bit) floating point. 
bool isSubface() const 
Determine if face is a subface (by checking a flag). 
virtual bool hasMipMaps()=0
True if the file has mipmaps. 
int copyBlock(FILE *dst, FILE *src, FilePos pos, int size)
PtexMainWriter(const char *path, PtexTexture *tex, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, bool genmipmaps)
int writeBlock(FILE *fp, const void *data, int size)
virtual ~PtexMainWriter()
int readBlock(FILE *fp, void *data, int size)
virtual void addMetaData(const char *key, MetaDataType t, const void *value, int size)
#define PtexFileMajorVersion
virtual int numFaces()=0
Number of faces stored in file. 
virtual bool close(Ptex::String &error)
Close the file. 
static const uint32_t Magic
MeshType
Type of base mesh for which the textures are defined. 
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution. 
EdgeId adjedge(int eid) const 
Access an adjacent edge id. The eid value must be 0..3. 
static const int TileSize
static uint32_t floor_log2(uint32_t x)
int size() const 
Total size of specified texture in texels (u * v). 
PtexWriterBase(const char *path, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces, bool compress)
static void encodeDifference(void *data, int size, DataType dt)
virtual Ptex::DataType dataType()=0
Type of data stored in file. 
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading. 
std::vector< FilePos > _rpos
std::vector< FilePos > pos
Smart-pointer for acquiring and releasing API objects. 
virtual bool writeFace(int faceid, const FaceInfo &f, const void *data, int stride)
Write texture data for a face. 
std::vector< LevelRec > _levels
void flagConstantNeighorhoods()
virtual ~PtexIncrWriter()
int8_t ulog2
log base 2 of u resolution, in texels 
Res calcTileRes(Res faceres)
Interface for reading data from a ptex file. 
static const int BlockSize
static bool applyEdits(const char *path, Ptex::String &error)
Apply edits to a file. 
std::vector< uint32_t > _faceids_r
Pixel resolution of a given texture. 
static void divalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
static void deinterleave(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
int writeBlank(FILE *fp, int size)
virtual Ptex::BorderMode uBorderMode()=0
Mode for filtering texture access beyond mesh border. 
Res res
Resolution of face. 
uint8_t adjedges
Adjacent edges, 2 bits per edge. 
Automatically acquire and release lock within enclosing scope. 
Information about a face, as stored in the Ptex file header. 
std::vector< MetaEntry > _metadata
virtual bool close(Ptex::String &error)=0
Close the file. 
virtual void writeMeta(const char *key, const char *value)
Write a string as meta data. 
PtexIncrWriter(const char *path, FILE *fp, Ptex::MeshType mt, Ptex::DataType dt, int nchannels, int alphachan, int nfaces)
std::map< std::string, int > _metamap
void writeConstFaceBlock(FILE *fp, const void *data, FaceDataHeader &fdh)
virtual bool writeFace(int faceid, const FaceInfo &f, const void *data, int stride)
Write texture data for a face. 
virtual void release()=0
Release resources held by this pointer (pointer becomes invalid). 
void writeFaceBlock(FILE *fp, const void *data, int stride, Res res, FaceDataHeader &fdh)
static void reduce(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Double-precision (32-bit) floating point. 
std::vector< uint8_t > data
static bool LittleEndian()
const char * c_str() const 
static bool isConstant(const void *data, int stride, int ures, int vres, int pixelSize)
Public API classes for reading, writing, caching, and filtering Ptex files. 
std::vector< uint8_t > _constdata
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.