67c3902e955b259703a35373a47c4deb53559118
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;
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
385 {
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
435 {
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 //########################################################################