Writing: adjusted label names and formatting of Fisher-and-Saupe table.
[fic.git] / interfaces.h
blobc8f13288ba22f871ca7de30df8d61b983d673b7e
1 #ifndef INTERFACES_HEADER_
2 #define INTERFACES_HEADER_
4 /* Forwards for interfaces */
5 struct IRoot;
6 struct IQuality2SE;
7 struct IColorTransformer;
8 struct IShapeTransformer;
9 struct ISquareEncoder;
10 struct ISquareRanges;
11 struct ISquareDomains;
12 struct IStdEncPredictor;
13 struct IIntCodec;
15 /** Contains basic types frequently used in modules */
16 namespace MTypes {
17 typedef double Real; ///< The floating-point type in which most computations are made
18 typedef float SReal; ///< The floating-point type for long-term pixel-value storage
20 typedef MatrixSlice<SReal> SMatrix; ///< Used for storing pixel matrices
21 typedef SMatrix::Const CSMatrix; ///< Used for passing constant pixels
22 typedef std::vector<SMatrix> MatrixList; ///< A list of pixel matrices
24 enum DecodeAct { Clear, Iterate }; ///< Possible decoding actions \todo name clash, etc.
26 struct PlaneBlock; // declared and described later in the file
28 typedef SummedMatrix<Real,SReal> SummedPixels;
30 namespace NOSPACE {
31 using namespace std;
32 using namespace MTypes;
37 /** \defgroup interfaces Interfaces for coding modules
38 * @{ */
40 /** Interface for root modules (with only one implementation MRoot),
41 * all modules are always owned (either directly or indirectly) by one of this type */
42 struct IRoot: public Interface<IRoot> {
43 /** The root can be in any of these modes */
44 enum Mode {
45 Clear, ///< no action has been done
46 Encode, ///< contains an encoded image
47 Decode ///< contains an image decoded from a file
50 static const Uint16 Magic= 65535-4063 /// magic number - integer identifying FIC files
51 , SettingsMagic= Magic^12345; ///< magic number - integer identifying settings files
53 /** A status-query method */
54 virtual Mode getMode() =0;
55 /** Saves current decoding state into a QImage */
56 virtual QImage toImage() =0;
58 /** Encodes an image - returns false on exception, getMode() have to be to be Clear */
59 virtual bool encode
60 ( const QImage &toEncode, const UpdateInfo &updateInfo=UpdateInfo::none ) =0;
61 /** Performs a decoding action (e.g.\ clearing, multiple iteration) */
62 virtual void decodeAct( DecodeAct action, int count=1 ) =0;
64 /** Saves an encoded image into a stream, returns true on success */
65 virtual bool toStream(std::ostream &file) =0;
66 /** Loads image from a file - returns true on success (to be run on in Clear state),
67 * can load in bigger size: dimension == orig_dim*2^\p zoom */
68 virtual bool fromStream(std::istream &file,int zoom=0) =0;
70 /** Shorthand: saves an encoded image to a file - returns the number of bytes written
71 * or \p false on failure */
72 int toFile(const char *fileName) {
73 std::ofstream file( fileName, ios_base::binary|ios_base::trunc|ios_base::out );
74 if ( !toStream(file) )
75 return 0;
76 else
77 return file.tellp();
79 /** Shorthand: loads image from a file - returns true on success, see ::fromStream */
80 bool fromFile(const char *fileName,int zoom=0) {
81 std::ifstream file( fileName, ios_base::binary|ios_base::in );
82 return fromStream(file,zoom);
85 /** Saves all settings to a file (incl.\ child modules), returns true on success */
86 bool allSettingsToFile(const char *fileName);
87 /** Loads all settings from a file (to be run on a shallow module), returns true on success */
88 bool allSettingsFromFile(const char *fileName);
89 }; // IRoot interface
94 /** Interface for modules deciding how the max.\ SE will depend on block size
95 * (parametrized by quality) */
96 struct IQuality2SE: public Interface<IQuality2SE> {
97 /** Returns maximum SE for a [0,1] quality and range blocks with pixelCount pixels */
98 virtual float rangeSE(float quality,int pixelCount) =0;
99 /** Fills an array (until levelEnd) with SE's according to [0,1] quality
100 * : on i-th index for "complete square range blocks" of level i.
101 * Common implementation - uses ::rangeSE method */
102 void regularRangeErrors(float quality,int levelEnd,float *squareErrors);
108 /** Interface for modules performing color transformations,
109 * following modules always work with single-color (greyscale) images */
110 struct IColorTransformer: public Interface<IColorTransformer> {
111 /** Contains some setings for one color plane of an image */
112 struct PlaneSettings;
114 /** Represents a one-color image, together with some setttings.
115 * In returned instances the pointed-to memory is always owned by this module. */
116 struct Plane {
117 mutable SMatrix pixels; ///< a matrix of pixels with values in [0,1]
118 const PlaneSettings *settings; ///< the settings for the plane
121 /** List of planes (the pointed-to memory is owned by the module) */
122 typedef std::vector<Plane> PlaneList;
124 /** Splits an image into color-planes and adjusts their settings (from \p prototype).
125 * It should call UpdateInfo::incMaxProgress with the total pixel count. */
126 virtual PlaneList image2planes(const QImage &toEncode,const PlaneSettings &prototype) =0;
127 /** Merges planes back into a color image (only useful when decoding) */
128 virtual QImage planes2image() =0;
130 /** Writes any data needed for plane reconstruction to a stream */
131 virtual void writeData(std::ostream &file) =0;
132 /** Reads any data needed for plane reconstruction from a stream and creates the plane list */
133 virtual PlaneList readData( std::istream &file, const PlaneSettings &prototype ) =0;
134 }; // IColorTransformer interface
136 struct IColorTransformer::PlaneSettings {
137 int width /// the width of the image (zoomed)
138 , height /// the height of the image (zoomed)
139 , domainCountLog2 /// 2-logarithm of the maximum domain count
140 , zoom; ///< the zoom (dimensions multiplied by 2^zoom)
141 SReal quality; ///< encoding quality for the plane, in [0,1] (higher is better)
142 IQuality2SE *moduleQ2SE; ///< pointer to the module computing maximum SE (never owned)
143 const UpdateInfo &updateInfo; ///< structure for communication with user
145 /** A simple constructor, only initializes the values from the parameters */
146 PlaneSettings( int width_, int height_, int domainCountLog2_, int zoom_
147 , SReal quality_=numeric_limits<SReal>::quiet_NaN()
148 , IQuality2SE *moduleQ2SE_=0, const UpdateInfo &updateInfo_=UpdateInfo::none )
149 : width(width_), height(height_)
150 , domainCountLog2(domainCountLog2_), zoom(zoom_)
151 , quality(quality_), moduleQ2SE(moduleQ2SE_), updateInfo(updateInfo_) {}
152 }; // PlaneSettings struct
157 /** Interface for modules handling pixel-shape changes
158 * and/or splitting the single-color planes into independently processed parts */
159 struct IShapeTransformer: public Interface<IShapeTransformer> {
160 typedef IColorTransformer::PlaneList PlaneList;
162 /** Creates jobs from the list of color planes, returns job count */
163 virtual int createJobs(const PlaneList &planes) =0;
164 /** Returns the number of jobs */
165 virtual int jobCount() =0;
167 /** Starts encoding a job - thread-safe (for different jobs) */
168 virtual void jobEncode(int jobIndex) =0;
169 /** Performs a decoding action for a job - thread-safe (for different jobs) */
170 virtual void jobDecodeAct( int jobIndex, DecodeAct action, int count=1 ) =0;
172 /** Writes all settings (shared by all jobs) needed for later reconstruction */
173 virtual void writeSettings(std::ostream &file) =0;
174 /** Reads settings (shared by all jobs) needed for reconstruction from a stream -
175 * needs to be done before the job creation */
176 virtual void readSettings(std::istream &file) =0;
178 /** Returns the number of phases (progressive encoding), only depends on settings */
179 virtual int phaseCount() =0;
180 /** Writes any data needed for reconstruction of every job, phase parameters
181 * determine the range of saved phases */
182 virtual void writeJobs(std::ostream &file,int phaseBegin,int phaseEnd) =0;
183 /** Reads all data needed for reconstruction of every job and prepares for encoding,
184 * parameters like ::writeJobs */
185 virtual void readJobs(std::istream &file,int phaseBegin,int phaseEnd) =0;
187 /** Shortcut - default parameters "phaseBegin=0,phaseEnd=phaseCount()" */
188 void writeJobs(std::ostream &file,int phaseBegin=0)
189 { writeJobs( file, phaseBegin, phaseCount() ); }
190 /** Shortcut - default parameters "phaseBegin=0,phaseEnd=phaseCount()" */
191 void readJobs(std::istream &file,int phaseBegin=0)
192 { readJobs( file, phaseBegin, phaseCount() ); }
193 }; // IShapeTransformer interface
196 /// @}
199 namespace MTypes {
200 /** Represents a rectangular piece of single-color image to be encoded/decoded.
201 * It is common structure for ISquare{Range,Domain,Encoder}.
202 * Inherits a pixel-matrix, its dimensions and block-summers and adds
203 * pointers to settings and modules handling square ranges, domains and encoding */
204 struct PlaneBlock: public SummedPixels {
205 typedef IColorTransformer::PlaneSettings PlaneSettings;
207 const PlaneSettings *settings; ///< the settings for the plane
208 ISquareRanges *ranges; ///< module for range blocks generation
209 ISquareDomains *domains;///< module for domain blocks generation
210 ISquareEncoder *encoder;///< module for encoding (maintaining domain-range mappings)
212 /** A simple integrity test - needs nonzero modules and pixel-matrix */
213 bool isReady() const
214 { return this && ranges && domains && encoder && pixels.isValid(); }
215 }; // PlaneBlock struct
219 /** \addtogroup interfaces
220 * @{ */
223 /** Interface for modules that control how the image
224 * will be split into rectangular (mostly square) range blocks */
225 struct ISquareRanges: public Interface<ISquareRanges> {
226 /** Structure representing a rectangular range block (usually square) */
227 struct RangeNode;
228 /** List of range nodes (pointers) */
229 typedef std::vector<RangeNode*> RangeList;
231 /** Starts encoding, calls modules in the passed structure.
232 * It should update UpdateInfo continually by the count of encoded pixels.
233 * \throws std::exception when cancelled via UpdateInfo or on other errors */
234 virtual void encode(const PlaneBlock &toEncode) =0;
235 /** Returns a reference to the current range-block list */
236 virtual const RangeList& getRangeList() const =0;
238 /** Write all settings needed for reconstruction */
239 virtual void writeSettings(std::ostream &file) =0;
240 /** Read all settings needed for reconstruction */
241 virtual void readSettings(std::istream &file) =0;
243 /** Writes data needed for reconstruction (except for settings) */
244 virtual void writeData(std::ostream &file) =0;
245 /** Reads data from a stream and reconstructs the positions of range blocks.
246 * \param file the stream to read from
247 * \param block contains the properties of the block to be reconstructed */
248 virtual void readData_buildRanges( std::istream &file, const PlaneBlock &block ) =0;
249 }; // ISquareRanges interface
251 struct ISquareRanges::RangeNode: public Block {
252 /** A common base type for data stored by encoders */
253 struct EncoderData {
254 float bestSE; ///< the best square error found until now
257 /// Encoders can store their data here, deleted in ::~RangeNode
258 mutable EncoderData *encoderData;
259 /// The smallest integer such that the block fits into square with side of length 2^level
260 int level;
262 /** Checks whether the block has regular shape (dimensions equal to 2^level) */
263 bool isRegular() const
264 { return width()==powers[level] && height()==powers[level]; }
265 protected:
266 /** Constructor - initializes ::encoderData to zero, to be used by derived classes */
267 RangeNode(const Block &block,int level_)
268 : Block(block), encoderData(0), level(level_) {}
270 /** Only deletes ::encoderData */
271 ~RangeNode()
272 { delete encoderData; }
273 }; // ISquareRanges::RangeNode struct
278 /** Interface for modules deciding what will square domain blocks look like */
279 struct ISquareDomains: public Interface<ISquareDomains> {
280 /** Describes one domain pool */
281 struct Pool;
282 /** List of pools */
283 typedef std::vector<Pool> PoolList;
285 /** Initializes the pools for given PlaneBlock, assumes settings are OK */
286 virtual void initPools(const PlaneBlock &planeBlock) =0;
287 /** Prepares domains in already initialized pools (and invalidates summers, etc.\ ) */
288 virtual void fillPixelsInPools(PlaneBlock &planeBlock) =0;
290 /** Returns a reference to internal list of domain pools */
291 virtual const PoolList& getPools() const =0;
292 /** Gets densities for all domain pools on a particular level (with size 2^level - zoomed),
293 * returns unzoomed densities */
294 virtual std::vector<short> getLevelDensities(int level,int stdDomCountLog2) =0;
296 /** Writes all settings (data needed for reconstruction that don't depend on the input) */
297 virtual void writeSettings(std::ostream &file) =0;
298 /** Reads all settings (like ::writeSettings) */
299 virtual void readSettings(std::istream &file) =0;
301 /** Writes all input-dependent data */
302 virtual void writeData(std::ostream &file) =0;
303 /** Reads all data, assumes the settings have already been read */
304 virtual void readData(std::istream &file) =0;
305 }; // ISquareDomains interface
307 struct ISquareDomains::Pool: public SummedPixels {
308 char type /// The pool-type identifier (like diamond, module-specific)
309 , level; ///< The count of down-scaling steps (1 for basic domains)
310 float contrFactor; ///< The contractive factor (0,1) - the quotient of areas
312 /** Constructor allocating the parent SummedPixels with correct dimensions
313 * (increased according to \p zoom) */
314 Pool(short width_,short height_,char type_,char level_,float cFactor,short zoom)
315 : type(type_), level(level_), contrFactor(cFactor)
316 { setSize( lShift(width_,zoom), lShift(height_,zoom) ); }
322 /** Interface for square encoders - maintaining mappings from square domains to square ranges */
323 struct ISquareEncoder: public Interface<ISquareEncoder> {
324 typedef IColorTransformer::Plane Plane;
325 typedef ISquareRanges::RangeNode RangeNode;
327 /** Used by encoders, represents information about a domain pool on a level */
328 struct LevelPoolInfo {
329 int indexBegin /// the beginning of domain indices in "this pool" on "this level"
330 , density; ///< the domain density (step size) in "this pool" on "this level"
332 /** [level][pool] -> LevelPoolInfo (the levels are zoomed). For every used level
333 * contains for all domain pools precomputed densities and the domain-ID boundaries */
334 typedef std::vector< std::vector<LevelPoolInfo> > LevelPoolInfos;
336 /** Initializes the module for encoding or decoding of a PlaneBlock */
337 virtual void initialize( IRoot::Mode mode, PlaneBlock &planeBlock ) =0;
338 /** Finds mapping with the best square error for a range (returns the SE),
339 * data neccessary for decoding are stored in RangeNode.encoderData */
340 virtual float findBestSE(const RangeNode &range,bool allowHigherSE=false) =0;
341 /** Finishes encoding - to be ready for saving or decoding (can do some cleanup) */
342 virtual void finishEncoding() =0;
343 /** Performs a decoding action */
344 virtual void decodeAct( DecodeAct action, int count=1 ) =0;
346 /** Write all settings needed for reconstruction (don't depend on encoded thing) */
347 virtual void writeSettings(std::ostream &file) =0;
348 /** Read all settings, opposite to ::writeSettings */
349 virtual void readSettings(std::istream &file) =0;
351 /** Returns the number of phases (progressive encoding), only depends on settings */
352 virtual int phaseCount() const =0;
353 /** Write one phase of data needed for reconstruction (excluding settings) */
354 virtual void writeData(std::ostream &file,int phase) =0;
355 /** Reads one phase of data needed for recostruction,
356 * assumes the settings have been read previously via ::readSettings */
357 virtual void readData(std::istream &file,int phase) =0;
358 }; // ISquareEncoder interface
363 /** Interface for domain-range mapping predictor generator for MStdEncoder */
364 struct IStdEncPredictor: public Interface<IStdEncPredictor> {
365 /** Contains information about one predicted domain block */
366 struct Prediction {
367 explicit Prediction( int domainID_=-1, char rotation_=-1 )
368 : domainID(domainID_), rotation(rotation_) {}
370 int domainID; ///< domain's identification number
371 char rotation; ///< the rotation of the domain
373 /** List of predictions (later often reffered to as a chunk) */
374 typedef std::vector<Prediction> Predictions;
376 /** %Interface for objects that predict domains for a concrete range block */
377 struct IOneRangePredictor {
378 /** Virtual destructor needed for safe deletion of derived classes */
379 virtual ~IOneRangePredictor() {}
380 /** Makes several predictions at once, returns \p store reference */
381 virtual Predictions& getChunk(float maxPredictedSE,Predictions &store) =0;
384 /** Holds plenty precomputed information about the range block to be predicted for */
385 struct NewPredictorData;
387 /** Creates a predictor (passing the ownership) for a range block */
388 virtual IOneRangePredictor* newPredictor(const NewPredictorData &data) =0;
389 /** Releases common resources (to be called when encoding is complete) */
390 virtual void cleanUp() =0;
391 }; // IStdEncPredictor interface
393 struct IStdEncPredictor::NewPredictorData {
394 const ISquareRanges::RangeNode *rangeBlock; ///< Pointer to the range block
395 const SummedPixels *rangePixels; ///< Pointer to range's pixels
396 const ISquareDomains::PoolList *pools; ///< Pointer to the domain pools
397 const ISquareEncoder::LevelPoolInfos::value_type *poolInfos;
398 ///< Pointer to LevelPoolInfos for all pools (for this level)
400 bool allowRotations /// Are rotations allowed?
401 , quantError /// Should quantization errors be taken into account?
402 , allowInversion /// Are mappings with negative linear coefficients allowed?
403 , isRegular; ///< Is this range block regular? (see RangeNode::isRegular)
405 Real maxLinCoeff2 /// The maximum linear coefficient squared (or <0 if none)
406 , bigScaleCoeff; ///< The coefficient of big-scaling penalization
408 Real rSum /// The sum of range block's all pixels
409 , r2Sum /// The sum of squares of range block's pixels
410 , pixCount /// The number of range block's pixels
411 , rnDev2 /// Precomputed = ( ::pixCount*::r2Sum - sqr(::rSum) )
412 , rnDev /// Precomputed = sqrt(::rnDev2)
413 , qrAvg /// The average of range's pixels rounded by the selected quantizer
414 , qrDev /// ::rnDev rounded by the selected quantizer
415 , qrDev2; ///< sqr(::qrDev)
416 #ifndef NDEBUG
417 NewPredictorData()
418 : rangeBlock(0), rangePixels(), pools(0), poolInfos(0) {}
419 #endif
420 }; // NewPredictorData struct
425 /** Integer sequences (de)coder interface */
426 struct IIntCodec: public Interface<IIntCodec> {
427 /** Sets the number of possible symbols to work with from now on data: [0,possib-1] */
428 virtual void setPossibilities(int possib) =0;
429 /** Codes data and sends them into a stream */
430 virtual void encode(std::vector<int> &data,std::ostream &file) =0;
431 /** Reads \c count symbols from \c file, decodes them and fills in \c data */
432 virtual void decode(std::istream &file,int count,std::vector<int> &data) =0;
434 /** Write all settings needed (doesn't include possibilities set) */
435 virtual void writeSettings(std::ostream &file) =0;
436 /** Read all settings needed (doesn't include possibilities set) */
437 virtual void readSettings(std::istream &file) =0;
440 /// @} - interfaces defgroup
442 #endif // INTERFACES_HEADER_