Ptex: PtexReader.cpp Source File

Ptex

PtexReader.cpp
Go to the documentation of this file.
1/*
2PTEX SOFTWARE
3Copyright 2014 Disney Enterprises, Inc. All rights reserved
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
22Disclaimer: THIS SOFTWARE IS PROVIDED BY WALT DISNEY PICTURES AND
23CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE ARE DISCLAIMED.
26IN NO EVENT SHALL WALT DISNEY PICTURES, THE COPYRIGHT HOLDER OR
27CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND BASED ON ANY
31THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33OF 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
45namespace {
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
57 PTEX_NAMESPACE_BEGIN
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
71PtexReader::PtexReader(bool premultiply, PtexInputHandler* io, PtexErrorHandler* err)
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
93PtexReader::~PtexReader()
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
104 void PtexReader::prune()
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();
111 _memUsed = _baseMemUsed;
112}
113
114
115 void PtexReader::purge()
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));
156 readBlock(&_header, HeaderSize);
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 }
172 _pixelsize = _header.pixelSize();
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));
182 readBlock(&_extheader, PtexUtils::min(uint32_t(ExtHeaderSize), _header.extheadersize));
183
184 // compute offsets of various blocks
185 FilePos pos = HeaderSize + _header.extheadersize;
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
192 _lmdheaderpos = pos; pos += _extheader.lmdheaderzipsize;
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)
197 _editdatapos = PtexUtils::max(FilePos(_extheader.editdatapos), pos);
198
199 // read basic file info
200 readFaceInfo();
201 readConstData();
202 readLevelInfo();
203 readEditData();
204 _baseMemUsed = _memUsed;
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
219 bool PtexReader::tryClose()
220{
221 if (_fp) {
222 if (!readlock.trylock()) return false;
223 closeFP();
224 readlock.unlock();
225 }
226 return true;
227}
228
229
230 void PtexReader::closeFP()
231{
232 if (_fp) {
233 _io->close(_fp);
234 _fp = 0;
235 }
236 inflateEnd(&_zstream);
237}
238
239
240 bool PtexReader::reopenFP()
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
267 const Ptex::FaceInfo& PtexReader::getFaceInfo(int faceid)
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
277 void PtexReader::readFaceInfo()
278{
279 if (_faceinfo.empty()) {
280 // read compressed face info block
281 seek(_faceinfopos);
282 int nfaces = _header.nfaces;
283 _faceinfo.resize(nfaces);
284 readZipBlock(&_faceinfo[0], _header.faceinfosize,
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
298 void PtexReader::readLevelInfo()
299{
300 if (_levelinfo.empty()) {
301 // read level info block
302 seek(_levelinfopos);
303 _levelinfo.resize(_header.nlevels);
304 readBlock(&_levelinfo[0], LevelInfoSize*_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
319 void PtexReader::readConstData()
320{
321 if (!_constdata) {
322 // read compressed constant data block
323 seek(_constdatapos);
324 int size = _pixelsize * _header.nfaces;
325 _constdata = new uint8_t[size];
326 readZipBlock(_constdata, _header.constdatasize, size);
327 if (_premultiply && _header.hasAlpha())
328 PtexUtils::multalpha(_constdata, _header.nfaces, datatype(),
329 _header.nchannels, _header.alphachan);
330 increaseMemUsed(size);
331 }
332}
333
334
335 PtexMetaData* PtexReader::getMetaData()
336{
337 if (!_metadata) readMetaData();
338 return _metadata;
339}
340
341
342 PtexReader::MetaData::Entry*
343PtexReader::MetaData::getEntry(int index)
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();
371 _reader->increaseMemUsed(sizeof(LargeMetaData) + e->datasize);
372 _reader->seek(e->lmdPos);
373 _reader->readZipBlock(e->data, e->lmdZipSize, e->datasize);
374 // update entry
375 e->lmdData = lmdData;
376 return e;
377 }
378}
379
380
381 void PtexReader::readMetaData()
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
394 if (_header.metadatamemsize)
395 readMetaDataBlock(newmeta, _metadatapos,
396 _header.metadatazipsize, _header.metadatamemsize, metaDataMemUsed);
397
398 // read large meta data headers
399 if (_extheader.lmdheadermemsize)
400 readLargeMetaDataHeaders(newmeta, _lmdheaderpos,
401 _extheader.lmdheaderzipsize, _extheader.lmdheadermemsize, metaDataMemUsed);
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
468 void PtexReader::readEditData()
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
502 void PtexReader::readEditFaceData()
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(),
520 _header.nchannels, _header.alphachan);
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
533 void PtexReader::readEditMetaData()
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 && size >= 0);
551 if (!_fp || size < 0) 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 (zipsize < 0 || unzipsize < 0) return false;
566 if (!_zstream.state) {
567 inflateInit(&_zstream);
568 }
569
570 void* buff = alloca(BlockSize);
571 _zstream.next_out = (Bytef*) data;
572 _zstream.avail_out = unzipsize;
573
574 while (1) {
575 int size = (zipsize < BlockSize) ? zipsize : BlockSize;
576 zipsize -= size;
577 if (!readBlock(buff, size)) break;
578 _zstream.next_in = (Bytef*) buff;
579 _zstream.avail_in = size;
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");
584 inflateReset(&_zstream);
585 return 0;
586 }
587 }
588
589 int total = (int)_zstream.total_out;
590 inflateReset(&_zstream);
591 return total == unzipsize;
592}
593
594
595 void PtexReader::readLevel(int levelid, Level*& level)
596{
597 // get read lock and make sure we still need to read
598 AutoMutex locker(readlock);
599 if (level) {
600 return;
601 }
602
603 // go ahead and read the level
604 LevelInfo& l = _levelinfo[levelid];
605
606 // keep new level local until finished
607 Level* newlevel = new Level(l.nfaces);
608 seek(_levelpos[levelid]);
609 readZipBlock(&newlevel->fdh[0], l.levelheadersize, FaceDataHeaderSize * l.nfaces);
610 computeOffsets(tell(), l.nfaces, &newlevel->fdh[0], &newlevel->offsets[0]);
611
612 // apply edits (if any) to level 0
613 if (levelid == 0) {
614 for (size_t i = 0, size = _faceedits.size(); i < size; i++) {
615 FaceEdit& e = _faceedits[i];
616 newlevel->fdh[e.faceid] = e.fdh;
617 newlevel->offsets[e.faceid] = e.pos;
618 }
619 }
620
621 // don't assign to result until level data is fully initialized
622 AtomicStore(&level, newlevel);
623 increaseMemUsed(level->memUsed());
624}
625
626
627 void PtexReader::readFace(int levelid, Level* level, int faceid, Ptex::Res res)
628{
629 FaceData*& face = level->faces[faceid];
630 FaceDataHeader fdh = level->fdh[faceid];
631 readFaceData(level->offsets[faceid], fdh, res, levelid, face);
632}
633
634
635 void PtexReader::TiledFace::readTile(int tile, FaceData*& data)
636{
637 _reader->readFaceData(_offsets[tile], _fdh[tile], _tileres, _levelid, data);
638}
639
640
641 void PtexReader::readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid,
642 FaceData*& face)
643{
644 AutoMutex locker(readlock);
645 if (face) {
646 return;
647 }
648
649 // keep new face local until fully initialized
650 FaceData* newface = 0;
651 size_t newMemUsed = 0;
652
653 seek(pos);
654 switch (fdh.encoding()) {
655 case enc_constant:
656 {
657 ConstantFace* cf = new ConstantFace(_pixelsize);
658 newface = cf;
659 newMemUsed = sizeof(ConstantFace) + _pixelsize;
660 readBlock(cf->data(), _pixelsize);
661 if (levelid==0 && _premultiply && _header.hasAlpha())
662 PtexUtils::multalpha(cf->data(), 1, datatype(),
663 _header.nchannels, _header.alphachan);
664 }
665 break;
666 case enc_tiled:
667 {
668 Res tileres;
669 readBlock(&tileres, sizeof(tileres));
670 uint32_t tileheadersize;
671 readBlock(&tileheadersize, sizeof(tileheadersize));
672 TiledFace* tf = new TiledFace(this, res, tileres, levelid);
673 newface = tf;
674 newMemUsed = tf->memUsed();
675 readZipBlock(&tf->_fdh[0], tileheadersize, FaceDataHeaderSize * tf->_ntiles);
676 computeOffsets(tell(), tf->_ntiles, &tf->_fdh[0], &tf->_offsets[0]);
677 }
678 break;
679 case enc_zipped:
680 case enc_diffzipped:
681 {
682 int uw = res.u(), vw = res.v();
683 int npixels = uw * vw;
684 int unpackedSize = _pixelsize * npixels;
685 PackedFace* pf = new PackedFace(res, _pixelsize, unpackedSize);
686 newface = pf;
687 newMemUsed = sizeof(PackedFace) + unpackedSize;
688 bool useNew = unpackedSize > AllocaMax;
689 char* tmp = useNew ? new char [unpackedSize] : (char*) alloca(unpackedSize);
690 readZipBlock(tmp, fdh.blocksize(), unpackedSize);
691 if (fdh.encoding() == enc_diffzipped)
692 PtexUtils::decodeDifference(tmp, unpackedSize, datatype());
693 PtexUtils::interleave(tmp, uw * DataSize(datatype()), uw, vw,
694 pf->data(), uw * _pixelsize,
695 datatype(), _header.nchannels);
696 if (levelid==0 && _premultiply && _header.hasAlpha())
697 PtexUtils::multalpha(pf->data(), npixels, datatype(),
698 _header.nchannels, _header.alphachan);
699 if (useNew) delete [] tmp;
700 }
701 break;
702 }
703
704 if (!newface) newface = errorData();
705
706 AtomicStore(&face, newface);
707 increaseMemUsed(newMemUsed);
708}
709
710
711 void PtexReader::getData(int faceid, void* buffer, int stride)
712{
713 const FaceInfo& f = getFaceInfo(faceid);
714 getData(faceid, buffer, stride, f.res);
715}
716
717
718 void PtexReader::getData(int faceid, void* buffer, int stride, Res res)
719{
720 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
721 PtexUtils::fill(&_errorPixel[0], buffer, stride, res.u(), res.v(), _pixelsize);
722 return;
723 }
724
725 // note - all locking is handled in called getData methods
726 int resu = res.u(), resv = res.v();
727 int rowlen = _pixelsize * resu;
728 if (stride == 0) stride = rowlen;
729
730 PtexPtr<PtexFaceData> d ( getData(faceid, res) );
731 if (d->isConstant()) {
732 // fill dest buffer with pixel value
733 PtexUtils::fill(d->getData(), buffer, stride,
734 resu, resv, _pixelsize);
735 }
736 else if (d->isTiled()) {
737 // loop over tiles
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();
743 int tilerowlen = _pixelsize * tileures;
744 int tile = 0;
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++) {
749 PtexPtr<PtexFaceData> t ( d->getTile(tile++) );
750 if (t->isConstant())
751 PtexUtils::fill(t->getData(), dsttile, stride,
752 tileures, tilevres, _pixelsize);
753 else
754 PtexUtils::copy(t->getData(), tilerowlen, dsttile, stride,
755 tilevres, tilerowlen);
756 dsttile += tilerowlen;
757 }
758 dsttilerow += stride * tilevres;
759 }
760 }
761 else {
762 PtexUtils::copy(d->getData(), rowlen, buffer, stride, resv, rowlen);
763 }
764}
765
766
767 PtexFaceData* PtexReader::getData(int faceid)
768{
769 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
770 return errorData(/*deleteOnRelease*/ true);
771 }
772
773 FaceInfo& fi = _faceinfo[faceid];
774 if (fi.isConstant() || fi.res == 0) {
775 return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
776 }
777
778 // get level zero (full) res face
779 Level* level = getLevel(0);
780 FaceData* face = getFace(0, level, faceid, fi.res);
781 return face;
782}
783
784
785 PtexFaceData* PtexReader::getData(int faceid, Res res)
786{
787 if (!_ok || faceid < 0 || size_t(faceid) >= _header.nfaces) {
788 return errorData(/*deleteOnRelease*/ true);
789 }
790
791 FaceInfo& fi = _faceinfo[faceid];
792 if (fi.isConstant() || res == 0) {
793 return new ConstDataPtr(getConstData() + faceid * _pixelsize, _pixelsize);
794 }
795
796 // determine how many reduction levels are needed
797 int redu = fi.res.ulog2 - res.ulog2, redv = fi.res.vlog2 - res.vlog2;
798
799 if (redu == 0 && redv == 0) {
800 // no reduction - get level zero (full) res face
801 Level* level = getLevel(0);
802 FaceData* face = getFace(0, level, faceid, res);
803 return face;
804 }
805
806 if (redu == redv && !fi.hasEdits()) {
807 // reduction is symmetric and non-negative
808 // and face has no edits => access data from reduction level (if present)
809 int levelid = redu;
810 if (size_t(levelid) < _levels.size()) {
811 Level* level = getLevel(levelid);
812
813 // get reduction face id
814 int rfaceid = _rfaceids[faceid];
815
816 // get the face data (if present)
817 FaceData* face = 0;
818 if (size_t(rfaceid) < level->faces.size()) {
819 face = getFace(levelid, level, rfaceid, res);
820 }
821 if (face) {
822 return face;
823 }
824 }
825 }
826
827 // dynamic reduction required - look in dynamic reduction cache
828 ReductionKey key(faceid, res);
829 FaceData* face = _reductions.get(key);
830 if (face) {
831 return face;
832 }
833
834 // not found, generate new reduction
835 FaceData *newface = 0;
836 size_t newMemUsed = 0;
837
838 if (res.ulog2 < 0 || res.vlog2 < 0) {
839 std::cerr << "PtexReader::getData - reductions below 1 pixel not supported" << std::endl;
840 newface = errorData();
841 }
842 else if (redu < 0 || redv < 0) {
843 std::cerr << "PtexReader::getData - enlargements not supported" << std::endl;
844 newface = errorData();
845 }
846 else if (_header.meshtype == mt_triangle)
847 {
848 if (redu != redv) {
849 std::cerr << "PtexReader::getData - anisotropic reductions not supported for triangle mesh" << std::endl;
850 newface = errorData();
851 }
852 else {
853 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)(res.vlog2+1))) );
854 FaceData* src = static_cast<FaceData*>(psrc.get());
855 newface = src->reduce(this, res, PtexUtils::reduceTri, newMemUsed);
856 }
857 }
858 else {
859 // determine which direction to blend
860 bool blendu;
861 if (redu == redv) {
862 // for symmetric face blends, alternate u and v blending
863 blendu = (res.ulog2 & 1);
864 }
865 else blendu = redu > redv;
866
867 if (blendu) {
868 // get next-higher u-res and reduce in u
869 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)(res.ulog2+1), (int8_t)res.vlog2)) );
870 FaceData* src = static_cast<FaceData*>(psrc.get());
871 newface = src->reduce(this, res, PtexUtils::reduceu, newMemUsed);
872 }
873 else {
874 // get next-higher v-res and reduce in v
875 PtexPtr<PtexFaceData> psrc ( getData(faceid, Res((int8_t)res.ulog2, (int8_t)(res.vlog2+1))) );
876 FaceData* src = static_cast<FaceData*>(psrc.get());
877 newface = src->reduce(this, res, PtexUtils::reducev, newMemUsed);
878 }
879 }
880
881 size_t tableNewMemUsed = 0;
882 face = _reductions.tryInsert(key, newface, tableNewMemUsed);
883 if (face != newface) {
884 delete newface;
885 }
886 else {
887 increaseMemUsed(newMemUsed + tableNewMemUsed);
888 }
889 return face;
890}
891
892
893 void PtexReader::getPixel(int faceid, int u, int v,
894 float* result, int firstchan, int nchannelsArg)
895{
896 memset(result, 0, sizeof(*result)*nchannelsArg);
897
898 // clip nchannels against actual number available
899 nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
900 if (nchannelsArg <= 0) return;
901
902 // get raw pixel data
903 PtexPtr<PtexFaceData> data ( getData(faceid) );
904 void* pixel = alloca(_pixelsize);
905 data->getPixel(u, v, pixel);
906
907 // adjust for firstchan offset
908 int datasize = DataSize(datatype());
909 if (firstchan)
910 pixel = (char*) pixel + datasize * firstchan;
911
912 // convert/copy to result as needed
913 if (datatype() == dt_float)
914 memcpy(result, pixel, datasize * nchannelsArg);
915 else
916 ConvertToFloat(result, pixel, datatype(), nchannelsArg);
917}
918
919
920 void PtexReader::getPixel(int faceid, int u, int v,
921 float* result, int firstchan, int nchannelsArg,
922 Ptex::Res res)
923{
924 memset(result, 0, nchannelsArg);
925
926 // clip nchannels against actual number available
927 nchannelsArg = PtexUtils::min(nchannelsArg, _header.nchannels-firstchan);
928 if (nchannelsArg <= 0) return;
929
930 // get raw pixel data
931 PtexPtr<PtexFaceData> data ( getData(faceid, res) );
932 void* pixel = alloca(_pixelsize);
933 data->getPixel(u, v, pixel);
934
935 // adjust for firstchan offset
936 int datasize = DataSize(datatype());
937 if (firstchan)
938 pixel = (char*) pixel + datasize * firstchan;
939
940 // convert/copy to result as needed
941 if (datatype() == dt_float)
942 memcpy(result, pixel, datasize * nchannelsArg);
943 else
944 ConvertToFloat(result, pixel, datatype(), nchannelsArg);
945}
946
947
948 PtexReader::FaceData*
949PtexReader::PackedFace::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
950 size_t& newMemUsed)
951{
952 // allocate a new face and reduce image
953 DataType dt = r->datatype();
954 int nchan = r->nchannels();
955 int memsize = _pixelsize * newres.size();
956 PackedFace* pf = new PackedFace(newres, _pixelsize, memsize);
957 newMemUsed = sizeof(PackedFace) + memsize;
958 // reduce and copy into new face
959 reducefn(_data, _pixelsize * _res.u(), _res.u(), _res.v(),
960 pf->_data, _pixelsize * newres.u(), dt, nchan);
961 return pf;
962}
963
964
965
966 PtexReader::FaceData* PtexReader::ConstantFace::reduce(PtexReader*, Res, PtexUtils::ReduceFn, size_t& newMemUsed)
967{
968 // must make a new constant face (even though it's identical to this one)
969 // because it will be owned by a different reduction level
970 // and will therefore have a different parent
971 ConstantFace* pf = new ConstantFace(_pixelsize);
972 newMemUsed = sizeof(ConstantFace) + _pixelsize;
973 memcpy(pf->_data, _data, _pixelsize);
974 return pf;
975}
976
977
978 PtexReader::FaceData*
979PtexReader::TiledFaceBase::reduce(PtexReader* r, Res newres, PtexUtils::ReduceFn reducefn,
980 size_t& newMemUsed)
981{
982 /* Tiled reductions should generally only be anisotropic (just u
983 or v, not both) since isotropic reductions are precomputed and
984 stored on disk. (This function should still work for isotropic
985 reductions though.)
986
987 In the anisotropic case, the number of tiles should be kept the
988 same along the direction not being reduced in order to preserve
989 the laziness of the file access. In contrast, if reductions
990 were not tiled, then any reduction would read all the tiles and
991 defeat the purpose of tiling.
992 */
993
994 // keep new face local until fully initialized
995 FaceData* newface = 0;
996
997 // don't tile triangle reductions (too complicated)
998 Res newtileres;
999 bool isTriangle = r->_header.meshtype == mt_triangle;
1000 if (isTriangle) {
1001 newtileres = newres;
1002 }
1003 else {
1004 // propagate the tile res to the reduction
1005 newtileres = _tileres;
1006 // but make sure tile isn't larger than the new face!
1007 if (newtileres.ulog2 > newres.ulog2) newtileres.ulog2 = newres.ulog2;
1008 if (newtileres.vlog2 > newres.vlog2) newtileres.vlog2 = newres.vlog2;
1009 }
1010
1011
1012 // determine how many tiles we will have on the reduction
1013 int newntiles = newres.ntiles(newtileres);
1014
1015 if (newntiles == 1) {
1016 // no need to keep tiling, reduce tiles into a single face
1017 // first, get all tiles and check if they are constant (with the same value)
1018 PtexFaceData** tiles = (PtexFaceData**) alloca(_ntiles * sizeof(PtexFaceData*));
1019 bool allConstant = true;
1020 for (int i = 0; i < _ntiles; i++) {
1021 PtexFaceData* tile = tiles[i] = getTile(i);
1022 allConstant = (allConstant && tile->isConstant() &&
1023 (i == 0 || (0 == memcmp(tiles[0]->getData(), tile->getData(),
1024 _pixelsize))));
1025 }
1026 if (allConstant) {
1027 // allocate a new constant face
1028 newface = new ConstantFace(_pixelsize);
1029 memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1030 newMemUsed = sizeof(ConstantFace) + _pixelsize;
1031 }
1032 else if (isTriangle) {
1033 // reassemble all tiles into temporary contiguous image
1034 // (triangle reduction doesn't work on tiles)
1035 int tileures = _tileres.u();
1036 int tilevres = _tileres.v();
1037 int sstride = _pixelsize * tileures;
1038 int dstride = sstride * _ntilesu;
1039 int dstepv = dstride * tilevres - sstride*(_ntilesu-1);
1040
1041 char* tmp = new char [_ntiles * _tileres.size() * _pixelsize];
1042 char* tmpptr = tmp;
1043 for (int i = 0; i < _ntiles;) {
1044 PtexFaceData* tile = tiles[i];
1045 if (tile->isConstant())
1046 PtexUtils::fill(tile->getData(), tmpptr, dstride,
1047 tileures, tilevres, _pixelsize);
1048 else
1049 PtexUtils::copy(tile->getData(), sstride, tmpptr, dstride, tilevres, sstride);
1050 i++;
1051 tmpptr += (i%_ntilesu) ? sstride : dstepv;
1052 }
1053
1054 // allocate a new packed face
1055 int memsize = _pixelsize * newres.size();
1056 newface = new PackedFace(newres, _pixelsize, memsize);
1057 newMemUsed = sizeof(PackedFace) + memsize;
1058 // reduce and copy into new face
1059 reducefn(tmp, _pixelsize * _res.u(), _res.u(), _res.v(),
1060 newface->getData(), _pixelsize * newres.u(), _dt, _nchan);
1061
1062 delete [] tmp;
1063 }
1064 else {
1065 // allocate a new packed face
1066 int memsize = _pixelsize * newres.size();
1067 newface = new PackedFace(newres, _pixelsize, memsize);
1068 newMemUsed = sizeof(PackedFace) + memsize;
1069
1070 int tileures = _tileres.u();
1071 int tilevres = _tileres.v();
1072 int sstride = _pixelsize * tileures;
1073 int dstride = _pixelsize * newres.u();
1074 int dstepu = dstride/_ntilesu;
1075 int dstepv = dstride*newres.v()/_ntilesv - dstepu*(_ntilesu-1);
1076
1077 char* dst = (char*) newface->getData();
1078 for (int i = 0; i < _ntiles;) {
1079 PtexFaceData* tile = tiles[i];
1080 if (tile->isConstant())
1081 PtexUtils::fill(tile->getData(), dst, dstride,
1082 newres.u()/_ntilesu, newres.v()/_ntilesv,
1083 _pixelsize);
1084 else
1085 reducefn(tile->getData(), sstride, tileures, tilevres,
1086 dst, dstride, _dt, _nchan);
1087 i++;
1088 dst += (i%_ntilesu) ? dstepu : dstepv;
1089 }
1090 }
1091 // release the tiles
1092 for (int i = 0; i < _ntiles; i++) tiles[i]->release();
1093 }
1094 else {
1095 // otherwise, tile the reduced face
1096 TiledReducedFace* tf = new TiledReducedFace(_reader, newres, newtileres, this, reducefn);
1097 newface = tf;
1098 newMemUsed = tf->memUsed();
1099 }
1100 return newface;
1101}
1102
1103
1104 void PtexReader::TiledFaceBase::getPixel(int ui, int vi, void* result)
1105{
1106 int tileu = ui >> _tileres.ulog2;
1107 int tilev = vi >> _tileres.vlog2;
1108 PtexPtr<PtexFaceData> tile ( getTile(tilev * _ntilesu + tileu) );
1109 tile->getPixel(ui - (tileu<<_tileres.ulog2),
1110 vi - (tilev<<_tileres.vlog2), result);
1111}
1112
1113
1114
1115 PtexFaceData* PtexReader::TiledReducedFace::getTile(int tile)
1116{
1117 FaceData*& face = _tiles[tile];
1118 if (face) {
1119 return face;
1120 }
1121
1122 // first, get all parent tiles for this tile
1123 // and check if they are constant (with the same value)
1124 int pntilesu = _parentface->ntilesu();
1125 int pntilesv = _parentface->ntilesv();
1126 int nu = pntilesu / _ntilesu; // num parent tiles for this tile in u dir
1127 int nv = pntilesv / _ntilesv; // num parent tiles for this tile in v dir
1128
1129 int ntilesval = nu*nv; // num parent tiles for this tile
1130 PtexFaceData** tiles = (PtexFaceData**) alloca(ntilesval * sizeof(PtexFaceData*));
1131 bool allConstant = true;
1132 int ptile = (tile/_ntilesu) * nv * pntilesu + (tile%_ntilesu) * nu;
1133 for (int i = 0; i < ntilesval;) {
1134 PtexFaceData* tileval = tiles[i] = _parentface->getTile(ptile);
1135 allConstant = (allConstant && tileval->isConstant() &&
1136 (i==0 || (0 == memcmp(tiles[0]->getData(), tileval->getData(),
1137 _pixelsize))));
1138 i++;
1139 ptile += (i%nu)? 1 : pntilesu - nu + 1;
1140 }
1141
1142 FaceData* newface = 0;
1143 size_t newMemUsed = 0;
1144 if (allConstant) {
1145 // allocate a new constant face
1146 newface = new ConstantFace(_pixelsize);
1147 newMemUsed = sizeof(ConstantFace) + _pixelsize;
1148 memcpy(newface->getData(), tiles[0]->getData(), _pixelsize);
1149 }
1150 else {
1151 // allocate a new packed face for the tile
1152 int memsize = _pixelsize*_tileres.size();
1153 newface = new PackedFace(_tileres, _pixelsize, memsize);
1154 newMemUsed = sizeof(PackedFace) + memsize;
1155
1156 // generate reduction from parent tiles
1157 int ptileures = _parentface->tileres().u();
1158 int ptilevres = _parentface->tileres().v();
1159 int sstride = ptileures * _pixelsize;
1160 int dstride = _tileres.u() * _pixelsize;
1161 int dstepu = dstride/nu;
1162 int dstepv = dstride*_tileres.v()/nv - dstepu*(nu-1);
1163
1164 char* dst = (char*) newface->getData();
1165 for (int i = 0; i < ntilesval;) {
1166 PtexFaceData* tileval = tiles[i];
1167 if (tileval->isConstant())
1168 PtexUtils::fill(tileval->getData(), dst, dstride,
1169 _tileres.u()/nu, _tileres.v()/nv,
1170 _pixelsize);
1171 else
1172 _reducefn(tileval->getData(), sstride, ptileures, ptilevres,
1173 dst, dstride, _dt, _nchan);
1174 i++;
1175 dst += (i%nu) ? dstepu : dstepv;
1176 }
1177 }
1178
1179 if (!AtomicCompareAndSwap(&face, (FaceData*)0, newface)) {
1180 delete newface;
1181 }
1182 else {
1183 _reader->increaseMemUsed(newMemUsed);
1184 }
1185
1186 return face;
1187}
1188
1189 PTEX_NAMESPACE_END
Magic
const uint32_t Magic
Definition: PtexIO.h:104
EditMetaDataHeaderSize
const int EditMetaDataHeaderSize
Definition: PtexIO.h:110
FaceDataHeaderSize
const int FaceDataHeaderSize
Definition: PtexIO.h:108
ExtHeaderSize
const int ExtHeaderSize
Definition: PtexIO.h:106
EditFaceDataHeaderSize
const int EditFaceDataHeaderSize
Definition: PtexIO.h:109
AllocaMax
const int AllocaMax
Definition: PtexIO.h:116
HeaderSize
const int HeaderSize
Definition: PtexIO.h:105
LevelInfoSize
const int LevelInfoSize
Definition: PtexIO.h:107
BlockSize
const int BlockSize
Definition: PtexIO.h:114
LittleEndian
bool LittleEndian()
Definition: PtexIO.h:119
et_editfacedata
@ et_editfacedata
Definition: PtexIO.h:92
et_editmetadata
@ et_editmetadata
Definition: PtexIO.h:92
enc_diffzipped
@ enc_diffzipped
Definition: PtexIO.h:81
enc_zipped
@ enc_zipped
Definition: PtexIO.h:81
enc_constant
@ enc_constant
Definition: PtexIO.h:81
enc_tiled
@ enc_tiled
Definition: PtexIO.h:81
PtexPlatform.h
Platform-specific classes, functions, and includes.
FilePos
off_t FilePos
Definition: PtexPlatform.h:99
AtomicStore
PTEX_INLINE void AtomicStore(T volatile *target, T value)
Definition: PtexPlatform.h:284
AtomicCompareAndSwap
PTEX_INLINE bool AtomicCompareAndSwap(T volatile *target, T oldvalue, T newvalue)
Definition: PtexPlatform.h:278
PtexReader.h
ConvertToFloat
void ConvertToFloat(float *dst, const void *src, DataType dt, int numChannels)
Definition: PtexUtils.cpp:123
PtexUtils.h
PTEX_NAMESPACE_END
#define PTEX_NAMESPACE_END
Definition: PtexVersion.h:62
Ptexture.h
Public API classes for reading, writing, caching, and filtering Ptex files.
AutoLock
Automatically acquire and release lock within enclosing scope.
Definition: PtexMutex.h:43
Mutex::trylock
bool trylock()
Definition: PtexPlatform.h:142
Mutex::unlock
void unlock()
Definition: PtexPlatform.h:143
PtexErrorHandler
Custom handler interface redirecting Ptex error messages.
Definition: Ptexture.h:658
PtexErrorHandler::reportError
virtual void reportError(const char *error)=0
PtexFaceData
Per-face texture data accessor.
Definition: Ptexture.h:406
PtexFaceData::getTile
virtual PtexFaceData * getTile(int tile)=0
Access a tile from the data block.
PtexFaceData::isConstant
virtual bool isConstant()=0
True if this data block is constant.
PtexFaceData::getData
virtual void * getData()=0
Access the data from this data block.
PtexHashMap::get
Value get(Key &key)
Definition: PtexHashMap.h:203
PtexHashMap::clear
void clear()
Definition: PtexHashMap.h:195
PtexHashMap::tryInsert
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
Definition: PtexHashMap.h:224
PtexInputHandler
Custom handler interface for intercepting and redirecting Ptex input stream calls.
Definition: Ptexture.h:619
PtexInputHandler::read
virtual size_t read(void *buffer, size_t size, Handle handle)=0
Read a number of bytes from the file.
PtexInputHandler::lastError
virtual const char * lastError()=0
Return the last error message encountered.
PtexInputHandler::open
virtual Handle open(const char *path)=0
Open a file in read mode.
PtexInputHandler::close
virtual bool close(Handle handle)=0
Close a file.
PtexMetaData
Meta data accessor.
Definition: Ptexture.h:328
PtexPtr
Smart-pointer for acquiring and releasing API objects.
Definition: Ptexture.h:1032
PtexPtr::get
T * get() const
Get pointer value.
Definition: Ptexture.h:1048
PtexReader::ConstDataPtr
Definition: PtexReader.h:345
PtexReader::ConstantFace
Definition: PtexReader.h:401
PtexReader::ConstantFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:966
PtexReader::FaceData
Definition: PtexReader.h:365
PtexReader::FaceData::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)=0
PtexReader::Level
Definition: PtexReader.h:520
PtexReader::Level::offsets
std::vector< FilePos > offsets
Definition: PtexReader.h:523
PtexReader::Level::fdh
std::vector< FaceDataHeader > fdh
Definition: PtexReader.h:522
PtexReader::Level::faces
std::vector< FaceData * > faces
Definition: PtexReader.h:524
PtexReader::Level::memUsed
size_t memUsed()
Definition: PtexReader.h:537
PtexReader::MetaData::LargeMetaData
Definition: PtexReader.h:273
PtexReader::MetaData::LargeMetaData::data
void * data()
Definition: PtexReader.h:278
PtexReader::MetaData
Definition: PtexReader.h:120
PtexReader::MetaData::selfDataSize
size_t selfDataSize()
Definition: PtexReader.h:266
PtexReader::MetaData::addEntry
void addEntry(uint8_t keysize, const char *key, uint8_t datatype, uint32_t datasize, const void *data, size_t &metaDataMemUsed)
Definition: PtexReader.h:246
PtexReader::MetaData::_reader
PtexReader * _reader
Definition: PtexReader.h:338
PtexReader::MetaData::addLmdEntry
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
PtexReader::MetaData::getEntry
Entry * getEntry(int index)
Definition: PtexReader.cpp:343
PtexReader::MetaData::_entries
std::vector< Entry * > _entries
Definition: PtexReader.h:341
PtexReader::PackedFace
Definition: PtexReader.h:377
PtexReader::PackedFace::data
void * data()
Definition: PtexReader.h:382
PtexReader::PackedFace::_data
char * _data
Definition: PtexReader.h:398
PtexReader::PackedFace::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:949
PtexReader::ReductionKey
Definition: PtexReader.h:685
PtexReader::TiledFaceBase::reduce
virtual FaceData * reduce(PtexReader *, Res newres, PtexUtils::ReduceFn, size_t &newMemUsed)
Definition: PtexReader.cpp:979
PtexReader::TiledFaceBase::_ntiles
int _ntiles
Definition: PtexReader.h:464
PtexReader::TiledFaceBase::getPixel
virtual void getPixel(int u, int v, void *result)
Read a single texel from the data block.
Definition: PtexReader.cpp:1104
PtexReader::TiledFace
Definition: PtexReader.h:470
PtexReader::TiledFace::_fdh
std::vector< FaceDataHeader > _fdh
Definition: PtexReader.h:493
PtexReader::TiledFace::memUsed
size_t memUsed()
Definition: PtexReader.h:486
PtexReader::TiledFace::readTile
void readTile(int tile, FaceData *&data)
Definition: PtexReader.cpp:635
PtexReader::TiledFace::_offsets
std::vector< FilePos > _offsets
Definition: PtexReader.h:494
PtexReader::TiledReducedFace
Definition: PtexReader.h:498
PtexReader::TiledReducedFace::getTile
virtual PtexFaceData * getTile(int tile)
Access a tile from the data block.
Definition: PtexReader.cpp:1115
PtexReader::TiledReducedFace::memUsed
size_t memUsed()
Definition: PtexReader.h:512
PtexReader
Definition: PtexReader.h:52
PtexReader::readLevelInfo
void readLevelInfo()
Definition: PtexReader.cpp:298
PtexReader::_reductions
ReductionMap _reductions
Definition: PtexReader.h:713
PtexReader::reopenFP
bool reopenFP()
Definition: PtexReader.cpp:240
PtexReader::datatype
DataType datatype() const
Definition: PtexReader.h:113
PtexReader::readEditFaceData
void readEditFaceData()
Definition: PtexReader.cpp:502
PtexReader::_premultiply
bool _premultiply
Definition: PtexReader.h:641
PtexReader::_constdatapos
FilePos _constdatapos
Definition: PtexReader.h:651
PtexReader::readMetaDataBlock
void readMetaDataBlock(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:414
PtexReader::readFaceInfo
void readFaceInfo()
Definition: PtexReader.cpp:277
PtexReader::_path
std::string _path
Definition: PtexReader.h:647
PtexReader::_constdata
uint8_t * _constdata
Definition: PtexReader.h:659
PtexReader::_levelpos
std::vector< FilePos > _levelpos
Definition: PtexReader.h:666
PtexReader::readEditData
void readEditData()
Definition: PtexReader.cpp:468
PtexReader::getPixel
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:893
PtexReader::_faceedits
std::vector< FaceEdit > _faceedits
Definition: PtexReader.h:683
PtexReader::release
virtual void release()
Release resources held by this pointer (pointer becomes invalid).
Definition: PtexReader.h:56
PtexReader::increaseMemUsed
void increaseMemUsed(size_t amount)
Definition: PtexReader.h:71
PtexReader::getFace
FaceData * getFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.h:580
PtexReader::purge
void purge()
Definition: PtexReader.cpp:115
PtexReader::_editdatapos
FilePos _editdatapos
Definition: PtexReader.h:657
PtexReader::tell
FilePos tell()
Definition: PtexReader.h:557
PtexReader::getLevel
Level * getLevel(int levelid)
Definition: PtexReader.h:572
PtexReader::errorData
FaceData * errorData(bool deleteOnRelease=false)
Definition: PtexReader.h:600
PtexReader::~PtexReader
virtual ~PtexReader()
Definition: PtexReader.cpp:93
PtexReader::_hasEdits
bool _hasEdits
Definition: PtexReader.h:661
PtexReader::_needToOpen
bool _needToOpen
Definition: PtexReader.h:643
PtexReader::computeOffsets
void computeOffsets(FilePos pos, int noffsets, const FaceDataHeader *fdh, FilePos *offsets)
Definition: PtexReader.h:605
PtexReader::readConstData
void readConstData()
Definition: PtexReader.cpp:319
PtexReader::getMetaData
virtual PtexMetaData * getMetaData()
Access meta data.
Definition: PtexReader.cpp:335
PtexReader::needToOpen
bool needToOpen() const
Definition: PtexReader.h:57
PtexReader::_extheader
ExtHeader _extheader
Definition: PtexReader.h:649
PtexReader::_leveldatapos
FilePos _leveldatapos
Definition: PtexReader.h:653
PtexReader::getData
virtual void getData(int faceid, void *buffer, int stride)
Access texture data for a face at highest-resolution.
Definition: PtexReader.cpp:711
PtexReader::_err
PtexErrorHandler * _err
Definition: PtexReader.h:640
PtexReader::readEditMetaData
void readEditMetaData()
Definition: PtexReader.cpp:533
PtexReader::_faceinfopos
FilePos _faceinfopos
Definition: PtexReader.h:650
PtexReader::_levelinfo
std::vector< LevelInfo > _levelinfo
Definition: PtexReader.h:665
PtexReader::PtexReader
PtexReader(bool premultiply, PtexInputHandler *inputHandler, PtexErrorHandler *errorHandler)
Definition: PtexReader.cpp:71
PtexReader::_zstream
z_stream_s _zstream
Definition: PtexReader.h:716
PtexReader::_io
PtexInputHandler * _io
Definition: PtexReader.h:639
PtexReader::getFaceInfo
virtual const Ptex::FaceInfo & getFaceInfo(int faceid)
Access resolution and adjacency information about a face.
Definition: PtexReader.cpp:267
PtexReader::_metadatapos
FilePos _metadatapos
Definition: PtexReader.h:654
PtexReader::readLargeMetaDataHeaders
void readLargeMetaDataHeaders(MetaData *metadata, FilePos pos, int zipsize, int memsize, size_t &metaDataMemUsed)
Definition: PtexReader.cpp:440
PtexReader::closeFP
void closeFP()
Definition: PtexReader.cpp:230
PtexReader::_pixelsize
int _pixelsize
Definition: PtexReader.h:658
PtexReader::_pendingPurge
bool _pendingPurge
Definition: PtexReader.h:644
PtexReader::readlock
Mutex readlock
Definition: PtexReader.h:637
PtexReader::readFace
void readFace(int levelid, Level *level, int faceid, Res res)
Definition: PtexReader.cpp:627
PtexReader::_levelinfopos
FilePos _levelinfopos
Definition: PtexReader.h:652
PtexReader::_lmdheaderpos
FilePos _lmdheaderpos
Definition: PtexReader.h:655
PtexReader::nchannels
int nchannels() const
Definition: PtexReader.h:114
PtexReader::_lmddatapos
FilePos _lmddatapos
Definition: PtexReader.h:656
PtexReader::prune
void prune()
Definition: PtexReader.cpp:104
PtexReader::_rfaceids
std::vector< uint32_t > _rfaceids
Definition: PtexReader.h:664
PtexReader::_metaedits
std::vector< MetaEdit > _metaedits
Definition: PtexReader.h:675
PtexReader::_memUsed
volatile size_t _memUsed
Definition: PtexReader.h:718
PtexReader::_header
Header _header
Definition: PtexReader.h:648
PtexReader::readFaceData
void readFaceData(FilePos pos, FaceDataHeader fdh, Res res, int levelid, FaceData *&face)
Definition: PtexReader.cpp:641
PtexReader::seek
void seek(FilePos pos)
Definition: PtexReader.h:558
PtexReader::readBlock
bool readBlock(void *data, int size, bool reportError=true)
Definition: PtexReader.cpp:548
PtexReader::_metadata
MetaData * _metadata
Definition: PtexReader.h:660
PtexReader::_levels
std::vector< Level * > _levels
Definition: PtexReader.h:667
PtexReader::_baseMemUsed
size_t _baseMemUsed
Definition: PtexReader.h:717
PtexReader::_faceinfo
std::vector< FaceInfo > _faceinfo
Definition: PtexReader.h:663
PtexReader::_fp
PtexInputHandler::Handle _fp
Definition: PtexReader.h:645
PtexReader::readZipBlock
bool readZipBlock(void *data, int zipsize, int unzipsize)
Definition: PtexReader.cpp:563
PtexReader::readMetaData
void readMetaData()
Definition: PtexReader.cpp:381
PtexReader::logOpen
void logOpen()
Definition: PtexReader.h:72
PtexReader::readLevel
void readLevel(int levelid, Level *&level)
Definition: PtexReader.cpp:595
PtexReader::_errorPixel
std::vector< char > _errorPixel
Definition: PtexReader.h:714
PtexReader::getConstData
uint8_t * getConstData()
Definition: PtexReader.h:579
PtexReader::_pos
FilePos _pos
Definition: PtexReader.h:646
PtexReader::open
bool open(const char *path, Ptex::String &error)
Definition: PtexReader.cpp:137
PtexReader::tryClose
bool tryClose()
Definition: PtexReader.cpp:219
PtexReader::setError
void setError(const char *error)
Definition: PtexReader.h:546
PtexReader::_ok
bool _ok
Definition: PtexReader.h:642
PtexTexture
Interface for reading data from a ptex file.
Definition: Ptexture.h:457
PtexTexture::path
virtual const char * path()=0
Path that file was opened with.
PtexTexture::open
static PtexTexture * open(const char *path, Ptex::String &error, bool premultiply=0)
Open a ptex file for reading.
Definition: PtexReader.cpp:59
Ptex::String
Memory-managed string.
Definition: Ptexture.h:296
Ptex::String::c_str
const char * c_str() const
Definition: Ptexture.h:304
PTEX_NAMESPACE_BEGIN
Definition: PtexSeparableKernel.cpp:42
PtexUtils::genRfaceids
void genRfaceids(const FaceInfo *faces, int nfaces, uint32_t *rfaceids, uint32_t *faceids)
Definition: PtexUtils.cpp:630
PtexUtils::reduceu
void reduceu(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:333
PtexUtils::min
T min(T a, T b)
Definition: PtexUtils.h:148
PtexUtils::max
T max(T a, T b)
Definition: PtexUtils.h:151
PtexUtils::decodeDifference
void decodeDifference(void *data, int size, DataType dt)
Definition: PtexUtils.cpp:271
PtexUtils::reducev
void reducev(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:366
PtexUtils::fill
void fill(const void *src, void *dst, int dstride, int ures, int vres, int pixelsize)
Definition: PtexUtils.cpp:422
PtexUtils::reduceTri
void reduceTri(const void *src, int sstride, int w, int, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:406
PtexUtils::copy
void copy(const void *src, int sstride, void *dst, int dstride, int vres, int rowlen)
Definition: PtexUtils.cpp:438
PtexUtils::ReduceFn
void ReduceFn(const void *src, int sstride, int ures, int vres, void *dst, int dstride, DataType dt, int nchannels)
Definition: PtexUtils.h:185
PtexUtils::multalpha
void multalpha(void *data, int npixels, DataType dt, int nchannels, int alphachan)
Definition: PtexUtils.cpp:579
PtexUtils::interleave
void interleave(const void *src, int sstride, int uw, int vw, void *dst, int dstride, DataType dt, int nchan)
Definition: PtexUtils.cpp:189
EditFaceDataHeader
Definition: PtexIO.h:93
EditFaceDataHeader::faceid
uint32_t faceid
Definition: PtexIO.h:94
EditFaceDataHeader::fdh
FaceDataHeader fdh
Definition: PtexIO.h:96
EditFaceDataHeader::faceinfo
FaceInfo faceinfo
Definition: PtexIO.h:95
EditMetaDataHeader
Definition: PtexIO.h:98
EditMetaDataHeader::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:99
EditMetaDataHeader::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:100
ExtHeader
Definition: PtexIO.h:64
ExtHeader::lmddatasize
uint64_t lmddatasize
Definition: PtexIO.h:71
ExtHeader::editdatapos
uint64_t editdatapos
Definition: PtexIO.h:73
ExtHeader::lmdheadermemsize
uint32_t lmdheadermemsize
Definition: PtexIO.h:70
ExtHeader::lmdheaderzipsize
uint32_t lmdheaderzipsize
Definition: PtexIO.h:69
ExtHeader::editdatasize
uint64_t editdatasize
Definition: PtexIO.h:72
FaceDataHeader
Definition: PtexIO.h:82
FaceDataHeader::encoding
Encoding encoding() const
Definition: PtexIO.h:85
FaceDataHeader::blocksize
uint32_t blocksize() const
Definition: PtexIO.h:84
Header
Definition: PtexIO.h:44
Header::metadatamemsize
uint32_t metadatamemsize
Definition: PtexIO.h:60
Header::faceinfosize
uint32_t faceinfosize
Definition: PtexIO.h:54
Header::nlevels
uint16_t nlevels
Definition: PtexIO.h:51
Header::nchannels
uint16_t nchannels
Definition: PtexIO.h:50
Header::meshtype
uint32_t meshtype
Definition: PtexIO.h:47
Header::constdatasize
uint32_t constdatasize
Definition: PtexIO.h:55
Header::levelinfosize
uint32_t levelinfosize
Definition: PtexIO.h:56
Header::extheadersize
uint32_t extheadersize
Definition: PtexIO.h:53
Header::metadatazipsize
uint32_t metadatazipsize
Definition: PtexIO.h:59
Header::pixelSize
int pixelSize() const
Definition: PtexIO.h:61
Header::alphachan
int32_t alphachan
Definition: PtexIO.h:49
Header::magic
uint32_t magic
Definition: PtexIO.h:45
Header::nfaces
uint32_t nfaces
Definition: PtexIO.h:52
Header::leveldatasize
uint64_t leveldatasize
Definition: PtexIO.h:58
Header::version
uint32_t version
Definition: PtexIO.h:46
Header::hasAlpha
bool hasAlpha() const
Definition: PtexIO.h:62
LevelInfo
Definition: PtexIO.h:75
LevelInfo::levelheadersize
uint32_t levelheadersize
Definition: PtexIO.h:77
LevelInfo::nfaces
uint32_t nfaces
Definition: PtexIO.h:78
PtexReader::FaceEdit
Definition: PtexReader.h:678
PtexReader::FaceEdit::pos
FilePos pos
Definition: PtexReader.h:679
PtexReader::FaceEdit::faceid
int faceid
Definition: PtexReader.h:680
PtexReader::FaceEdit::fdh
FaceDataHeader fdh
Definition: PtexReader.h:681
PtexReader::MetaData::Entry
Definition: PtexReader.h:284
PtexReader::MetaData::Entry::lmdPos
FilePos lmdPos
Definition: PtexReader.h:291
PtexReader::MetaData::Entry::lmdZipSize
uint32_t lmdZipSize
Definition: PtexReader.h:292
PtexReader::MetaData::Entry::isLmd
bool isLmd
Definition: PtexReader.h:289
PtexReader::MetaData::Entry::datasize
uint32_t datasize
Definition: PtexReader.h:287
PtexReader::MetaData::Entry::lmdData
LargeMetaData * lmdData
Definition: PtexReader.h:290
PtexReader::MetaData::Entry::data
char * data
Definition: PtexReader.h:288
PtexReader::MetaEdit
Definition: PtexReader.h:670
PtexReader::MetaEdit::zipsize
int zipsize
Definition: PtexReader.h:672
PtexReader::MetaEdit::memsize
int memsize
Definition: PtexReader.h:673
PtexReader::MetaEdit::pos
FilePos pos
Definition: PtexReader.h:671
Ptex::FaceInfo
Information about a face, as stored in the Ptex file header.
Definition: Ptexture.h:229
Ptex::Res
Pixel resolution of a given texture.
Definition: Ptexture.h:159