Ptex
PtexReader.cpp
Go to the documentation of this file.
1 /*
2 PTEX SOFTWARE
3 Copyright 2014 Disney Enterprises, Inc. All rights reserved
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in
14  the documentation and/or other materials provided with the
15  distribution.
16 
17  * The names "Disney", "Walt Disney Pictures", "Walt Disney Animation
18  Studios" or the names of its contributors may NOT be used to
19  endorse or promote products derived from this software without
20  specific prior written permission from Walt Disney Pictures.
21 
22 Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25 FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26 IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
34 */
35 
36 #include "PtexPlatform.h"
37 #include <iostream>
38 #include <sstream>
39 #include <stdio.h>
40 
41 #include "Ptexture.h"
42 #include "PtexUtils.h"
43 #include "PtexReader.h"
44 
45 namespace {
46  class TempErrorHandler : public PtexErrorHandler
47  {
48  std::string _error;
49  public:
50  virtual void reportError(const char* error) {
51  _error += error;
52  }
53  const std::string& getErrorString() const { return _error; }
54  };
55 }
56 
58 
59 PtexTexture* PtexTexture::open(const char* path, Ptex::String& error, bool premultiply)
60 {
61  PtexReader* reader = new PtexReader(premultiply, (PtexInputHandler*) 0, (PtexErrorHandler*) 0);
62  bool ok = reader->open(path, error);
63  if (!ok) {
64  reader->release();
65  return 0;
66  }
67  return reader;
68 }
69 
70 
72  : _io(io ? io : &_defaultIo),
73  _err(err),
74  _premultiply(premultiply),
75  _ok(true),
76  _needToOpen(true),
77  _pendingPurge(false),
78  _fp(0),
79  _pos(0),
80  _pixelsize(0),
81  _constdata(0),
82  _metadata(0),
83  _hasEdits(false),
84  _baseMemUsed(sizeof(*this)),
85  _memUsed(_baseMemUsed),
86  _opens(0),
87  _blockReads(0)
88 {
89  memset(&_zstream, 0, sizeof(_zstream));
90 }
91 
92 
94 {
95  closeFP();
96  if (_constdata) delete [] _constdata;
97  if (_metadata) delete _metadata;
98 
99  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
100  if (*i) delete *i;
101  }
102 }
103 
105 {
106  if (_metadata) { delete _metadata; _metadata = 0; }
107  for (std::vector<Level*>::iterator i = _levels.begin(); i != _levels.end(); ++i) {
108  if (*i) { delete *i; *i = 0; }
109  }
110  _reductions.clear();
112 }
113 
114 
116 {
117  // free all dynamic data
118  prune();
119  if (_constdata) {delete [] _constdata; _constdata = 0; }
120  std::vector<FaceInfo>().swap(_faceinfo);
121  std::vector<uint32_t>().swap(_rfaceids);
122  std::vector<LevelInfo>().swap(_levelinfo);
123  std::vector<FilePos>().swap(_levelpos);
124  std::vector<Level*>().swap(_levels);
125  std::vector<MetaEdit>().swap(_metaedits);
126  std::vector<FaceEdit>().swap(_faceedits);
127  closeFP();
128 
129  // reset initial state
130  _ok = true;
131  _needToOpen = true;
132  _pendingPurge = false;
133  _memUsed = _baseMemUsed = sizeof(*this);
134 }
135 
136 
137 bool PtexReader::open(const char* pathArg, Ptex::String& error)
138 {
139  AutoMutex locker(readlock);
140  if (!needToOpen()) return false;
141 
142  if (!LittleEndian()) {
143  error = "Ptex library doesn't currently support big-endian cpu's";
144  return 0;
145  }
146  _path = pathArg;
147  _fp = _io->open(pathArg);
148  if (!_fp) {
149  std::string errstr = "Can't open ptex file: ";
150  errstr += pathArg; errstr += "\n"; errstr += _io->lastError();
151  error = errstr.c_str();
152  _ok = 0;
153  return 0;
154  }
155  memset(&_header, 0, sizeof(_header));
157  if (_header.magic != Magic) {
158  std::string errstr = "Not a ptex file: "; errstr += pathArg;
159  error = errstr.c_str();
160  _ok = 0;
161  closeFP();
162  return 0;
163  }
164  if (_header.version != 1) {
165  std::stringstream s;
166  s << "Unsupported ptex file version ("<< _header.version << "): " << pathArg;
167  error = s.str();
168  _ok = 0;
169  closeFP();
170  return 0;
171  }
173  _errorPixel.resize(_pixelsize);
174 
175  // install temp error handler to capture error (to return in error param)
176  TempErrorHandler tempErr;
177  PtexErrorHandler* prevErr = _err;
178  _err = &tempErr;
179 
180  // read extended header
181  memset(&_extheader, 0, sizeof(_extheader));
183 
184  // compute offsets of various blocks
186  _faceinfopos = pos; pos += _header.faceinfosize;
187  _constdatapos = pos; pos += _header.constdatasize;
188  _levelinfopos = pos; pos += _header.levelinfosize;
189  _leveldatapos = pos; pos += _header.leveldatasize;
190  _metadatapos = pos; pos += _header.metadatazipsize;
191  pos += sizeof(uint64_t); // compatibility barrier
193  _lmddatapos = pos; pos += _extheader.lmddatasize;
194 
195  // edit data may not start immediately if additional sections have been added
196  // use value from extheader if present (and > pos)
198 
199  // read basic file info
200  readFaceInfo();
201  readConstData();
202  readLevelInfo();
203  readEditData();
205 
206  // restore error handler
207  _err = prevErr;
208 
209  // an error occurred while reading the file
210  if (!_ok) {
211  error = tempErr.getErrorString();
212  closeFP();
213  return 0;
214  }
215  AtomicStore(&_needToOpen, false);
216  return true;
217 }
218 
220 {
221  if (_fp) {
222  if (!readlock.trylock()) return false;
223  closeFP();
224  readlock.unlock();
225  }
226  return true;
227 }
228 
229 
231 {
232  if (_fp) {
233  _io->close(_fp);
234  _fp = 0;
235  }
236  inflateEnd(&_zstream);
237 }
238 
239 
241 {
242  if (_fp) return true;
243 
244  // we assume this is called lazily in a scope where readlock is already held
245  _fp = _io->open(_path.c_str());
246  if (!_fp) {
247  setError("Can't reopen");
248  return false;
249  }
250  _pos = 0;
251  Header headerval;
252  ExtHeader extheaderval;
253  readBlock(&headerval, HeaderSize);
254  memset(&extheaderval, 0, sizeof(extheaderval));
255  readBlock(&extheaderval, PtexUtils::min(uint32_t(ExtHeaderSize), headerval.extheadersize));
256  if (0 != memcmp(&headerval, &_header, sizeof(headerval)) ||
257  0 != memcmp(&extheaderval, &_extheader, sizeof(extheaderval)))
258  {
259  setError("Header mismatch on reopen of");
260  return false;
261  }
262  logOpen();
263  return true;
264 }
265 
266 
268 {
269  if (faceid >= 0 && uint32_t(faceid) < _faceinfo.size())
270  return _faceinfo[faceid];
271 
272  static Ptex::FaceInfo dummy;
273  return dummy;
274 }
275 
276 
278 {
279  if (_faceinfo.empty()) {
280  // read compressed face info block
282  int nfaces = _header.nfaces;
283  _faceinfo.resize(nfaces);
285  (int)(sizeof(FaceInfo)*nfaces));
286 
287  // generate rfaceids
288  _rfaceids.resize(nfaces);
289  std::vector<uint32_t> faceids_r(nfaces);
290  PtexUtils::genRfaceids(&_faceinfo[0], nfaces,
291  &_rfaceids[0], &faceids_r[0]);
292  increaseMemUsed(nfaces * (sizeof(_faceinfo[0]) + sizeof(_rfaceids[0])));
293  }
294 }
295 
296 
297 
299 {
300  if (_levelinfo.empty()) {
301  // read level info block
303  _levelinfo.resize(_header.nlevels);
305 
306  // initialize related data
307  _levels.resize(_header.nlevels);
308  _levelpos.resize(_header.nlevels);
309  FilePos pos = _leveldatapos;
310  for (int i = 0; i < _header.nlevels; i++) {
311  _levelpos[i] = pos;
312  pos += _levelinfo[i].leveldatasize;
313  }
314  increaseMemUsed(_header.nlevels * sizeof(_levelinfo[0]) + sizeof(_levels[0]) + sizeof(_levelpos[0]));
315  }
316 }
317 
318 
320 {
321  if (!_constdata) {
322  // read compressed constant data block
324  int size = _pixelsize * _header.nfaces;
325  _constdata = new uint8_t[size];
327  if (_premultiply && _header.hasAlpha())
330  increaseMemUsed(size);
331  }
332 }
333 
334 
336 {
337  if (!_metadata) readMetaData();
338  return _metadata;
339 }
340 
341 
344 {
345  if (index < 0 || index >= int(_entries.size())) {
346  return 0;
347  }
348 
349  Entry* e = _entries[index];
350  if (!e->isLmd) {
351  // normal (small) meta data - just return directly
352  return e;
353  }
354 
355  // large meta data - may not be read in yet
356  if (e->lmdData) {
357  // already in memory
358  return e;
359  }
360  else {
361  // not present, must read from file
362 
363  // get read lock and make sure we still need to read
364  AutoMutex locker(_reader->readlock);
365  if (e->lmdData) {
366  return e;
367  }
368  // go ahead and read, keep local until finished
369  LargeMetaData* lmdData = new LargeMetaData(e->datasize);
370  e->data = (char*) lmdData->data();
372  _reader->seek(e->lmdPos);
374  // update entry
375  e->lmdData = lmdData;
376  return e;
377  }
378 }
379 
380 
382 {
383  // get read lock and make sure we still need to read
384  AutoMutex locker(readlock);
385  if (_metadata) {
386  return;
387  }
388 
389  // allocate new meta data (keep local until fully initialized)
390  MetaData* newmeta = new MetaData(this);
391  size_t metaDataMemUsed = sizeof(MetaData);
392 
393  // read primary meta data blocks
396  _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
397 
398  // read large meta data headers
402 
403  // read meta data edits
404  for (size_t i = 0, size = _metaedits.size(); i < size; i++)
405  readMetaDataBlock(newmeta, _metaedits[i].pos,
406  _metaedits[i].zipsize, _metaedits[i].memsize, metaDataMemUsed);
407 
408  // store meta data
409  AtomicStore(&_metadata, newmeta);
410  increaseMemUsed(newmeta->selfDataSize() + metaDataMemUsed);
411 }
412 
413 
414 void PtexReader::readMetaDataBlock(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
415 {
416  seek(pos);
417  // read from file
418  bool useNew = memsize > AllocaMax;
419  char* buff = useNew ? new char[memsize] : (char*)alloca(memsize);
420 
421  if (readZipBlock(buff, zipsize, memsize)) {
422  // unpack data entries
423  char* ptr = buff;
424  char* end = ptr + memsize;
425  while (ptr < end) {
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);
434  }
435  }
436  if (useNew) delete [] buff;
437 }
438 
439 
440 void PtexReader::readLargeMetaDataHeaders(MetaData* metadata, FilePos pos, int zipsize, int memsize, size_t& metaDataMemUsed)
441 {
442  seek(pos);
443  // read from file
444  bool useNew = memsize > AllocaMax;
445  char* buff = useNew ? new char [memsize] : (char*)alloca(memsize);
446 
447  if (readZipBlock(buff, zipsize, memsize)) {
448  pos += zipsize;
449 
450  // unpack data entries
451  char* ptr = buff;
452  char* end = ptr + memsize;
453  while (ptr < end) {
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);
462  pos += zipsizeval;
463  }
464  }
465  if (useNew) delete [] buff;
466 }
467 
469 {
470  // determine file range to scan for edits
471  FilePos pos = FilePos(_editdatapos), endpos;
472  if (_extheader.editdatapos > 0) {
473  // newer files record the edit data position and size in the extheader
474  // note: position will be non-zero even if size is zero
475  endpos = FilePos(pos + _extheader.editdatasize);
476  }
477  else {
478  // must have an older file, just read until EOF
479  endpos = FilePos((uint64_t)-1);
480  }
481 
482  while (pos < endpos) {
483  seek(pos);
484  // read the edit data header
485  uint8_t edittype = et_editmetadata;
486  uint32_t editsize;
487  if (!readBlock(&edittype, sizeof(edittype), /*reporterror*/ false)) break;
488  if (!readBlock(&editsize, sizeof(editsize), /*reporterror*/ false)) break;
489  if (!editsize) break;
490  _hasEdits = true;
491  pos = tell() + editsize;
492  switch (edittype) {
493  case et_editfacedata: readEditFaceData(); break;
494  case et_editmetadata: readEditMetaData(); break;
495  }
496  }
497  increaseMemUsed(sizeof(_faceedits[0]) * _faceedits.capacity() +
498  sizeof(_metaedits[0]) * _metaedits.capacity());
499 }
500 
501 
503 {
504  // read header
505  EditFaceDataHeader efdh;
506  if (!readBlock(&efdh, EditFaceDataHeaderSize)) return;
507 
508  // update face info
509  int faceid = efdh.faceid;
510  if (faceid < 0 || size_t(faceid) >= _header.nfaces) return;
511  FaceInfo& f = _faceinfo[faceid];
512  f = efdh.faceinfo;
513  f.flags |= FaceInfo::flag_hasedits;
514 
515  // read const value now
516  uint8_t* constdata = _constdata + _pixelsize * faceid;
517  if (!readBlock(constdata, _pixelsize)) return;
518  if (_premultiply && _header.hasAlpha())
519  PtexUtils::multalpha(constdata, 1, datatype(),
521 
522  // update header info for remaining data
523  if (!f.isConstant()) {
524  _faceedits.push_back(FaceEdit());
525  FaceEdit& e = _faceedits.back();
526  e.pos = tell();
527  e.faceid = faceid;
528  e.fdh = efdh.fdh;
529  }
530 }
531 
532 
534 {
535  // read header
536  EditMetaDataHeader emdh;
537  if (!readBlock(&emdh, EditMetaDataHeaderSize)) return;
538 
539  // record header info for later
540  _metaedits.push_back(MetaEdit());
541  MetaEdit& e = _metaedits.back();
542  e.pos = tell();
543  e.zipsize = emdh.metadatazipsize;
544  e.memsize = emdh.metadatamemsize;
545 }
546 
547 
548 bool PtexReader::readBlock(void* data, int size, bool reporterror)
549 {
550  assert(_fp);
551  if (!_fp) return false;
552  int result = (int)_io->read(data, size, _fp);
553  if (result == size) {
554  _pos += size;
555  return true;
556  }
557  if (reporterror)
558  setError("PtexReader error: read failed (EOF)");
559  return false;
560 }
561 
562 
563 bool PtexReader::readZipBlock(void* data, int zipsize, int unzipsize)
564 {
565  if (!_zstream.state) {
566  inflateInit(&_zstream);
567  }
568 
569  void* buff = alloca(BlockSize);
570  _zstream.next_out = (Bytef*) data;
571  _zstream.avail_out = unzipsize;
572 
573  while (1) {
574  int size = (zipsize < BlockSize) ? zipsize : BlockSize;
575  zipsize -= size;
576  if (!readBlock(buff, size)) break;
577  _zstream.next_in = (Bytef*) buff;
578  _zstream.avail_in = size;
579  int zresult = inflate(&_zstream, zipsize ? Z_NO_FLUSH : Z_FINISH);
580  if (zresult == Z_STREAM_END) break;
581  if (zresult != Z_OK) {
582  setError("PtexReader error: unzip failed, file corrupt");
583  inflateReset(&_zstream);
584  return 0;
585  }
586  }
587 
588  int total = (int)_zstream.total_out;
589  inflateReset(&_zstream);
590  return total == unzipsize;
591 }
592 
593 
594 void PtexReader::readLevel(int levelid, Level*& level)
595 {
596  // get read lock and make sure we still need to read
597  AutoMutex locker(readlock);
598  if (level) {
599  return;
600  }
601 
602  // go ahead and read the level
603  LevelInfo& l = _levelinfo[levelid];
604 
605  // keep new level local until finished
606  Level* newlevel = new Level(l.nfaces);
607  seek(_levelpos[levelid]);
609  computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
610 
611  // apply edits (if any) to level 0
612  if (levelid == 0) {
613  for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
614  FaceEdit& e = _faceedits[i];
615  newlevel->fdh[e.faceid] = e.fdh;
616  newlevel->offsets[e.faceid] = e.pos;
617  }
618  }
619 
620  // don't assign to result until level data is fully initialized
621  AtomicStore(&level, newlevel);
622  increaseMemUsed(level->memUsed());
623 }
624 
625 
626 void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
627 {
628  FaceData*& face = level->faces[faceid];
629  FaceDataHeader fdh = level->fdh[faceid];
630  readFaceData(level->offsets[faceid], fdh, res, levelid, face);
631 }
632 
633 
635 {
636  _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
637 }
638 
639 
640 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
641  FaceData*& face)
642 {
643  AutoMutex locker(readlock);
644  if (face) {
645  return;
646  }
647 
648  // keep new face local until fully initialized
649  FaceData* newface = 0;
650  size_t newMemUsed = 0;
651 
652  seek(pos);
653  switch (fdh.encoding()) {
654  case enc_constant:
655  {
657  newface = cf;
658  newMemUsed = sizeof(ConstantFace) + _pixelsize;
659  readBlock(cf->data(), _pixelsize);
660  if (levelid==0 && _premultiply && _header.hasAlpha())
661  PtexUtils::multalpha(cf->data(), 1, datatype(),
663  }
664  break;
665  case enc_tiled:
666  {
667  Res tileres;
668  readBlock(&tileres, sizeof(tileres));
669  uint32_t tileheadersize;
670  readBlock(&tileheadersize, sizeof(tileheadersize));
671  TiledFace* tf = new TiledFace(this, res, tileres, levelid);
672  newface = tf;
673  newMemUsed = tf->memUsed();
674  readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
675  computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
676  }
677  break;
678  case enc_zipped:
679  case enc_diffzipped:
680  {
681  int uw = res.u(), vw = res.v();
682  int npixels = uw * vw;
683  int unpackedSize = _pixelsize * npixels;
684  PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
685  newface = pf;
686  newMemUsed = sizeof(PackedFace) + unpackedSize;
687  bool useNew = unpackedSize > AllocaMax;
688  char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
689  readZipBlock(tmp, fdh.blocksize(), unpackedSize);
690  if (fdh.encoding() == enc_diffzipped)
691  PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
692  PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
693  pf->data(), uw * _pixelsize,
695  if (levelid==0 && _premultiply && _header.hasAlpha())
696  PtexUtils::multalpha(pf->data(), npixels, datatype(),
698  if (useNew) delete [] tmp;
699  }
700  break;
701  }
702 
703  if (!newface) newface = errorData();
704 
705  AtomicStore(&face, newface);
706  increaseMemUsed(newMemUsed);
707 }
708 
709 
710 void PtexReader::getData(int faceid, void* buffer, int stride)
711 {
712  const FaceInfo& f = getFaceInfo(faceid);
713  getData(faceid, buffer, stride, f.res);
714 }
715 
716 
717 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
718 {
719  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
720  PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
721  return;
722  }
723 
724  // note - all locking is handled in called getData methods
725  int resu = res.u(), resv = res.v();
726  int rowlen = _pixelsize * resu;
727  if (stride == 0) stride = rowlen;
728 
729  PtexPtr<PtexFaceData> d ( getData(faceid, res) );
730  if (d->isConstant()) {
731  // fill dest buffer with pixel value
732  PtexUtils::fill(d->getData(), buffer, stride,
733  resu, resv, _pixelsize);
734  }
735  else if (d->isTiled()) {
736  // loop over tiles
737  Res tileres = d->tileRes();
738  int ntilesu = res.ntilesu(tileres);
739  int ntilesv = res.ntilesv(tileres);
740  int tileures = tileres.u();
741  int tilevres = tileres.v();
742  int tilerowlen = _pixelsize * tileures;
743  int tile = 0;
744  char* dsttilerow = (char*) buffer;
745  for (int i = 0; i < ntilesv; i++) {
746  char* dsttile = dsttilerow;
747  for (int j = 0; j < ntilesu; j++) {
748  PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
749  if (t->isConstant())
750  PtexUtils::fill(t->getData(), dsttile, stride,
751  tileures, tilevres, _pixelsize);
752  else
753  PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
754  tilevres, tilerowlen);
755  dsttile += tilerowlen;
756  }
757  dsttilerow += stride * tilevres;
758  }
759  }
760  else {
761  PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
762  }
763 }
764 
765 
767 {
768  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
769  return errorData(/*deleteOnRelease*/ true);
770  }
771 
772  FaceInfo& fi = _faceinfo[faceid];
773  if (fi.isConstant() || fi.res == 0) {
774  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
775  }
776 
777  // get level zero (full) res face
778  Level* level = getLevel(0);
779  FaceData* face = getFace(0, level, faceid, fi.res);
780  return face;
781 }
782 
783 
784 PtexFaceData* PtexReader::getData(int faceid, Res res)
785 {
786  if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
787  return errorData(/*deleteOnRelease*/ true);
788  }
789 
790  FaceInfo& fi = _faceinfo[faceid];
791  if (fi.isConstant() || res == 0) {
792  return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
793  }
794 
795  // determine how many reduction levels are needed
796  int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
797 
798  if (redu == 0 && redv == 0) {
799  // no reduction - get level zero (full) res face
800  Level* level = getLevel(0);
801  FaceData* face = getFace(0, level, faceid, res);
802  return face;
803  }
804 
805  if (redu == redv && !fi.hasEdits()) {
806  // reduction is symmetric and non-negative
807  // and face has no edits => access data from reduction level (if present)
808  int levelid = redu;
809  if (size_t(levelid) < _levels.size()) {
810  Level* level = getLevel(levelid);
811 
812  // get reduction face id
813  int rfaceid = _rfaceids[faceid];
814 
815  // get the face data (if present)
816  FaceData* face = 0;
817  if (size_t(rfaceid) < level->faces.size()) {
818  face = getFace(levelid, level, rfaceid, res);
819  }
820  if (face) {
821  return face;
822  }
823  }
824  }
825 
826  // dynamic reduction required - look in dynamic reduction cache
827  ReductionKey key(faceid, res);
828  FaceData* face = _reductions.get(key);
829  if (face) {
830  return face;
831  }
832 
833  // not found, generate new reduction
834  FaceData *newface = 0;
835  size_t newMemUsed = 0;
836 
837  if (res.ulog2 < 0 || res.vlog2 < 0) {
838  std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
839  newface = errorData();
840  }
841  else if (redu < 0 || redv < 0) {
842  std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
843  newface = errorData();
844  }
845  else if (_header.meshtype == mt_triangle)
846  {
847  if (redu != redv) {
848  std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
849  newface = errorData();
850  }
851  else {
852  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
853  FaceData* src = static_cast<FaceData*>(psrc.get());
854  newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
855  }
856  }
857  else {
858  // determine which direction to blend
859  bool blendu;
860  if (redu == redv) {
861  // for symmetric face blends, alternate u and v blending
862  blendu = (res.ulog2 & 1);
863  }
864  else blendu = redu > redv;
865 
866  if (blendu) {
867  // get next-higher u-res and reduce in u
868  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
869  FaceData* src = static_cast<FaceData*>(psrc.get());
870  newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
871  }
872  else {
873  // get next-higher v-res and reduce in v
874  PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
875  FaceData* src = static_cast<FaceData*>(psrc.get());
876  newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
877  }
878  }
879 
880  size_t tableNewMemUsed = 0;
881  face = _reductions.tryInsert(key, newface, tableNewMemUsed);
882  if (face != newface) {
883  delete newface;
884  }
885  else {
886  increaseMemUsed(newMemUsed + tableNewMemUsed);
887  }
888  return face;
889 }
890 
891 
892 void PtexReader::getPixel(int faceid, int u, int v,
893  float* result, int firstchan, int nchannelsArg)
894 {
895  memset(result, 0, sizeof(*result)*nchannelsArg);
896 
897  // clip nchannels against actual number available
898  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
899  if (nchannelsArg <= 0) return;
900 
901  // get raw pixel data
902  PtexPtr<PtexFaceData> data ( getData(faceid) );
903  void* pixel = alloca(_pixelsize);
904  data->getPixel(u, v, pixel);
905 
906  // adjust for firstchan offset
907  int datasize = DataSize(datatype());
908  if (firstchan)
909  pixel = (char*) pixel + datasize * firstchan;
910 
911  // convert/copy to result as needed
912  if (datatype() == dt_float)
913  memcpy(result, pixel, datasize * nchannelsArg);
914  else
915  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
916 }
917 
918 
919 void PtexReader::getPixel(int faceid, int u, int v,
920  float* result, int firstchan, int nchannelsArg,
921  Ptex::Res res)
922 {
923  memset(result, 0, nchannelsArg);
924 
925  // clip nchannels against actual number available
926  nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
927  if (nchannelsArg <= 0) return;
928 
929  // get raw pixel data
930  PtexPtr<PtexFaceData> data ( getData(faceid, res) );
931  void* pixel = alloca(_pixelsize);
932  data->getPixel(u, v, pixel);
933 
934  // adjust for firstchan offset
935  int datasize = DataSize(datatype());
936  if (firstchan)
937  pixel = (char*) pixel + datasize * firstchan;
938 
939  // convert/copy to result as needed
940  if (datatype() == dt_float)
941  memcpy(result, pixel, datasize * nchannelsArg);
942  else
943  ConvertToFloat(result, pixel, datatype(), nchannelsArg);
944 }
945 
946 
949  size_t& newMemUsed)
950 {
951  // allocate a new face and reduce image
952  DataType dt = r->datatype();
953  int nchan = r->nchannels();
954  int memsize = _pixelsize * newres.size();
955  PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
956  newMemUsed = sizeof(PackedFace) + memsize;
957  // reduce and copy into new face
958  reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
959  pf->_data, _pixelsize * newres.u(), dt, nchan);
960  return pf;
961 }
962 
963 
964 
966 {
967  // must make a new constant face (even though it's identical to this one)
968  // because it will be owned by a different reduction level
969  // and will therefore have a different parent
971  newMemUsed = sizeof(ConstantFace) + _pixelsize;
972  memcpy(pf->_data, _data, _pixelsize);
973  return pf;
974 }
975 
976 
979  size_t& newMemUsed)
980 {
981  /* Tiled reductions should generally only be anisotropic (just u
982  or v, not both) since isotropic reductions are precomputed and
983  stored on disk. (This function should still work for isotropic
984  reductions though.)
985 
986  In the anisotropic case, the number of tiles should be kept the
987  same along the direction not being reduced in order to preserve
988  the laziness of the file access. In contrast, if reductions
989  were not tiled, then any reduction would read all the tiles and
990  defeat the purpose of tiling.
991  */
992 
993  // keep new face local until fully initialized
994  FaceData* newface = 0;
995 
996  // don't tile triangle reductions (too complicated)
997  Res newtileres;
998  bool isTriangle = r->_header.meshtype == mt_triangle;
999  if (isTriangle) {
1000  newtileres = newres;
1001  }
1002  else {
1003  // propagate the tile res to the reduction
1004  newtileres = _tileres;
1005  // but make sure tile isn't larger than the new face!
1006  if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1007  if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1008  }
1009 
1010 
1011  // determine how many tiles we will have on the reduction
1012  int newntiles = newres.ntiles(newtileres);
1013 
1014  if (newntiles == 1) {
1015  // no need to keep tiling, reduce tiles into a single face
1016  // first, get all tiles and check if they are constant (with the same value)
1017  PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1018  bool allConstant = true;
1019  for (int i = 0; i < _ntiles; i++) {
1020  PtexFaceData* tile = tiles[i] = getTile(i);
1021  allConstant = (allConstant && tile->isConstant() &&
1022  (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1023  _pixelsize))));
1024  }
1025  if (allConstant) {
1026  // allocate a new constant face
1027  newface = new ConstantFace(_pixelsize);
1028  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1029  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1030  }
1031  else if (isTriangle) {
1032  // reassemble all tiles into temporary contiguous image
1033  // (triangle reduction doesn't work on tiles)
1034  int tileures = _tileres.u();
1035  int tilevres = _tileres.v();
1036  int sstride = _pixelsize * tileures;
1037  int dstride = sstride * _ntilesu;
1038  int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1039 
1040  char* tmp = new char [_ntiles * _tileres.size() * _pixelsize];
1041  char* tmpptr = tmp;
1042  for (int i = 0; i < _ntiles;) {
1043  PtexFaceData* tile = tiles[i];
1044  if (tile->isConstant())
1045  PtexUtils::fill(tile->getData(), tmpptr, dstride,
1046  tileures, tilevres, _pixelsize);
1047  else
1048  PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1049  i++;
1050  tmpptr += (i%_ntilesu) ? sstride : dstepv;
1051  }
1052 
1053  // allocate a new packed face
1054  int memsize = _pixelsize * newres.size();
1055  newface = new PackedFace(newres, _pixelsize, memsize);
1056  newMemUsed = sizeof(PackedFace) + memsize;
1057  // reduce and copy into new face
1058  reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1059  newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1060 
1061  delete [] tmp;
1062  }
1063  else {
1064  // allocate a new packed face
1065  int memsize = _pixelsize * newres.size();
1066  newface = new PackedFace(newres, _pixelsize, memsize);
1067  newMemUsed = sizeof(PackedFace) + memsize;
1068 
1069  int tileures = _tileres.u();
1070  int tilevres = _tileres.v();
1071  int sstride = _pixelsize * tileures;
1072  int dstride = _pixelsize * newres.u();
1073  int dstepu = dstride/_ntilesu;
1074  int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1075 
1076  char* dst = (char*) newface->getData();
1077  for (int i = 0; i < _ntiles;) {
1078  PtexFaceData* tile = tiles[i];
1079  if (tile->isConstant())
1080  PtexUtils::fill(tile->getData(), dst, dstride,
1081  newres.u()/_ntilesu, newres.v()/_ntilesv,
1082  _pixelsize);
1083  else
1084  reducefn(tile->getData(), sstride, tileures, tilevres,
1085  dst, dstride, _dt, _nchan);
1086  i++;
1087  dst += (i%_ntilesu) ? dstepu : dstepv;
1088  }
1089  }
1090  // release the tiles
1091  for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1092  }
1093  else {
1094  // otherwise, tile the reduced face
1095  TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
1096  newface = tf;
1097  newMemUsed = tf->memUsed();
1098  }
1099  return newface;
1100 }
1101 
1102 
1103 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1104 {
1105  int tileu = ui >> _tileres.ulog2;
1106  int tilev = vi >> _tileres.vlog2;
1107  PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1108  tile->getPixel(ui - (tileu<<_tileres.ulog2),
1109  vi - (tilev<<_tileres.vlog2), result);
1110 }
1111 
1112 
1113 
1115 {
1116  FaceData*& face = _tiles[tile];
1117  if (face) {
1118  return face;
1119  }
1120 
1121  // first, get all parent tiles for this tile
1122  // and check if they are constant (with the same value)
1123  int pntilesu = _parentface->ntilesu();
1124  int pntilesv = _parentface->ntilesv();
1125  int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1126  int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1127 
1128  int ntilesval = nu*nv; // num parent tiles for this tile
1129  PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
1130  bool allConstant = true;
1131  int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1132  for (int i = 0; i < ntilesval;) {
1133  PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
1134  allConstant = (allConstant && tileval->isConstant() &&
1135  (i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
1136  _pixelsize))));
1137  i++;
1138  ptile += (i%nu)? 1 : pntilesu - nu + 1;
1139  }
1140 
1141  FaceData* newface = 0;
1142  size_t newMemUsed = 0;
1143  if (allConstant) {
1144  // allocate a new constant face
1145  newface = new ConstantFace(_pixelsize);
1146  newMemUsed = sizeof(ConstantFace) + _pixelsize;
1147  memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1148  }
1149  else {
1150  // allocate a new packed face for the tile
1151  int memsize = _pixelsize*_tileres.size();
1152  newface = new PackedFace(_tileres, _pixelsize, memsize);
1153  newMemUsed = sizeof(PackedFace) + memsize;
1154 
1155  // generate reduction from parent tiles
1156  int ptileures = _parentface->tileres().u();
1157  int ptilevres = _parentface->tileres().v();
1158  int sstride = ptileures * _pixelsize;
1159  int dstride = _tileres.u() * _pixelsize;
1160  int dstepu = dstride/nu;
1161  int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1162 
1163  char* dst = (char*) newface->getData();
1164  for (int i = 0; i < ntilesval;) {
1165  PtexFaceData* tileval = tiles[i];
1166  if (tileval->isConstant())
1167  PtexUtils::fill(tileval->getData(), dst, dstride,
1168  _tileres.u()/nu, _tileres.v()/nv,
1169  _pixelsize);
1170  else
1171  _reducefn(tileval->getData(), sstride, ptileures, ptilevres,
1172  dst, dstride, _dt, _nchan);
1173  i++;
1174  dst += (i%nu) ? dstepu : dstepv;
1175  }
1176  }
1177 
1178  if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
1179  delete newface;
1180  }
1181  else {
1182  _reader->increaseMemUsed(newMemUsed);
1183  }
1184 
1185  return face;
1186 }
1187 
uint32_t levelheadersize
Definition: PtexIO.h:76
const int AllocaMax
Definition: PtexIO.h:114
ExtHeader _extheader
Definition: PtexReader.h:649
std::vector< char > _errorPixel
Definition: PtexReader.h:714
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:965
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:360
const int HeaderSize
Definition: PtexIO.h:103
const int FaceDataHeaderSize
Definition: PtexIO.h:106
uint32_t metadatamemsize
Definition: PtexIO.h:59
uint32_t meshtype
Definition: PtexIO.h:46
uint32_t metadatamemsize
Definition: PtexIO.h:99
std::vector< Entry * > _entries
Definition: PtexReader.h:341
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:265
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.h:174
PtexInputHandler * _io
Definition: PtexReader.h:639
void readFaceInfo()
Definition: PtexReader.cpp:277
Memory-managed string.
Definition: Ptexture.h:308
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition: PtexReader.cpp:267
uint32_t nfaces
Definition: PtexIO.h:77
void logOpen()
Definition: PtexReader.h:72
uint16_t nlevels
Definition: PtexIO.h:50
void readLevelInfo()
Definition: PtexReader.cpp:298
uint64_t editdatapos
Definition: PtexIO.h:72
uint64_t leveldatasize
Definition: PtexIO.h:57
int32_t alphachan
Definition: PtexIO.h:48
Definition: PtexIO.h:43
FilePos _leveldatapos
Definition: PtexReader.h:653
uint32_t blocksize() const
Definition: PtexIO.h:83
Meta data accessor.
Definition: Ptexture.h:341
const uint32_t Magic
Definition: PtexIO.h:102
uint32_t metadatazipsize
Definition: PtexIO.h:58
void clear()
Definition: PtexHashMap.h:195
MetaData * _metadata
Definition: PtexReader.h:660
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:416
void closeFP()
Definition: PtexReader.cpp:230
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexReader.cpp:71
size_t memUsed()
Definition: PtexReader.h:537
void readConstData()
Definition: PtexReader.cpp:319
bool readBlock(void *data, int size, bool reportError=true)
Definition: PtexReader.cpp:548
std::vector< FilePos > offsets
Definition: PtexReader.h:523
int pixelSize() const
Definition: PtexIO.h:60
std::string _path
Definition: PtexReader.h:647
uint8_t * _constdata
Definition: PtexReader.h:659
void readLevel(int levelid, Level *&level)
Definition: PtexReader.cpp:594
bool trylock()
Definition: PtexPlatform.h:132
std::vector< FilePos > _levelpos
Definition: PtexReader.h:666
Single-precision (32-bit) floating point.
Definition: Ptexture.h:89
T min(T a, T b)
Definition: PtexUtils.h:147
virtual PtexMetaData * getMetaData()
Access meta data.
Definition: PtexReader.cpp:335
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:414
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:978
const int EditMetaDataHeaderSize
Definition: PtexIO.h:108
Platform-specific classes, functions, and includes.
virtual Handle open(const char *path)=0
Open a file in read mode.
LargeMetaData * lmdData
Definition: PtexReader.h:290
uint32_t faceid
Definition: PtexIO.h:93
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:624
bool _needToOpen
Definition: PtexReader.h:643
size_t _baseMemUsed
Definition: PtexReader.h:717
std::vector< uint32_t > _rfaceids
Definition: PtexReader.h:664
const char * c_str() const
Definition: Ptexture.h:317
ReductionMap _reductions
Definition: PtexReader.h:713
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
off_t FilePos
Definition: PtexPlatform.h:89
virtual void reportError(const char *error)=0
uint32_t constdatasize
Definition: PtexIO.h:54
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:400
FaceData * errorData(bool deleteOnRelease=false)
Definition: PtexReader.h:600
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:117
void readFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.cpp:626
z_stream_s _zstream
Definition: PtexReader.h:716
Per-face texture data accessor.
Definition: Ptexture.h:419
Encoding encoding() const
Definition: PtexIO.h:84
void increaseMemUsed(size_t amount)
Definition: PtexReader.h:71
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:671
uint32_t magic
Definition: PtexIO.h:44
virtual void * getData()=0
Access the data from this data block.
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition: PtexReader.cpp:59
FilePos _lmdheaderpos
Definition: PtexReader.h:655
FaceInfo faceinfo
Definition: PtexIO.h:94
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
uint32_t faceinfosize
Definition: PtexIO.h:53
uint64_t editdatasize
Definition: PtexIO.h:71
int ntilesu(Res tileres) const
Determine the number of tiles in the u direction for the given tile res.
Definition: Ptexture.h:219
void readTile(int tile, FaceData *&data)
Definition: PtexReader.cpp:634
void readMetaData()
Definition: PtexReader.cpp:381
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:440
virtual ~PtexReader()
Definition: PtexReader.cpp:93
std::vector< MetaEdit > _metaedits
Definition: PtexReader.h:675
uint32_t extheadersize
Definition: PtexIO.h:52
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition: PtexReader.h:605
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:268
void addLmdEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, FilePos filepos, uint32_t zipsize, size_t &metaDataMemUsed)
Definition: PtexReader.h:255
Mutex readlock
Definition: PtexReader.h:637
bool hasAlpha() const
Definition: PtexIO.h:61
T * get()
Get pointer value.
Definition: Ptexture.h:1061
bool _hasEdits
Definition: PtexReader.h:661
void prune()
Definition: PtexReader.cpp:104
FilePos _faceinfopos
Definition: PtexReader.h:650
bool needToOpen() const
Definition: PtexReader.h:57
uint64_t lmddatasize
Definition: PtexIO.h:70
void setError(const char *error)
Definition: PtexReader.h:546
Mesh is triangle-based.
Definition: Ptexture.h:80
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexReader.h:56
PtexErrorHandler * _err
Definition: PtexReader.h:640
FilePos _editdatapos
Definition: PtexReader.h:657
virtual const char * lastError()=0
Return the last error message encountered.
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition: PtexReader.h:246
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition: PtexReader.cpp:563
std::vector< FaceEdit > _faceedits
Definition: PtexReader.h:683
FilePos _levelinfopos
Definition: PtexReader.h:652
FaceDataHeader fdh
Definition: PtexIO.h:95
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition: PtexReader.cpp:710
bool _premultiply
Definition: PtexReader.h:641
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
const int EditFaceDataHeaderSize
Definition: PtexIO.h:107
FilePos _constdatapos
Definition: PtexReader.h:651
std::vector< Level * > _levels
Definition: PtexReader.h:667
T max(T a, T b)
Definition: PtexUtils.h:150
std::vector< FaceDataHeader > fdh
Definition: PtexReader.h:522
Level * getLevel(int levelid)
Definition: PtexReader.h:572
PtexInputHandler::Handle _fp
Definition: PtexReader.h:645
std::vector< FaceInfo > _faceinfo
Definition: PtexReader.h:663
virtual void getPixel(int faceid, int u, int v, float *result, int firstchan, int nchannels)
Access a single texel from the highest resolution texture .
Definition: PtexReader.cpp:892
void purge()
Definition: PtexReader.cpp:115
Entry * getEntry(int index)
Definition: PtexReader.cpp:343
std::vector< FaceDataHeader > _fdh
Definition: PtexReader.h:493
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.h:580
uint32_t lmdheaderzipsize
Definition: PtexIO.h:68
virtual const char * path()=0
Path that file was opened with.
bool tryClose()
Definition: PtexReader.cpp:219
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:327
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1045
virtual bool isTiled()=0
True if this data block is tiled.
const int LevelInfoSize
Definition: PtexIO.h:105
FilePos _metadatapos
Definition: PtexReader.h:654
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition: PtexReader.cpp:640
Header _header
Definition: PtexReader.h:648
virtual bool isConstant()=0
True if this data block is constant.
int _pixelsize
Definition: PtexReader.h:658
virtual void getPixel(int u, int v, void *result)=0
Read a single texel from the data block.
volatile size_t _memUsed
Definition: PtexReader.h:718
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
FaceDataHeader fdh
Definition: PtexReader.h:681
Interface for reading data from a ptex file.
Definition: Ptexture.h:470
std::vector< FilePos > _offsets
Definition: PtexReader.h:494
uint8_t * getConstData()
Definition: PtexReader.h:579
DataType datatype() const
Definition: PtexReader.h:113
uint16_t nchannels
Definition: PtexIO.h:49
Pixel resolution of a given texture.
Definition: Ptexture.h:172
const int ExtHeaderSize
Definition: PtexIO.h:104
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:43
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:948
bool open(const char *path, Ptex::String &error)
Definition: PtexReader.cpp:137
bool LittleEndian()
Definition: PtexIO.h:117
void unlock()
Definition: PtexPlatform.h:133
uint32_t nfaces
Definition: PtexIO.h:51
int DataSize(DataType dt)
Look up size of given data type (in bytes).
Definition: Ptexture.h:143
int nchannels() const
Definition: PtexReader.h:114
std::vector< LevelInfo > _levelinfo
Definition: PtexReader.h:665
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:573
std::vector< FaceData * > faces
Definition: PtexReader.h:524
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:242
uint32_t version
Definition: PtexIO.h:45
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:183
void readEditFaceData()
Definition: PtexReader.cpp:502
void readEditData()
Definition: PtexReader.cpp:468
void seek(FilePos pos)
Definition: PtexReader.h:558
DataType
Type of data stored in texture file.
Definition: Ptexture.h:85
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:274
uint32_t lmdheadermemsize
Definition: PtexIO.h:69
uint32_t metadatazipsize
Definition: PtexIO.h:98
const int BlockSize
Definition: PtexIO.h:112
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
virtual bool close(Handle handle)=0
Close a file.
bool reopenFP()
Definition: PtexReader.cpp:240
void readEditMetaData()
Definition: PtexReader.cpp:533
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:432
FilePos tell()
Definition: PtexReader.h:557
FilePos _pos
Definition: PtexReader.h:646
Public API classes for reading, writing, caching, and filtering Ptex files.
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition: PtexHashMap.h:224
uint32_t levelinfosize
Definition: PtexIO.h:55
bool _pendingPurge
Definition: PtexReader.h:644
PtexReader * _reader
Definition: PtexReader.h:338
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:632
FilePos _lmddatapos
Definition: PtexReader.h:656
virtual Ptex::Res tileRes()=0
Resolution of each tile in this data block.
Value get(Key &key)
Definition: PtexHashMap.h:203