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.