TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/thumbnail/ThumbnailDiskCache.cpp
Go to the documentation of this file.
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