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)