Code

67c3902e955b259703a35373a47c4deb53559118
[inkscape.git] / src / trace / siox.h
1 #ifndef __SIOX_H__
2 #define __SIOX_H__
3 /**
4  *  Copyright 2005, 2006 by Gerald Friedland, Kristian Jantz and Lars Knipping
5  *
6  *  Conversion to C++ for Inkscape by Bob Jamison
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License");
9  *  you may not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS,
16  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  */
21 /**
22  * Note by Bob Jamison:
23  * After translating the siox.org Java API to C++ and receiving an
24  * education into this wonderful code,  I began again,
25  * and started this version using lessons learned.  This version is
26  * an attempt to provide an dependency-free SIOX engine that anyone
27  * can use in their project with minimal effort.
28  *
29  * Many thanks to the fine people at siox.org.
30  */
32 #include <string>
33 #include <vector>
35 #define HAVE_GLIB
37 #ifdef HAVE_GLIB
38 #include <glib.h>
39 #include <gdk-pixbuf/gdk-pixbuf.h>
40 #endif
43 namespace org
44 {
46 namespace siox
47 {
50 //########################################################################
51 //#  C L A B
52 //########################################################################
54 /**
55  *
56  */
57 class CieLab
58 {
59 public:
61     /**
62      *
63      */
64     CieLab()
65         {
66         init();
67         C = 0;
68         L = A = B = 0.0f;
69         }
72     /**
73      *
74      */
75     CieLab(unsigned long rgb);
78     /**
79      *
80      */
81     CieLab(float lArg, float aArg, float bArg)
82         {
83         init();
84         C = 0;
85         L = lArg;
86         A = aArg;
87         B = bArg;
88         }
91     /**
92      *
93      */
94     CieLab(const CieLab &other)
95         {
96         init();
97         C = other.C;
98         L = other.L;
99         A = other.A;
100         B = other.B;
101         }
104     /**
105      *
106      */
107     CieLab &operator=(const CieLab &other)
108         {
109         init();
110         C = other.C;
111         L = other.L;
112         A = other.A;
113         B = other.B;
114         return *this;
115         }
117     /**
118      *
119      */
120     virtual ~CieLab()
121         {}
123     /**
124      * Retrieve a CieLab value via index.
125      */
126     virtual float operator()(unsigned int index)
127         {
128         if      (index==0) return L;
129         else if (index==1) return A;
130         else if (index==2) return B;
131         else return 0;
132         }
135     /**
136      *
137      */
138     virtual void add(const CieLab &other)
139         {
140         C += other.C;
141         L += other.L;
142         A += other.A;
143         B += other.B;
144         }
147     /**
148      *
149      */
150     virtual void mul(float scale)
151         {
152         L *= scale;
153         A *= scale;
154         B *= scale;
155         }
158     /**
159      *
160      */
161     virtual unsigned long toRGB();
163     /**
164      * Approximate cube roots
165      */
166     double cbrt(double x);
168     /**
169      *
170      */
171     double qnrt(double x);
173     /**
174      * Raise to the 2.4 power
175      */
176     double pow24(double x);
178     /**
179      * Squared Euclidian distance between this and another color
180      */
181     float diffSq(const CieLab &other);
183     /**
184      * Computes squared euclidian distance in CieLab space for two colors
185      * given as RGB values.
186      */
187     static float diffSq(unsigned int rgb1, unsigned int rgb2);
189     /**
190      * Computes squared euclidian distance in CieLab space for two colors
191      * given as RGB values.
192      */
193     static float diff(unsigned int rgb0, unsigned int rgb1);
196     unsigned int C;
197     float L;
198     float A;
199     float B;
201 private:
203     /**
204      *
205      */
206     void init();
209 };
212 //########################################################################
213 //#  S I O X    I M A G E
214 //########################################################################
216 /**
217  * This is a generic image type that provides a consistent interface
218  * to Siox, so that developers will not need to worry about data arrays.
219  */
220 class SioxImage
222 public:
224     /**
225      *  Create an image with the given width and height
226      */
227     SioxImage(unsigned int width, unsigned int height);
229     /**
230      *  Copy constructor
231      */
232     SioxImage(const SioxImage &other);
234     /**
235      *  Assignment
236      */
237     SioxImage &operator=(const SioxImage &other);
239     /**
240      * Clean up after use.
241      */
242     virtual ~SioxImage();
244     /**
245      * Returns true if the previous operation on this image
246      * was successful, else false.
247      */
248     virtual bool isValid();
250     /**
251      * Sets whether an operation was successful, and whether
252      * this image should be considered a valid one.
253      * was successful, else false.
254      */
255     virtual void setValid(bool val);
257     /**
258      * Set a pixel at the x,y coordinates to the given value.
259      * If the coordinates are out of range, do nothing.
260      */
261     virtual void setPixel(unsigned int x,
262                           unsigned int y,
263                           unsigned int pixval);
265     /**
266      * Set a pixel at the x,y coordinates to the given r, g, b values.
267      * If the coordinates are out of range, do nothing.
268      */
269     virtual void setPixel(unsigned int x, unsigned int y,
270                           unsigned int a, 
271                           unsigned int r, 
272                           unsigned int g,
273                           unsigned int b);
275     /**
276      *  Get a pixel at the x,y coordinates given.  If
277      *  the coordinates are out of range, return 0
278      */
279     virtual unsigned int getPixel(unsigned int x, unsigned int y);
282     /**
283      *  Return the image data buffer
284      */
285     virtual unsigned int *getImageData();
287     /**
288      * Set a confidence value at the x,y coordinates to the given value.
289      * If the coordinates are out of range, do nothing.
290      */
291     virtual void setConfidence(unsigned int x,
292                                unsigned int y,
293                                float conf);
295     /**
296      *  Get a confidence value at the x,y coordinates given.  If
297      *  the coordinates are out of range, return 0
298      */
299     virtual float getConfidence(unsigned int x, unsigned int y);
301     /**
302      *  Return the confidence data buffer
303      */
304     virtual float *getConfidenceData();
306     /**
307      * Return the width of this image
308      */
309     virtual int getWidth();
311     /**
312      * Return the height of this image
313      */
314     virtual int getHeight();
316     /**
317      * Saves this image as a simple color PPM
318      */
319     bool writePPM(const std::string fileName);
323 #ifdef HAVE_GLIB
325     /**
326      * Special constructor to create an image from a GdkPixbuf.
327      */
328     SioxImage(GdkPixbuf *buf);
330     /**
331      * Creates a GdkPixbuf from this image.  The user must
332      * remember to destroy the image when no longer needed.
333      * with g_free(pixbuf)
334      */
335     GdkPixbuf *getGdkPixbuf();
337 #endif
339 private:
341     SioxImage()
342         {}
344     /**
345      * Assign values to that of another
346      */
347     void assign(const SioxImage &other);
349     /**
350      * Initialize values.  Used by constructors
351      */
352     void init(unsigned int width, unsigned int height);
354     bool valid;
356     unsigned int width;
358     unsigned int height;
360     unsigned long imageSize;
362     /**
363      * Pixel data
364      */
365     unsigned int *pixdata;
367     /**
368      * Confidence matrix data
369      */
370     float *cmdata;
371 };
375 //########################################################################
376 //#  S I O X    O B S E R V E R
377 //########################################################################
378 class Siox;
380 /**
381  *  This is a class for observing the progress of a Siox engine.  Overload
382  *  the methods in your subclass to get the desired behaviour.
383  */
384 class SioxObserver
386 public:
388     /**
389      *  Constructor.  Context can point to anything, and is usually
390      *  used to point to a C++ object or C state object, to delegate
391      *  callback processing to something else.  Use NULL to ignore.
392      */
393     SioxObserver(void *contextArg) : context(NULL)
394         { context = contextArg; }
396     /**
397      *  Destructor
398      */
399     virtual ~SioxObserver()
400         { }
402     /**
403      *  Informs the observer how much has been completed.
404      *  Return false if the processing should be aborted.
405      */
406     virtual bool progress(float percentCompleted)
407         {
408         return true;
409         }
411     /**
412      *  Send an error string to the Observer.  Processing will
413      *  be halted.
414      */
415     virtual void error(const std::string &msg)
416         {
417         }
419 protected:
421     void *context;
423 };
427 //########################################################################
428 //#  S I O X
429 //########################################################################
431 /**
432  *
433  */
434 class Siox
436 public:
438     /**
439      * Confidence corresponding to a certain foreground region (equals one).
440      */
441     static const float CERTAIN_FOREGROUND_CONFIDENCE; //=1.0f;
443     /**
444      * Confidence for a region likely being foreground.
445      */
446     static const float FOREGROUND_CONFIDENCE; //=0.8f;
448     /** 
449      * Confidence for foreground or background type being equally likely.
450      */
451     static const float UNKNOWN_REGION_CONFIDENCE; //=0.5f;
453     /**
454      * Confidence for a region likely being background.
455      */
456     static const float BACKGROUND_CONFIDENCE; //=0.1f;
458     /**
459      * Confidence corresponding to a certain background reagion (equals zero).
460      */
461     static const float CERTAIN_BACKGROUND_CONFIDENCE; //=0.0f;
463     /**
464      *  Construct a Siox engine
465      */
466     Siox();
468     /**
469      *  Construct a Siox engine.  Use null to ignore
470      */
471     Siox(SioxObserver *observer);
473     /**
474      *
475      */
476     virtual ~Siox();
478     /**
479      *  Extract the foreground of the original image, according
480      *  to the values in the confidence matrix.  If the operation fails,
481      *  sioxImage.isValid()  will be false.
482      *  backgroundFillColor is any ARGB color,  such as 0xffffff (white)
483      *  or 0x000000 (black)
484      */
485     virtual SioxImage extractForeground(const SioxImage &originalImage,
486                                         unsigned int backgroundFillColor);
488 private:
490     SioxObserver *sioxObserver;
492     /**
493      * Progress reporting
494      */
495     bool progressReport(float percentCompleted);
497     /**
498      * Flag this as false during processing to abort
499      */
500     bool keepGoing;
502     /**
503      * Our signature limits
504      */
505     float limits[3];
507     /**
508      * Image width
509      */
510     unsigned int width;
512     /**
513      * Image height
514      */
515     unsigned int height;
517     /**
518      * Image size in pixels
519      */
520     unsigned long pixelCount;
522     /**
523      * Image data
524      */
525     unsigned int *image;
527     /**
528      * Image confidence matrix
529      */
530     float *cm;
532     /**
533      * Markup for image editing
534      */
535     int *labelField;
538     /**
539      * Maximum distance of two lab values.
540      */
541     float clusterSize;
543     /**
544      *  Initialize the Siox engine to its 'pristine' state.
545      *  Performed at the beginning of extractForeground().
546      */
547     void init();
549     /**
550      *  Clean up any debris from processing.
551      */
552     void cleanup();
554     /**
555      * Error logging
556      */
557     void error(char *fmt, ...);
559     /**
560      * Trace logging
561      */
562     void trace(char *fmt, ...);
564     /**
565      *  Stage 1 of the color signature work.  'dims' will be either
566      *  2 for grays, or 3 for colors
567      */
568     void colorSignatureStage1(CieLab *points,
569                               unsigned int leftBase,
570                               unsigned int rightBase,
571                               unsigned int recursionDepth,
572                               unsigned int *clusters,
573                               const unsigned int dims);
575     /**
576      *  Stage 2 of the color signature work
577      */
578     void colorSignatureStage2(CieLab         *points,
579                               unsigned int leftBase,
580                               unsigned int rightBase,
581                               unsigned int recursionDepth,
582                               unsigned int *clusters,
583                               const float  threshold,
584                               const unsigned int dims);
586     /**
587      *  Main color signature method
588      */
589     bool colorSignature(const std::vector<CieLab> &inputVec,
590                         std::vector<CieLab> &result,
591                         const unsigned int dims);
594     /**
595      *
596      */
597     void keepOnlyLargeComponents(float threshold,
598                                  double sizeFactorToKeep);
600     /**
601      *
602      */
603     int depthFirstSearch(int startPos, float threshold, int curLabel);
606     /**
607      *
608      */
609     void fillColorRegions();
611     /**
612      * Applies the morphological dilate operator.
613      *
614      * Can be used to close small holes in the given confidence matrix.
615      */
616     void dilate(float *cm, int xres, int yres);
618     /**
619      * Applies the morphological erode operator.
620      */
621     void erode(float *cm, int xres, int yres);
623     /**
624      * Normalizes the matrix to values to [0..1].
625      */
626     void normalizeMatrix(float *cm, int cmSize);
628     /**
629      * Multiplies matrix with the given scalar.
630      */
631     void premultiplyMatrix(float alpha, float *cm, int cmSize);
633     /**
634      * Blurs confidence matrix with a given symmetrically weighted kernel.
635      */
636     void smooth(float *cm, int xres, int yres,
637                   float f1, float f2, float f3);
639     /**
640      * Squared Euclidian distance of p and q.
641      */
642     float sqrEuclidianDist(float *p, int pSize, float *q);
647 };
652 } // namespace siox
653 } // namespace org
655 #endif /* __SIOX_H__ */
656 //########################################################################
657 //#  E N D    O F    F I L E
658 //########################################################################