Fixed wrong prediction for incomplete ranges.
[fic.git] / modules / root.cpp
blob7dcfc3acad8f0db23e795c8ecff4ce8e90e3316a
1 #include "root.h"
2 #include "../util.h"
3 #include "../fileUtil.h"
5 #include <QImage>
6 #include <QThreadPool>
8 using namespace std;
11 QImage MRoot::toImage() {
12 ASSERT( getMode()!=Clear && settings && moduleColor() && moduleShape() );
13 return moduleColor()->planes2image();
16 namespace NOSPACE {
17 /** Represents a scheduled encoding job for use in QThreadPool */
18 class ScheduledJob: public QRunnable {
19 IShapeTransformer *worker; ///< the worker to perform the job
20 int job; ///< the job's identifier
21 volatile bool &errorFlag; ///< the flag to set in case of failure
22 public:
23 /** Creates a new scheduled job, failure reported in \p errorFlag_ */
24 ScheduledJob( IShapeTransformer *worker_, int job_, volatile bool &errorFlag_ )
25 : worker(worker_), job(job_), errorFlag(errorFlag_) {}
27 /** Just makes #worker do the #job and sets #errorFlag in case of error (virtual method) */
28 void run() {
29 try {
30 worker->jobEncode(job);
31 } catch (exception &e) {
32 errorFlag= true;
35 }; // ScheduledJob class
37 bool MRoot::encode(const QImage &toEncode,const UpdateInfo &updateInfo) {
38 ASSERT( getMode()==Clear && settings && moduleColor() && moduleShape()
39 && maxThreads()>=1 );
40 // set my zoom and dimensions
41 zoom= 0;
42 this->width= toEncode.width();
43 this->height= toEncode.height();
44 // get the plane list, create the jobs from it
45 PlaneSettings planeProto( width, height, settingsInt(DomainCountLog2), 0/*zoom*/
46 , quality(), moduleQuality(), updateInfo );
47 PlaneList planes= moduleColor()->image2planes( toEncode, planeProto );
48 int jobCount= moduleShape()->createJobs(planes);
49 // process the jobs
50 if (maxThreads()==1)
51 // simple one-thread mode: pocesses jobs sequentially, returns false on failure
52 try {
53 for (int i=0; i<jobCount; ++i)
54 moduleShape()->jobEncode(i);
55 } catch (exception &e) {
56 return false;
58 else {
59 // multi-threaded mode: create ScheduleJob instances and push them into a QThreadPool
60 volatile bool errorFlag= false;
61 QThreadPool jobPool;
62 jobPool.setMaxThreadCount( maxThreads() );
63 for (int job=0; job<jobCount; ++job)
64 jobPool.start( new ScheduledJob(moduleShape(),job,errorFlag) );
65 jobPool.waitForDone();
66 if (errorFlag)
67 return false;
69 // encoding successful - change the mode and return true
70 myMode= Encode;
71 return true;
74 void MRoot::decodeAct(DecodeAct action,int count) {
75 ASSERT( getMode()!=Clear && settings && moduleColor() && moduleShape() );
76 int jobCount= moduleShape()->jobCount();
77 ASSERT(jobCount>0);
78 // there will be probably no need to parallelize decoding
79 for (int i=0; i<jobCount; ++i)
80 moduleShape()->jobDecodeAct(i,action,count);
83 bool MRoot::toStream(std::ostream &file) {
84 ASSERT( getMode()!=Clear && settings && moduleColor() && moduleShape() );
85 // an exception is thrown on write/save errors
86 try {
87 file.exceptions( ofstream::eofbit | ofstream::failbit | ofstream::badbit );
89 STREAM_POS(file);
90 // put the magic, the dimensions (not zoomed) and child-module IDs
91 put<Uint16>(file,Magic);
92 put<Uint16>( file, rShift(width,zoom) );
93 put<Uint16>( file, rShift(height,zoom) );
94 file_saveModuleType( file, ModuleColor );
95 file_saveModuleType( file, ModuleShape );
97 STREAM_POS(file);
98 // put settings common for all the jobs
99 put<Uchar>( file, settingsInt(DomainCountLog2) );
101 STREAM_POS(file);
102 moduleColor()->writeData(file);
104 STREAM_POS(file);
105 moduleShape()->writeSettings(file);
107 STREAM_POS(file);
108 // put the workers' data
109 moduleShape()->writeJobs(file);
111 STREAM_POS(file);
112 return true;
113 } catch(exception &e) {
114 return false;
118 bool MRoot::fromStream(istream &file,int newZoom) {
119 ASSERT( newZoom>=0 && getMode()==Clear && settings && !moduleColor() && !moduleShape() );
120 zoom= newZoom;
121 // an exception is thrown on read/load errors
122 try {
123 file.exceptions( ifstream::eofbit | ifstream::failbit | ifstream::badbit );
125 STREAM_POS(file);
126 // check the magic number, load the dimensions and child-module types
127 if (get<Uint16>(file) != Magic)
128 return false;
129 this->width= lShift( (int)get<Uint16>(file), zoom );
130 this->height= lShift( (int)get<Uint16>(file), zoom );
131 file_loadModuleType( file, ModuleColor );
132 file_loadModuleType( file, ModuleShape );
134 STREAM_POS(file);
135 // create the planes and get settings common for all the jobs
136 settingsInt(DomainCountLog2)= get<Uchar>(file);
137 PlaneSettings planeProto( width, height, settingsInt(DomainCountLog2), zoom );
139 STREAM_POS(file);
140 PlaneList planes= moduleColor()->readData(file,planeProto);
142 STREAM_POS(file);
143 moduleShape()->readSettings(file);
145 STREAM_POS(file);
146 // create the jobs (from the plane list) and get their data
147 moduleShape()->createJobs(planes);
148 moduleShape()->readJobs(file);
150 STREAM_POS(file);
151 myMode= Decode;
152 return true;
153 } catch(exception &e) {
154 return false;