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;
176 TempErrorHandler tempErr;
191 pos +=
sizeof(uint64_t);
211 error = tempErr.getErrorString();
242 if (
_fp)
return true;
254 memset(&extheaderval, 0,
sizeof(extheaderval));
256 if (0 != memcmp(&headerval, &
_header,
sizeof(headerval)) ||
257 0 != memcmp(&extheaderval, &
_extheader,
sizeof(extheaderval)))
259 setError(
"Header mismatch on reopen of");
269 if (faceid >= 0 && uint32_t(faceid) <
_faceinfo.size())
285 (
int)(
sizeof(FaceInfo)*nfaces));
289 std::vector<uint32_t> faceids_r(nfaces);
345 if (index < 0 || index >=
int(
_entries.size())) {
391 size_t metaDataMemUsed =
sizeof(
MetaData);
404 for (
size_t i = 0, size =
_metaedits.size(); i < size; i++)
419 char* buff = useNew ?
new char[memsize] : (
char*)alloca(memsize);
424 char* end = ptr + memsize;
426 uint8_t keysize = *ptr++;
427 char* key = (
char*)ptr; ptr += keysize;
428 key[keysize-1] =
'\0';
429 uint8_t datatypeval = *ptr++;
430 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
431 ptr +=
sizeof(datasize);
432 char* data = ptr; ptr += datasize;
433 metadata->
addEntry((uint8_t)(keysize-1), key, datatypeval, datasize, data, metaDataMemUsed);
436 if (useNew)
delete [] buff;
445 char* buff = useNew ?
new char [memsize] : (
char*)alloca(memsize);
452 char* end = ptr + memsize;
454 uint8_t keysize = *ptr++;
455 char* key = (
char*)ptr; ptr += keysize;
456 uint8_t datatypeval = *ptr++;
457 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
458 ptr +=
sizeof(datasize);
459 uint32_t zipsizeval; memcpy(&zipsizeval, ptr,
sizeof(zipsizeval));
460 ptr +=
sizeof(zipsizeval);
461 metadata->
addLmdEntry((uint8_t)(keysize-1), key, datatypeval, datasize, pos, zipsizeval, metaDataMemUsed);
465 if (useNew)
delete [] buff;
479 endpos =
FilePos((uint64_t)-1);
482 while (pos < endpos) {
487 if (!
readBlock(&edittype,
sizeof(edittype),
false))
break;
488 if (!
readBlock(&editsize,
sizeof(editsize),
false))
break;
489 if (!editsize)
break;
491 pos =
tell() + editsize;
513 f.flags |= FaceInfo::flag_hasedits;
523 if (!f.isConstant()) {
550 assert(
_fp && size >= 0);
551 if (!
_fp || size < 0)
return false;
553 if (result == size) {
558 setError(
"PtexReader error: read failed (EOF)");
565 if (zipsize < 0 || unzipsize < 0)
return false;
580 int zresult = inflate(&
_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
581 if (zresult == Z_STREAM_END)
break;
582 if (zresult != Z_OK) {
583 setError(
"PtexReader error: unzip failed, file corrupt");
589 int total = (int)
_zstream.total_out;
591 return total == unzipsize;
614 for (
size_t i = 0, size =
_faceedits.size(); i < size; i++) {
637 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
651 size_t newMemUsed = 0;
670 uint32_t tileheadersize;
671 readBlock(&tileheadersize,
sizeof(tileheadersize));
682 int uw = res.u(), vw = res.v();
683 int npixels = uw * vw;
687 newMemUsed =
sizeof(
PackedFace) + unpackedSize;
689 char* tmp = useNew ?
new char [unpackedSize] : (
char*) alloca(unpackedSize);
699 if (useNew)
delete [] tmp;
714 getData(faceid, buffer, stride, f.res);
726 int resu = res.u(), resv = res.v();
728 if (stride == 0) stride = rowlen;
731 if (d->isConstant()) {
736 else if (d->isTiled()) {
738 Res tileres = d->tileRes();
739 int ntilesu = res.ntilesu(tileres);
740 int ntilesv = res.ntilesv(tileres);
741 int tileures = tileres.u();
742 int tilevres = tileres.v();
745 char* dsttilerow = (
char*) buffer;
746 for (
int i = 0; i < ntilesv; i++) {
747 char* dsttile = dsttilerow;
748 for (
int j = 0; j < ntilesu; j++) {
755 tilevres, tilerowlen);
756 dsttile += tilerowlen;
758 dsttilerow += stride * tilevres;
774 if (fi.isConstant() || fi.res == 0) {
792 if (fi.isConstant() || res == 0) {
797 int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
799 if (redu == 0 && redv == 0) {
806 if (redu == redv && !fi.hasEdits()) {
810 if (
size_t(levelid) <
_levels.size()) {
818 if (
size_t(rfaceid) < level->
faces.size()) {
819 face =
getFace(levelid, level, rfaceid, res);
836 size_t newMemUsed = 0;
838 if (res.ulog2 < 0 || res.vlog2 < 0) {
839 std::cerr <<
"PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
842 else if (redu < 0 || redv < 0) {
843 std::cerr <<
"PtexReader::getData - enlargements not supported" << std::endl;
849 std::cerr <<
"PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
863 blendu = (res.ulog2 & 1);
865 else blendu = redu > redv;
881 size_t tableNewMemUsed = 0;
883 if (face != newface) {
894 float* result,
int firstchan,
int nchannelsArg)
896 memset(result, 0,
sizeof(*result)*nchannelsArg);
900 if (nchannelsArg <= 0)
return;
905 data->getPixel(u, v, pixel);
908 int datasize = DataSize(
datatype());
910 pixel = (
char*) pixel + datasize * firstchan;
914 memcpy(result, pixel, datasize * nchannelsArg);
921 float* result,
int firstchan,
int nchannelsArg,
924 memset(result, 0, nchannelsArg);
928 if (nchannelsArg <= 0)
return;
933 data->getPixel(u, v, pixel);
936 int datasize = DataSize(
datatype());
938 pixel = (
char*) pixel + datasize * firstchan;
942 memcpy(result, pixel, datasize * nchannelsArg);
959 reducefn(_data,
_pixelsize * _res.u(), _res.u(), _res.v(),
1001 newtileres = newres;
1005 newtileres = _tileres;
1007 if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1008 if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1013 int newntiles = newres.ntiles(newtileres);
1015 if (newntiles == 1) {
1019 bool allConstant =
true;
1020 for (
int i = 0; i < _ntiles; i++) {
1022 allConstant = (allConstant && tile->
isConstant() &&
1032 else if (isTriangle) {
1035 int tileures = _tileres.u();
1036 int tilevres = _tileres.v();
1038 int dstride = sstride * _ntilesu;
1039 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1041 char* tmp =
new char [_ntiles * _tileres.size() *
_pixelsize];
1043 for (
int i = 0; i < _ntiles;) {
1051 tmpptr += (i%_ntilesu) ? sstride : dstepv;
1059 reducefn(tmp,
_pixelsize * _res.u(), _res.u(), _res.v(),
1070 int tileures = _tileres.u();
1071 int tilevres = _tileres.v();
1074 int dstepu = dstride/_ntilesu;
1075 int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1077 char* dst = (
char*) newface->
getData();
1078 for (
int i = 0; i < _ntiles;) {
1082 newres.u()/_ntilesu, newres.v()/_ntilesv,
1085 reducefn(tile->
getData(), sstride, tileures, tilevres,
1086 dst, dstride, _dt, _nchan);
1088 dst += (i%_ntilesu) ? dstepu : dstepv;
1092 for (
int i = 0; i < _ntiles; i++) tiles[i]->
release();
1106 int tileu = ui >> _tileres.ulog2;
1107 int tilev = vi >> _tileres.vlog2;
1109 tile->getPixel(ui - (tileu<<_tileres.ulog2),
1110 vi - (tilev<<_tileres.vlog2), result);
1124 int pntilesu = _parentface->ntilesu();
1125 int pntilesv = _parentface->ntilesv();
1126 int nu = pntilesu / _ntilesu;
1127 int nv = pntilesv / _ntilesv;
1129 int ntilesval = nu*nv;
1131 bool allConstant =
true;
1132 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1133 for (
int i = 0; i < ntilesval;) {
1135 allConstant = (allConstant && tileval->
isConstant() &&
1139 ptile += (i%nu)? 1 : pntilesu - nu + 1;
1143 size_t newMemUsed = 0;
1157 int ptileures = _parentface->tileres().u();
1158 int ptilevres = _parentface->tileres().v();
1161 int dstepu = dstride/nu;
1162 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1164 char* dst = (
char*) newface->
getData();
1165 for (
int i = 0; i < ntilesval;) {
1169 _tileres.u()/nu, _tileres.v()/nv,
1172 _reducefn(tileval->
getData(), sstride, ptileures, ptilevres,
1173 dst, dstride, _dt, _nchan);
1175 dst += (i%nu) ? dstepu : dstepv;
1183 _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.