TuttleOFX
1
|
00001 #include "ThumbnailDiskCache.hpp" 00002 00003 #include <tuttle/host/memory/MemoryCache.hpp> 00004 #include <tuttle/host/Graph.hpp> 00005 #include <tuttle/host/Node.hpp> 00006 #include <tuttle/host/io.hpp> 00007 00008 #include <boost/functional/hash.hpp> 00009 #include <boost/filesystem/operations.hpp> 00010 00011 #include <ctime> 00012 00013 00014 namespace tuttle { 00015 namespace host { 00016 00017 ::boost::shared_ptr<attribute::Image> loadImage( const std::string& imagePath ) 00018 { 00019 memory::MemoryCache outputCache; 00020 00021 compute( 00022 outputCache, 00023 list_of 00024 ( NodeInit(io::getBestReader(imagePath)) 00025 .setParam("filename", imagePath.c_str()) ) 00026 ); 00027 00028 return outputCache.get(0); 00029 } 00030 00031 ::boost::shared_ptr<attribute::Image> loadAndGenerateThumbnail( const std::string& imagePath, const std::string& thumbnailToCreate, const int thumbnailMaxSize ) 00032 { 00033 memory::MemoryCache outputCache; 00034 memory::MemoryCache internCache; 00035 00036 Graph graph; 00037 std::vector<INode*> nodes = graph.addConnectedNodes( 00038 list_of 00039 ( NodeInit(io::getBestReader(imagePath)) 00040 .setParam("filename", imagePath.c_str()) ) 00041 ( NodeInit("tuttle.resize") 00042 .setParam("size", thumbnailMaxSize, thumbnailMaxSize) 00043 .setParam("keepRatio", true) ) 00044 ( NodeInit(io::getBestWriter(thumbnailToCreate)) 00045 .setParam("filename", thumbnailToCreate.c_str()) ) 00046 ); 00047 graph.setup(); 00048 00049 OfxRangeD timeDomain = nodes.back()->getTimeDomain(); 00050 OfxTime time = timeDomain.min + (timeDomain.max - timeDomain.min) * 0.5; 00051 00052 // TODO: If it's a sequence, the middle frame may not exist. 00053 // item = sequenceParser.browse(id)[0] 00054 // if item._type is sequenceParser.eTypeSequence: 00055 // fileAtTime = item._sequence.getAbsoluteFilenameAt(int(time)) 00056 // if not os.path.exists(fileAtTime): 00057 // time = td.min 00058 00059 ComputeOptions cOptions; 00060 cOptions.setVerboseLevel(eVerboseLevelTrace); 00061 cOptions.setTimeRange(time, time); 00062 00063 graph.compute( 00064 outputCache, 00065 NodeListArg(), 00066 cOptions, 00067 internCache 00068 ); 00069 return outputCache.get(0); 00070 } 00071 00072 const std::string ThumbnailDiskCache::s_thumbnailExtension(".png"); 00073 const int ThumbnailDiskCache::s_thumbnailMaxSize(256); 00074 00075 bool ThumbnailDiskCache::containsUpToDate( const boost::filesystem::path& imagePath ) const 00076 { 00077 std::time_t thumbnailLastWriteTime; // thumbnail cached file time 00078 if( ! _diskCacheTranslator.contains( _diskCacheTranslator.keyToAbsolutePath( buildKey(imagePath) ).replace_extension(".png"), thumbnailLastWriteTime ) ) 00079 return false; 00080 00081 boost::system::error_code error; 00082 if( ! boost::filesystem::exists(imagePath, error) ) 00083 return false; 00084 00085 const bool upToDate = (thumbnailLastWriteTime == boost::filesystem::last_write_time(imagePath)); 00086 return upToDate; 00087 } 00088 00089 ThumbnailDiskCache::TImage ThumbnailDiskCache::retrieveThumbnail( const KeyType key ) const 00090 { 00091 return loadImage( _diskCacheTranslator.keyToAbsolutePath( key ).replace_extension(s_thumbnailExtension).string() ); 00092 } 00093 00094 ThumbnailDiskCache::TImage ThumbnailDiskCache::create( KeyType& key, const boost::filesystem::path& imagePath ) 00095 { 00096 key = buildKey(imagePath); 00097 const boost::filesystem::path thumbnailPath = _diskCacheTranslator.create( key ).replace_extension(s_thumbnailExtension); 00098 00099 // Load full image as thumbnail 00100 TImage thumbnail = loadAndGenerateThumbnail( imagePath.string(), thumbnailPath.string(), s_thumbnailMaxSize ); 00101 00102 // Set the last write time to the same value as the source image 00103 std::time_t lastWriteTimeSourceImg = boost::filesystem::last_write_time(imagePath); // read last write time 00104 boost::filesystem::last_write_time( thumbnailPath, lastWriteTimeSourceImg ); // set last write time of the thumbnail 00105 00106 return thumbnail; 00107 } 00108 00109 ThumbnailDiskCache::KeyType ThumbnailDiskCache::buildKey( const boost::filesystem::path& imagePath ) const 00110 { 00111 KeyType key = 0; 00112 boost::hash_combine( key, imagePath ); 00113 return key; 00114 } 00115 00116 ThumbnailDiskCache::TImage ThumbnailDiskCache::getThumbnail( KeyType& key, const boost::filesystem::path& imagePath ) 00117 { 00118 if( ! containsUpToDate(imagePath) ) 00119 { 00120 return create( key, imagePath ); 00121 } 00122 00123 // Load an existing thumbnail 00124 key = buildKey(imagePath); 00125 const boost::filesystem::path thumbnailPath = _diskCacheTranslator.keyToAbsolutePath( key ).replace_extension(s_thumbnailExtension); 00126 00127 return loadImage( thumbnailPath.string() ); 00128 } 00129 00130 } 00131 } 00132