0dbf76a8e0e187b8ea28bc0c5e49b70535519595
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 CLAB
58 {
59 public:
61 /**
62 *
63 */
64 CLAB()
65 {
66 C = 0;
67 L = A = B = 0.0f;
68 }
71 /**
72 *
73 */
74 CLAB(unsigned long rgb);
77 /**
78 *
79 */
80 CLAB(float lArg, float aArg, float bArg)
81 {
82 C = 0;
83 L = lArg;
84 A = aArg;
85 B = bArg;
86 }
89 /**
90 *
91 */
92 CLAB(const CLAB &other)
93 {
94 C = other.C;
95 L = other.L;
96 A = other.A;
97 B = other.B;
98 }
101 /**
102 *
103 */
104 CLAB &operator=(const CLAB &other)
105 {
106 C = other.C;
107 L = other.L;
108 A = other.A;
109 B = other.B;
110 return *this;
111 }
113 /**
114 *
115 */
116 virtual ~CLAB()
117 {}
119 /**
120 * Retrieve a CLAB value via index.
121 */
122 virtual float operator()(unsigned int index)
123 {
124 if (index==0) return L;
125 else if (index==1) return A;
126 else if (index==2) return B;
127 else return 0;
128 }
131 /**
132 *
133 */
134 virtual void add(const CLAB &other)
135 {
136 C += other.C;
137 L += other.L;
138 A += other.A;
139 B += other.B;
140 }
143 /**
144 *
145 */
146 virtual void mul(float scale)
147 {
148 L *= scale;
149 A *= scale;
150 B *= scale;
151 }
154 /**
155 *
156 */
157 virtual unsigned long toRGB();
159 /**
160 * Computes squared euclidian distance in CLAB space for two colors
161 * given as RGB values.
162 */
163 static float diffSq(unsigned int rgb1, unsigned int rgb2);
165 /**
166 * Computes squared euclidian distance in CLAB space for two colors
167 * given as RGB values.
168 */
169 static float diff(unsigned int rgb0, unsigned int rgb1);
172 unsigned int C;
173 float L;
174 float A;
175 float B;
178 };
181 //########################################################################
182 //# S I O X I M A G E
183 //########################################################################
185 /**
186 * This is a generic image type that provides a consistent interface
187 * to Siox, so that developers will not need to worry about data arrays.
188 */
189 class SioxImage
190 {
191 public:
193 /**
194 * Create an image with the given width and height
195 */
196 SioxImage(unsigned int width, unsigned int height);
198 /**
199 * Copy constructor
200 */
201 SioxImage(const SioxImage &other);
203 /**
204 * Assignment
205 */
206 SioxImage &operator=(const SioxImage &other);
208 /**
209 * Clean up after use.
210 */
211 virtual ~SioxImage();
213 /**
214 * Returns true if the previous operation on this image
215 * was successful, else false.
216 */
217 virtual bool isValid();
219 /**
220 * Sets whether an operation was successful, and whether
221 * this image should be considered a valid one.
222 * was successful, else false.
223 */
224 virtual void setValid(bool val);
226 /**
227 * Set a pixel at the x,y coordinates to the given value.
228 * If the coordinates are out of range, do nothing.
229 */
230 virtual void setPixel(unsigned int x,
231 unsigned int y,
232 unsigned int pixval);
234 /**
235 * Set a pixel at the x,y coordinates to the given r, g, b values.
236 * If the coordinates are out of range, do nothing.
237 */
238 virtual void setPixel(unsigned int x, unsigned int y,
239 unsigned int a,
240 unsigned int r,
241 unsigned int g,
242 unsigned int b);
244 /**
245 * Get a pixel at the x,y coordinates given. If
246 * the coordinates are out of range, return 0
247 */
248 virtual unsigned int getPixel(unsigned int x, unsigned int y);
251 /**
252 * Return the image data buffer
253 */
254 virtual unsigned int *getImageData();
256 /**
257 * Set a confidence value at the x,y coordinates to the given value.
258 * If the coordinates are out of range, do nothing.
259 */
260 virtual void setConfidence(unsigned int x,
261 unsigned int y,
262 float conf);
264 /**
265 * Get a confidence value at the x,y coordinates given. If
266 * the coordinates are out of range, return 0
267 */
268 virtual float getConfidence(unsigned int x, unsigned int y);
270 /**
271 * Return the confidence data buffer
272 */
273 virtual float *getConfidenceData();
275 /**
276 * Return the width of this image
277 */
278 virtual int getWidth();
280 /**
281 * Return the height of this image
282 */
283 virtual int getHeight();
285 /**
286 * Saves this image as a simple color PPM
287 */
288 bool writePPM(const std::string fileName);
292 #ifdef HAVE_GLIB
294 /**
295 * Special constructor to create an image from a GdkPixbuf.
296 */
297 SioxImage(GdkPixbuf *buf);
299 /**
300 * Creates a GdkPixbuf from this image. The user must
301 * remember to destroy the image when no longer needed.
302 * with g_free(pixbuf)
303 */
304 GdkPixbuf *getGdkPixbuf();
306 #endif
308 private:
310 SioxImage()
311 {}
313 /**
314 * Assign values to that of another
315 */
316 void assign(const SioxImage &other);
318 /**
319 * Initialize values. Used by constructors
320 */
321 void init(unsigned int width, unsigned int height);
323 bool valid;
325 unsigned int width;
327 unsigned int height;
329 unsigned long imageSize;
331 /**
332 * Pixel data
333 */
334 unsigned int *pixdata;
336 /**
337 * Confidence matrix data
338 */
339 float *cmdata;
340 };
344 //########################################################################
345 //# S I O X O B S E R V E R
346 //########################################################################
347 class Siox;
349 /**
350 * This is a class for observing the progress of a Siox engine. Overload
351 * the methods in your subclass to get the desired behaviour.
352 */
353 class SioxObserver
354 {
355 public:
357 /**
358 * Constructor. Context can point to anything, and is usually
359 * used to point to a C++ object or C state object, to delegate
360 * callback processing to something else. Use NULL to ignore.
361 */
362 SioxObserver(void *contextArg) : context(NULL)
363 { context = contextArg; }
365 /**
366 * Destructor
367 */
368 virtual ~SioxObserver()
369 { }
371 /**
372 * Informs the observer how much has been completed.
373 * Return false if the processing should be aborted.
374 */
375 virtual bool progress(float percentCompleted)
376 {
377 return true;
378 }
380 /**
381 * Send an error string to the Observer. Processing will
382 * be halted.
383 */
384 virtual void error(const std::string &msg)
385 {
386 }
388 protected:
390 void *context;
392 };
396 //########################################################################
397 //# S I O X
398 //########################################################################
400 /**
401 *
402 */
403 class Siox
404 {
405 public:
407 /**
408 * Confidence corresponding to a certain foreground region (equals one).
409 */
410 static const float CERTAIN_FOREGROUND_CONFIDENCE; //=1.0f;
412 /**
413 * Confidence for a region likely being foreground.
414 */
415 static const float FOREGROUND_CONFIDENCE; //=0.8f;
417 /**
418 * Confidence for foreground or background type being equally likely.
419 */
420 static const float UNKNOWN_REGION_CONFIDENCE; //=0.5f;
422 /**
423 * Confidence for a region likely being background.
424 */
425 static const float BACKGROUND_CONFIDENCE; //=0.1f;
427 /**
428 * Confidence corresponding to a certain background reagion (equals zero).
429 */
430 static const float CERTAIN_BACKGROUND_CONFIDENCE; //=0.0f;
432 /**
433 * Construct a Siox engine
434 */
435 Siox();
437 /**
438 * Construct a Siox engine. Use null to ignore
439 */
440 Siox(SioxObserver *observer);
442 /**
443 *
444 */
445 virtual ~Siox();
447 /**
448 * Extract the foreground of the original image, according
449 * to the values in the confidence matrix. If the operation fails,
450 * sioxImage.isValid() will be false.
451 * backgroundFillColor is any ARGB color, such as 0xffffff (white)
452 * or 0x000000 (black)
453 */
454 virtual SioxImage extractForeground(const SioxImage &originalImage,
455 unsigned int backgroundFillColor);
457 private:
459 SioxObserver *sioxObserver;
461 /**
462 * Progress reporting
463 */
464 bool progressReport(float percentCompleted);
466 /**
467 * Flag this as false during processing to abort
468 */
469 bool keepGoing;
471 /**
472 * Our signature limits
473 */
474 float limits[3];
476 /**
477 * Image width
478 */
479 unsigned int width;
481 /**
482 * Image height
483 */
484 unsigned int height;
486 /**
487 * Image size in pixels
488 */
489 unsigned long pixelCount;
491 /**
492 * Image data
493 */
494 unsigned int *image;
496 /**
497 * Image confidence matrix
498 */
499 float *cm;
501 /**
502 * Markup for image editing
503 */
504 int *labelField;
507 /**
508 * Maximum distance of two lab values.
509 */
510 float clusterSize;
512 /**
513 * Initialize the Siox engine to its 'pristine' state.
514 * Performed at the beginning of extractForeground().
515 */
516 void init();
518 /**
519 * Clean up any debris from processing.
520 */
521 void cleanup();
523 /**
524 * Error logging
525 */
526 void error(char *fmt, ...);
528 /**
529 * Trace logging
530 */
531 void trace(char *fmt, ...);
533 /**
534 * Stage 1 of the color signature work. 'dims' will be either
535 * 2 for grays, or 3 for colors
536 */
537 void colorSignatureStage1(CLAB *points,
538 unsigned int leftBase,
539 unsigned int rightBase,
540 unsigned int recursionDepth,
541 unsigned int *clusters,
542 const unsigned int dims);
544 /**
545 * Stage 2 of the color signature work
546 */
547 void colorSignatureStage2(CLAB *points,
548 unsigned int leftBase,
549 unsigned int rightBase,
550 unsigned int recursionDepth,
551 unsigned int *clusters,
552 const float threshold,
553 const unsigned int dims);
555 /**
556 * Main color signature method
557 */
558 bool colorSignature(const std::vector<CLAB> &inputVec,
559 std::vector<CLAB> &result,
560 const unsigned int dims);
563 /**
564 *
565 */
566 void keepOnlyLargeComponents(float threshold,
567 double sizeFactorToKeep);
569 /**
570 *
571 */
572 int depthFirstSearch(int startPos, float threshold, int curLabel);
575 /**
576 *
577 */
578 void fillColorRegions();
580 /**
581 * Applies the morphological dilate operator.
582 *
583 * Can be used to close small holes in the given confidence matrix.
584 */
585 void dilate(float *cm, int xres, int yres);
587 /**
588 * Applies the morphological erode operator.
589 */
590 void erode(float *cm, int xres, int yres);
592 /**
593 * Normalizes the matrix to values to [0..1].
594 */
595 void normalizeMatrix(float *cm, int cmSize);
597 /**
598 * Multiplies matrix with the given scalar.
599 */
600 void premultiplyMatrix(float alpha, float *cm, int cmSize);
602 /**
603 * Blurs confidence matrix with a given symmetrically weighted kernel.
604 */
605 void smooth(float *cm, int xres, int yres,
606 float f1, float f2, float f3);
608 /**
609 * Squared Euclidian distance of p and q.
610 */
611 float sqrEuclidianDist(float *p, int pSize, float *q);
613 /**
614 * Squared Euclidian distance of p and q.
615 */
616 float sqrEuclidianDist(const CLAB &p, const CLAB &q);
619 };
624 } // namespace siox
625 } // namespace org
627 #endif /* __SIOX_H__ */
628 //########################################################################
629 //# E N D O F F I L E
630 //########################################################################