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
221 {
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;
372 private:
374 /**
375 * Error logging
376 */
377 void error(const char *fmt, ...) G_GNUC_PRINTF(2,3);
379 };
383 //########################################################################
384 //# S I O X O B S E R V E R
385 //########################################################################
386 class Siox;
388 /**
389 * This is a class for observing the progress of a Siox engine. Overload
390 * the methods in your subclass to get the desired behaviour.
391 */
392 class SioxObserver
393 {
394 public:
396 /**
397 * Constructor. Context can point to anything, and is usually
398 * used to point to a C++ object or C state object, to delegate
399 * callback processing to something else. Use NULL to ignore.
400 */
401 SioxObserver(void *contextArg) : context(NULL)
402 { context = contextArg; }
404 /**
405 * Destructor
406 */
407 virtual ~SioxObserver()
408 { }
410 /**
411 * Informs the observer how much has been completed.
412 * Return false if the processing should be aborted.
413 */
414 virtual bool progress(float /*percentCompleted*/)
415 {
416 return true;
417 }
419 /**
420 * Send an error string to the Observer. Processing will
421 * be halted.
422 */
423 virtual void error(const std::string &/*msg*/)
424 {
425 }
427 protected:
429 void *context;
431 };
435 //########################################################################
436 //# S I O X
437 //########################################################################
439 /**
440 *
441 */
442 class Siox
443 {
444 public:
446 /**
447 * Confidence corresponding to a certain foreground region (equals one).
448 */
449 static const float CERTAIN_FOREGROUND_CONFIDENCE; //=1.0f;
451 /**
452 * Confidence for a region likely being foreground.
453 */
454 static const float FOREGROUND_CONFIDENCE; //=0.8f;
456 /**
457 * Confidence for foreground or background type being equally likely.
458 */
459 static const float UNKNOWN_REGION_CONFIDENCE; //=0.5f;
461 /**
462 * Confidence for a region likely being background.
463 */
464 static const float BACKGROUND_CONFIDENCE; //=0.1f;
466 /**
467 * Confidence corresponding to a certain background reagion (equals zero).
468 */
469 static const float CERTAIN_BACKGROUND_CONFIDENCE; //=0.0f;
471 /**
472 * Construct a Siox engine
473 */
474 Siox();
476 /**
477 * Construct a Siox engine. Use null to ignore
478 */
479 Siox(SioxObserver *observer);
481 /**
482 *
483 */
484 virtual ~Siox();
486 /**
487 * Extract the foreground of the original image, according
488 * to the values in the confidence matrix. If the operation fails,
489 * sioxImage.isValid() will be false.
490 * backgroundFillColor is any ARGB color, such as 0xffffff (white)
491 * or 0x000000 (black)
492 */
493 virtual SioxImage extractForeground(const SioxImage &originalImage,
494 unsigned int backgroundFillColor);
496 private:
498 SioxObserver *sioxObserver;
500 /**
501 * Progress reporting
502 */
503 bool progressReport(float percentCompleted);
505 /**
506 * Flag this as false during processing to abort
507 */
508 bool keepGoing;
510 /**
511 * Our signature limits
512 */
513 float limits[3];
515 /**
516 * Image width
517 */
518 unsigned int width;
520 /**
521 * Image height
522 */
523 unsigned int height;
525 /**
526 * Image size in pixels
527 */
528 unsigned long pixelCount;
530 /**
531 * Image data
532 */
533 unsigned int *image;
535 /**
536 * Image confidence matrix
537 */
538 float *cm;
540 /**
541 * Markup for image editing
542 */
543 int *labelField;
546 /**
547 * Maximum distance of two lab values.
548 */
549 float clusterSize;
551 /**
552 * Initialize the Siox engine to its 'pristine' state.
553 * Performed at the beginning of extractForeground().
554 */
555 void init();
557 /**
558 * Clean up any debris from processing.
559 */
560 void cleanup();
562 /**
563 * Error logging
564 */
565 void error(const char *fmt, ...) G_GNUC_PRINTF(2,3);
567 /**
568 * Trace logging
569 */
570 void trace(const char *fmt, ...) G_GNUC_PRINTF(2,3);
572 /**
573 * Stage 1 of the color signature work. 'dims' will be either
574 * 2 for grays, or 3 for colors
575 */
576 void colorSignatureStage1(CieLab *points,
577 unsigned int leftBase,
578 unsigned int rightBase,
579 unsigned int recursionDepth,
580 unsigned int *clusters,
581 const unsigned int dims);
583 /**
584 * Stage 2 of the color signature work
585 */
586 void colorSignatureStage2(CieLab *points,
587 unsigned int leftBase,
588 unsigned int rightBase,
589 unsigned int recursionDepth,
590 unsigned int *clusters,
591 const float threshold,
592 const unsigned int dims);
594 /**
595 * Main color signature method
596 */
597 bool colorSignature(const std::vector<CieLab> &inputVec,
598 std::vector<CieLab> &result,
599 const unsigned int dims);
602 /**
603 *
604 */
605 void keepOnlyLargeComponents(float threshold,
606 double sizeFactorToKeep);
608 /**
609 *
610 */
611 int depthFirstSearch(int startPos, float threshold, int curLabel);
614 /**
615 *
616 */
617 void fillColorRegions();
619 /**
620 * Applies the morphological dilate operator.
621 *
622 * Can be used to close small holes in the given confidence matrix.
623 */
624 void dilate(float *cm, int xres, int yres);
626 /**
627 * Applies the morphological erode operator.
628 */
629 void erode(float *cm, int xres, int yres);
631 /**
632 * Normalizes the matrix to values to [0..1].
633 */
634 void normalizeMatrix(float *cm, int cmSize);
636 /**
637 * Multiplies matrix with the given scalar.
638 */
639 void premultiplyMatrix(float alpha, float *cm, int cmSize);
641 /**
642 * Blurs confidence matrix with a given symmetrically weighted kernel.
643 */
644 void smooth(float *cm, int xres, int yres,
645 float f1, float f2, float f3);
647 /**
648 * Squared Euclidian distance of p and q.
649 */
650 float sqrEuclidianDist(float *p, int pSize, float *q);
655 };
660 } // namespace siox
661 } // namespace org
663 #endif /* __SIOX_H__ */
664 //########################################################################
665 //# E N D O F F I L E
666 //########################################################################