66 error =
"Ptex library doesn't currently support big-endian cpu's";
72 std::string errstr =
"Can't open ptex file: ";
74 error = errstr.
c_str();
79 std::string errstr =
"Not a ptex file: "; errstr +=
path;
80 error = errstr.
c_str();
102 pos +=
sizeof(uint64_t);
129 _io(io ? io : &_defaultIo),
130 _premultiply(premultiply),
187 if (faceid >= 0 && uint32_t(faceid) <
_faceinfo.size())
207 std::vector<uint32_t> faceids_r(nfaces);
213 for (
int i = 0; i < nfaces; i++)
267 MetaMap::iterator iter =
_map.find(key);
268 if (iter ==
_map.end()) {
273 Entry* e = &iter->second;
341 for (
size_t i = 0, size =
_metaedits.size(); i < size; i++)
358 for (
size_t i = 0, size =
_metaedits.size(); i < size; i++)
376 char* buff = useMalloc ? (
char*) malloc(memsize) : (
char*)alloca(memsize);
381 char* end = ptr + memsize;
383 uint8_t keysize = *ptr++;
384 char* key = (
char*)ptr; ptr += keysize;
385 key[keysize-1] =
'\0';
387 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
388 ptr +=
sizeof(datasize);
389 char* data = ptr; ptr += datasize;
390 metadata->
addEntry((uint8_t)(keysize-1), key, datatype, datasize, data);
393 if (useMalloc) free(buff);
402 char* buff = useMalloc ? (
char*) malloc(memsize) : (
char*)alloca(memsize);
409 char* end = ptr + memsize;
411 uint8_t keysize = *ptr++;
412 char* key = (
char*)ptr; ptr += keysize;
414 uint32_t datasize; memcpy(&datasize, ptr,
sizeof(datasize));
415 ptr +=
sizeof(datasize);
416 uint32_t zipsize; memcpy(&zipsize, ptr,
sizeof(zipsize));
417 ptr +=
sizeof(zipsize);
418 metadata->
addLmdEntry((uint8_t)(keysize-1), key, datatype, datasize, pos, zipsize);
422 if (useMalloc) free(buff);
436 endpos =
FilePos((uint64_t)-1);
439 while (pos < endpos) {
444 if (!
readBlock(&edittype,
sizeof(edittype),
false))
break;
445 if (!
readBlock(&editsize,
sizeof(editsize),
false))
break;
446 if (!editsize)
break;
448 pos =
tell() + editsize;
506 if (result == size) {
513 setError(
"PtexReader error: read failed (EOF)");
530 int zresult = inflate(&
_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
531 if (zresult == Z_STREAM_END)
break;
532 if (zresult != Z_OK) {
533 setError(
"PtexReader error: unzip failed, file corrupt");
539 int total = (int)
_zstream.total_out;
541 return total == unzipsize;
574 for (
size_t i = 0, size =
_faceedits.size(); i < size; i++) {
621 int first = faceid, last = faceid;
628 int nfaces = int(level->
fdh.size());
631 if (f < 0 || level->faces[f])
break;
641 if (f >= nfaces || level->
faces[f])
break;
653 std::vector<FaceData*> extraFaces;
654 extraFaces.reserve(last-first);
656 for (
int i = first; i <= last; i++) {
662 if (i != faceid) extraFaces.push_back(face);
668 for (
size_t i = 0, size = extraFaces.size(); i < size; i++)
669 extraFaces[i]->
unref();
692 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
722 uint32_t tileheadersize;
723 readBlock(&tileheadersize,
sizeof(tileheadersize));
733 int uw = res.
u(), vw = res.
v();
734 int npixels = uw * vw;
738 bool useMalloc = unpackedSize >
AllocaMax;
739 void* tmp = useMalloc ? malloc(unpackedSize) : alloca(unpackedSize);
750 if (useMalloc) free(tmp);
772 int resu = res.
u(), resv = res.
v();
774 if (stride == 0) stride = rowlen;
786 int ntilesu = res.
ntilesu(tileres);
787 int ntilesv = res.
ntilesv(tileres);
788 int tileures = tileres.
u();
789 int tilevres = tileres.
v();
792 char* dsttilerow = (
char*) buffer;
793 for (
int i = 0; i < ntilesv; i++) {
794 char* dsttile = dsttilerow;
795 for (
int j = 0; j < ntilesu; j++) {
797 if (!t) { i = ntilesv;
break; }
803 tilevres, tilerowlen);
804 dsttile += tilerowlen;
806 dsttilerow += stride * tilevres;
817 if (faceid < 0 ||
size_t(faceid) >=
_header.
nfaces)
return 0;
837 if (faceid < 0 ||
size_t(faceid) >=
_header.
nfaces)
return 0;
840 if ((fi.
isConstant() && res >= 0) || res == 0) {
851 if (redu == 0 && redv == 0) {
860 if (redu == redv && !fi.
hasEdits() && res >= 0) {
864 if (
size_t(levelid) <
_levels.size()) {
872 if (
size_t(rfaceid) < level->
faces.size())
873 face =
getFace(levelid, level, rfaceid);
895 std::cerr <<
"PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
898 if (redu < 0 || redv < 0) {
899 std::cerr <<
"PtexReader::getData - enlargements not supported" << std::endl;
905 std::cerr <<
"PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
919 blendu = (res.
ulog2 & 1);
921 else blendu = redu > redv;
948 assert(res.
ulog2 < 0);
949 length = (res.
vlog2 <= 0 ? 1 : res.
v());
954 assert(res.
vlog2 < 0);
955 length = (res.
ulog2 <= 0 ? 1 : res.
u());
965 int r1 = (f.
adjedge(e1)-e1+2)&3;
966 int r2 = (f.
adjedge(e2)-e2+2)&3;
969 Res pres1 = pres, pres2 = pres;
970 if (r1 & 1) pres1.
swapuv();
971 if (r2 & 1) pres2.swapuv();
974 if (nf1 >= 0 && !(
_faceinfo[nf1].res >= pres)) nf1 = -1;
975 if (nf2 >= 0 && !(
_faceinfo[nf2].res >= pres)) nf2 = -1;
981 psrc[0] =
getData(faceid, pres);
987 flip[nf] = length ? (r1 + blendu) & 1 : 0;
988 psrc[nf++] =
getData(nf1, pres1);
991 flip[nf] = length ? (r2 + blendu) & 1 : 0;
992 psrc[nf++] =
getData(nf2, pres2);
1004 for (
int i = 0; i < nf; i++) psrc[i]->
release();
1018 memcpy(data, psrc[0]->
getData(), size);
1021 float weight = 1.0f / (float)nf;
1022 memset(data, 0, size);
1023 for (
int i = 0; i < nf; i++)
1037 for (
int i = 0; i < nf; i++) psrc[i]->
release();
1042 float* result,
int firstchan,
int nchannels)
1044 memset(result, 0,
sizeof(*result)*nchannels);
1049 if (nchannels <= 0)
return;
1060 pixel = (
char*) pixel + datasize * firstchan;
1064 memcpy(result, pixel, datasize * nchannels);
1071 float* result,
int firstchan,
int nchannels,
1074 memset(result, 0, nchannels);
1079 if (nchannels <= 0)
return;
1090 pixel = (
char*) pixel + datasize * firstchan;
1094 memcpy(result, pixel, datasize * nchannels);
1121 reducefn(_data,
_pixelsize * _res.u(), _res.u(), _res.v(),
1181 if (newres.
ulog2 == 1 || newres.
vlog2 == 1 || isTriangle) {
1182 newtileres = newres;
1186 newtileres = _tileres;
1194 int newntiles = newres.
ntiles(newtileres);
1196 if (newntiles == 1) {
1200 bool allConstant =
true;
1201 for (
int i = 0; i < _ntiles; i++) {
1203 allConstant = (allConstant && tile->
isConstant() &&
1212 else if (isTriangle) {
1215 int tileures = _tileres.u();
1216 int tilevres = _tileres.v();
1218 int dstride = sstride * _ntilesu;
1219 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1221 char* tmp = (
char*) malloc(_ntiles * _tileres.size() *
_pixelsize);
1223 for (
int i = 0; i < _ntiles;) {
1231 tmpptr += i%_ntilesu ? sstride : dstepv;
1238 reducefn(tmp,
_pixelsize * _res.u(), _res.u(), _res.v(),
1248 int tileures = _tileres.u();
1249 int tilevres = _tileres.v();
1252 int dstepu = dstride/_ntilesu;
1253 int dstepv = dstride*newres.
v()/_ntilesv - dstepu*(_ntilesu-1);
1255 char* dst = (
char*) newface->
getData();
1256 for (
int i = 0; i < _ntiles;) {
1260 newres.
u()/_ntilesu, newres.
v()/_ntilesv,
1263 reducefn(tile->
getData(), sstride, tileures, tilevres,
1264 dst, dstride, _dt, _nchan);
1266 dst += i%_ntilesu ? dstepu : dstepv;
1270 for (
int i = 0; i < _ntiles; i++) tiles[i]->
release();
1275 _dt, _nchan,
this, reducefn);
1287 int tileu = ui >> _tileres.ulog2;
1288 int tilev = vi >> _tileres.vlog2;
1290 tile->
getPixel(ui - (tileu<<_tileres.ulog2),
1291 vi - (tilev<<_tileres.vlog2), result);
1308 int pntilesu = _parentface->ntilesu();
1309 int pntilesv = _parentface->ntilesv();
1310 int nu = pntilesu / _ntilesu;
1311 int nv = pntilesv / _ntilesv;
1315 bool allConstant =
true;
1316 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1317 for (
int i = 0; i < ntiles;) {
1322 allConstant = (allConstant && tile->
isConstant() &&
1326 ptile += i%nu? 1 : pntilesu - nu + 1;
1334 for (
int i = 0; i < ntiles; i++) tiles[i]->
release();
1349 int ptileures = _parentface->tileres().u();
1350 int ptilevres = _parentface->tileres().v();
1353 int dstepu = dstride/nu;
1354 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1356 char* dst = (
char*) face->
getData();
1357 for (
int i = 0; i < ntiles;) {
1361 _tileres.u()/nu, _tileres.v()/nv,
1364 _reducefn(tile->
getData(), sstride, ptileures, ptilevres,
1365 dst, dstride, _dt, _nchan);
1367 dst += i%nu ? dstepu : dstepv;
1374 for (
int i = 0; i < ntiles; i++) tiles[i]->
release();
void handlePendingDelete()
FaceData * getFace(int levelid, Level *level, int faceid)
Left edge, from UV (0,1) to (0,0)
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)=0
int ntiles(Res tileres) const
Determine the total number of tiles for the given tile res.
int ntilesv(Res tileres) const
Determine the number of tiles in the v direction for the given tile res.
safevector< LevelInfo > _levelinfo
static void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
PtexReader(void **parent, PtexCacheImpl *cache, bool premultiply, PtexInputHandler *handler)
bool isConstant() const
Determine if face is constant (by checking a flag).
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.
Top edge, from UV (1,1) to (0,1)
static void reduceTri(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
static const int AllocaMax
safevector< FilePos > _levelpos
safevector< FilePos > _offsets
virtual PtexTexture * get(const char *path, Ptex::String &error)=0
Open a texture.
DataType
Type of data stored in texture file.
safevector< MetaEdit > _metaedits
static void blend(const void *src, float weight, void *dst, bool flip, int rowlen, DataType dt, int nchannels)
safevector< Level * > _levels
static const int HeaderSize
File-handle and memory cache for reading ptex files.
bool readBlock(void *data, int size, bool reportError=true)
virtual const char * path()
Path that file was opened with.
static void copy(const void *src, int sstride, void *dst, int dstride, int nrows, int rowlen)
static const int LevelInfoSize
void readLevel(int levelid, Level *&level)
virtual PtexMetaData * getMetaData()
Access meta data.
static PtexCache * create(int maxFiles=0, int maxMem=0, bool premultiply=false, PtexInputHandler *handler=0)
Create a cache with the specified limits.
static const int EditMetaDataHeaderSize
int v() const
V resolution in texels.
Bottom edge, from UV (0,0) to (1,0)
int32_t adjfaces[4]
Adjacent faces (-1 == no adjacent face).
safevector< FaceEdit > _faceedits
safevector< uint32_t > _rfaceids
static const int ExtHeaderSize
void blendFaces(FaceData *&face, int faceid, Res res, bool blendu)
Per-face texture data accessor.
int u() const
U resolution in texels.
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize)
Res getRes(int levelid, int faceid)
virtual void * getData()=0
Access the data from this data block.
int8_t vlog2
log base 2 of v resolution, in texels
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
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 PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
Single-precision (32-bit) floating point.
safevector< FilePos > offsets
void readTile(int tile, FaceData *&data)
iterator end() const
Returns an iteraot referencing the location just beyond the table.
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
bool hasEdits() const
Determine if face has edits in the file (by checking a flag).
safevector< FaceDataHeader > fdh
virtual void purgeAll()=0
Remove all texture files from the cache.
T * get()
Get pointer value.
void setError(const char *error)
static void orphanList(T &list)
bool readZipBlock(void *data, int zipsize, int unzipsize)
DataType datatype() const
static const uint32_t Magic
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
static void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
EdgeId adjedge(int eid) const
Access an adjacent edge id. The eid value must be 0..3.
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize)
Level * getLevel(int levelid)
PtexInputHandler::Handle _fp
int size() const
Total size of specified texture in texels (u * v).
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
void swapuv()
Swap the u and v resolution values in place.
void readFace(int levelid, Level *level, int faceid)
Smart-pointer for acquiring and releasing API objects.
virtual bool isTiled()=0
True if this data block is tiled.
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
virtual void * getData()
Access the data from this data block.
virtual bool isConstant()=0
True if this data block is constant.
int8_t ulog2
log base 2 of u resolution, in texels
virtual void getPixel(int u, int v, void *result)=0
Read a single texel from the data block.
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Right edge, from UV (1,0) to (1,1)
Interface for reading data from a ptex file.
static const int BlockSize
safevector< FaceData * > faces
Pixel resolution of a given texture.
virtual void reduce(FaceData *&, PtexReader *, Res newres, PtexUtils::ReduceFn)
safevector< FaceDataHeader > _fdh
Cache entry for open file handle.
safevector< FaceInfo > _faceinfo
static void reduceu(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
static void interleave(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
static const int FaceDataHeaderSize
bool open(const char *path, Ptex::String &error)
Ptex cache implementation.
static void reducev(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Res res
Resolution of face.
Automatically acquire and release lock within enclosing scope.
Information about a face, as stored in the Ptex file header.
iterator begin() const
Returns an iterator referencing the beginning of the table.
static void decodeDifference(void *data, int size, DataType dt)
static void ConvertToFloat(float *dst, const void *src, Ptex::DataType dt, int numChannels)
Convert a number of data values from the given data type to float.
static bool LittleEndian()
static const int EditFaceDataHeaderSize
const char * c_str() const
Public API classes for reading, writing, caching, and filtering Ptex files.
int unpackedSize(FaceDataHeader fdh, int levelid, int faceid)
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.