53 const std::string& getErrorString()
const {
return _error; }
72 : _io(io ? io : &_defaultIo),
74 _premultiply(premultiply),
84 _baseMemUsed(sizeof(*this)),
85 _memUsed(_baseMemUsed),
99 for (std::vector<Level*>::iterator i =
_levels.begin(); i !=
_levels.end(); ++i) {
107 for (std::vector<Level*>::iterator i =
_levels.begin(); i !=
_levels.end(); ++i) {
108 if (*i) {
delete *i; *i = 0; }
124 std::vector<Level*>().swap(
_levels);
143 error =
"Ptex library doesn't currently support big-endian cpu's";
149 std::string errstr =
"Can't open ptex file: ";
150 errstr += pathArg; errstr +=
"\n"; errstr +=
_io->
lastError();
151 error = errstr.
c_str();
158 std::string errstr =
"Not a ptex file: "; errstr += pathArg;
159 error = errstr.
c_str();
166 s <<
"Unsupported ptex file version ("<<
_header.
version <<
"): " << pathArg;
184 TempErrorHandler tempErr;
199 pos +=
sizeof(uint64_t);
219 error = tempErr.getErrorString();
250 if (
_fp)
return true;
262 memset(&extheaderval, 0,
sizeof(extheaderval));
264 if (0 != memcmp(&headerval, &
_header,
sizeof(headerval)) ||
265 0 != memcmp(&extheaderval, &
_extheader,
sizeof(extheaderval)))
267 setError(
"Header mismatch on reopen of");
277 if (faceid >= 0 && uint32_t(faceid) <
_faceinfo.size())
293 (
int)(
sizeof(FaceInfo)*nfaces));
297 std::vector<uint32_t> faceids_r(nfaces);
353 if (index < 0 || index >=
int(
_entries.size())) {
399 size_t metaDataMemUsed =
sizeof(
MetaData);
412 for (
size_t i = 0, size =
_metaedits.size(); i < size; i++)
427 char* buff = useNew ?
new char[memsize] : (
char*)alloca(memsize);
432 char* end = ptr + memsize;
434 uint8_t keysize = *ptr++;
435 char* key = (
char*)ptr; ptr += keysize;
436 key[keysize-1] =
'\0';
437 uint8_t datatypeval = *ptr++;
438 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
439 ptr +=
sizeof(datasize);
440 char* data = ptr; ptr += datasize;
441 metadata->
addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
444 if (useNew)
delete [] buff;
453 char* buff = useNew ?
new char [memsize] : (
char*)alloca(memsize);
460 char* end = ptr + memsize;
462 uint8_t keysize = *ptr++;
463 char* key = (
char*)ptr; ptr += keysize;
464 uint8_t datatypeval = *ptr++;
465 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
466 ptr +=
sizeof(datasize);
467 uint32_t zipsizeval; memcpy(&zipsizeval, ptr,
sizeof(zipsizeval));
468 ptr +=
sizeof(zipsizeval);
469 metadata->
addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
473 if (useNew)
delete [] buff;
487 endpos =
FilePos((uint64_t)-1);
490 while (pos < endpos) {
495 if (!
readBlock(&edittype,
sizeof(edittype),
false))
break;
496 if (!
readBlock(&editsize,
sizeof(editsize),
false))
break;
497 if (!editsize)
break;
499 pos =
tell() + editsize;
521 f.flags |= FaceInfo::flag_hasedits;
531 if (!f.isConstant()) {
558 assert(
_fp && size >= 0);
559 if (!
_fp || size < 0)
return false;
561 if (result == size) {
566 setError(
"PtexReader error: read failed (EOF)");
573 if (zipsize < 0 || unzipsize < 0)
return false;
588 int zresult = inflate(&
_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
589 if (zresult == Z_STREAM_END)
break;
590 if (zresult != Z_OK) {
591 setError(
"PtexReader error: unzip failed, file corrupt");
597 int total = (int)
_zstream.total_out;
599 return total == unzipsize;
622 for (
size_t i = 0, size =
_faceedits.size(); i < size; i++) {
645 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
659 size_t newMemUsed = 0;
678 uint32_t tileheadersize;
679 readBlock(&tileheadersize,
sizeof(tileheadersize));
690 int uw = res.u(), vw = res.v();
691 int npixels = uw * vw;
695 newMemUsed =
sizeof(
PackedFace) + unpackedSize;
697 char* tmp = useNew ?
new char [unpackedSize] : (
char*) alloca(unpackedSize);
707 if (useNew)
delete [] tmp;
722 getData(faceid, buffer, stride, f.res);
734 int resu = res.u(), resv = res.v();
736 if (stride == 0) stride = rowlen;
739 if (d->isConstant()) {
744 else if (d->isTiled()) {
746 Res tileres = d->tileRes();
747 int ntilesu = res.ntilesu(tileres);
748 int ntilesv = res.ntilesv(tileres);
749 int tileures = tileres.u();
750 int tilevres = tileres.v();
753 char* dsttilerow = (
char*) buffer;
754 for (
int i = 0; i < ntilesv; i++) {
755 char* dsttile = dsttilerow;
756 for (
int j = 0; j < ntilesu; j++) {
763 tilevres, tilerowlen);
764 dsttile += tilerowlen;
766 dsttilerow += stride * tilevres;
782 if (fi.isConstant() || fi.res == 0) {
800 if (fi.isConstant() || res == 0) {
805 int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
807 if (redu == 0 && redv == 0) {
814 if (redu == redv && !fi.hasEdits()) {
818 if (
size_t(levelid) <
_levels.size()) {
826 if (
size_t(rfaceid) < level->
faces.size()) {
827 face =
getFace(levelid, level, rfaceid, res);
844 size_t newMemUsed = 0;
846 if (res.ulog2 < 0 || res.vlog2 < 0) {
847 std::cerr <<
"PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
850 else if (redu < 0 || redv < 0) {
851 std::cerr <<
"PtexReader::getData - enlargements not supported" << std::endl;
857 std::cerr <<
"PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
871 blendu = (res.ulog2 & 1);
873 else blendu = redu > redv;
889 size_t tableNewMemUsed = 0;
891 if (face != newface) {
902 float* result,
int firstchan,
int nchannelsArg)
904 memset(result, 0,
sizeof(*result)*nchannelsArg);
908 if (nchannelsArg <= 0)
return;
913 data->getPixel(u, v, pixel);
916 int datasize = DataSize(
datatype());
918 pixel = (
char*) pixel + datasize * firstchan;
922 memcpy(result, pixel, datasize * nchannelsArg);
929 float* result,
int firstchan,
int nchannelsArg,
932 memset(result, 0, nchannelsArg);
936 if (nchannelsArg <= 0)
return;
941 data->getPixel(u, v, pixel);
944 int datasize = DataSize(
datatype());
946 pixel = (
char*) pixel + datasize * firstchan;
950 memcpy(result, pixel, datasize * nchannelsArg);
967 reducefn(_data,
_pixelsize * _res.u(), _res.u(), _res.v(),
1009 newtileres = newres;
1013 newtileres = _tileres;
1015 if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1016 if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1021 int newntiles = newres.ntiles(newtileres);
1023 if (newntiles == 1) {
1027 bool allConstant =
true;
1028 for (
int i = 0; i < _ntiles; i++) {
1030 allConstant = (allConstant && tile->
isConstant() &&
1040 else if (isTriangle) {
1043 int tileures = _tileres.u();
1044 int tilevres = _tileres.v();
1046 int dstride = sstride * _ntilesu;
1047 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1049 char* tmp =
new char [_ntiles * _tileres.size() *
_pixelsize];
1051 for (
int i = 0; i < _ntiles;) {
1059 tmpptr += (i%_ntilesu) ? sstride : dstepv;
1067 reducefn(tmp,
_pixelsize * _res.u(), _res.u(), _res.v(),
1078 int tileures = _tileres.u();
1079 int tilevres = _tileres.v();
1082 int dstepu = dstride/_ntilesu;
1083 int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1085 char* dst = (
char*) newface->
getData();
1086 for (
int i = 0; i < _ntiles;) {
1090 newres.u()/_ntilesu, newres.v()/_ntilesv,
1093 reducefn(tile->
getData(), sstride, tileures, tilevres,
1094 dst, dstride, _dt, _nchan);
1096 dst += (i%_ntilesu) ? dstepu : dstepv;
1100 for (
int i = 0; i < _ntiles; i++) tiles[i]->
release();
1114 int tileu = ui >> _tileres.ulog2;
1115 int tilev = vi >> _tileres.vlog2;
1117 tile->getPixel(ui - (tileu<<_tileres.ulog2),
1118 vi - (tilev<<_tileres.vlog2), result);
1132 int pntilesu = _parentface->ntilesu();
1133 int pntilesv = _parentface->ntilesv();
1134 int nu = pntilesu / _ntilesu;
1135 int nv = pntilesv / _ntilesv;
1137 int ntilesval = nu*nv;
1139 bool allConstant =
true;
1140 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1141 for (
int i = 0; i < ntilesval;) {
1143 allConstant = (allConstant && tileval->
isConstant() &&
1147 ptile += (i%nu)? 1 : pntilesu - nu + 1;
1151 size_t newMemUsed = 0;
1165 int ptileures = _parentface->tileres().u();
1166 int ptilevres = _parentface->tileres().v();
1169 int dstepu = dstride/nu;
1170 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1172 char* dst = (
char*) newface->
getData();
1173 for (
int i = 0; i < ntilesval;) {
1177 _tileres.u()/nu, _tileres.v()/nv,
1180 _reducefn(tileval->
getData(), sstride, ptileures, ptilevres,
1181 dst, dstride, _dt, _nchan);
1183 dst += (i%nu) ? dstepu : dstepv;
1191 _reader->increaseMemUsed(newMemUsed);
const int EditMetaDataHeaderSize
const int FaceDataHeaderSize
const int EditFaceDataHeaderSize
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
#define PTEX_NAMESPACE_END
Public API classes for reading, writing, caching, and filtering Ptex files.
Automatically acquire and release lock within enclosing scope.
Custom handler interface redirecting Ptex error messages.
virtual void reportError(const char *error)=0
Per-face texture data accessor.
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
virtual bool isConstant()=0
True if this data block is constant.
virtual void * getData()=0
Access the data from this data block.
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Smart-pointer for acquiring and releasing API objects.
T * get() const
Get pointer value.
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
std::vector< FilePos > offsets
std::vector< FaceDataHeader > fdh
std::vector< FaceData * > faces
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
std::vector< FaceDataHeader > _fdh
void readTile(int tile, FaceData *&data)
std::vector< FilePos > _offsets
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
DataType datatype() const
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
std::vector< FilePos > _levelpos
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
std::vector< FaceEdit > _faceedits
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
void increaseMemUsed(size_t amount)
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Level * getLevel(int levelid)
FaceData * errorData(bool deleteOnRelease=false)
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
virtual PtexMetaData * getMetaData()
Access meta data.
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
std::vector< LevelInfo > _levelinfo
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
void readFace(int levelid, Level *level, int faceid, Res res)
std::vector< uint32_t > _rfaceids
std::vector< MetaEdit > _metaedits
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
bool readBlock(void *data, int size, bool reportError=true)
std::vector< Level * > _levels
std::vector< FaceInfo > _faceinfo
PtexInputHandler::Handle _fp
bool readZipBlock(void *data, int zipsize, int unzipsize)
void readLevel(int levelid, Level *&level)
std::vector< char > _errorPixel
bool open(const char *path, Ptex::String &error)
void setError(const char *error)
Interface for reading data from a ptex file.
virtual const char * path()=0
Path that file was opened with.
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
const char * c_str() const
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void decodeDifference(void *data, int size, DataType dt)
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Information about a face, as stored in the Ptex file header.
Pixel resolution of a given texture.