00001
00002
00003
00004
00005
00006
00007 #include "ColorConstants.h"
00008 #include "ColorFilter.h"
00009 #include "ColorFilterStrategyForeground.h"
00010 #include "ColorFilterStrategyHue.h"
00011 #include "ColorFilterStrategyIntensity.h"
00012 #include "ColorFilterStrategySaturation.h"
00013 #include "ColorFilterStrategyValue.h"
00014 #include "EngaugeAssert.h"
00015 #include "mmsubs.h"
00016 #include <QDebug>
00017 #include <qmath.h>
00018 #include <QImage>
00019
00020 ColorFilter::ColorFilter()
00021 {
00022 createStrategies ();
00023 }
00024
00025 bool ColorFilter::colorCompare (QRgb rgb1,
00026 QRgb rgb2) const
00027 {
00028 const long MASK = 0xf0f0f0f0;
00029 return (rgb1 & MASK) == (rgb2 & MASK);
00030 }
00031
00032 void ColorFilter::createStrategies ()
00033 {
00034 m_strategies [COLOR_FILTER_MODE_FOREGROUND] = new ColorFilterStrategyForeground ();
00035 m_strategies [COLOR_FILTER_MODE_HUE ] = new ColorFilterStrategyHue ();
00036 m_strategies [COLOR_FILTER_MODE_INTENSITY ] = new ColorFilterStrategyIntensity ();
00037 m_strategies [COLOR_FILTER_MODE_SATURATION] = new ColorFilterStrategySaturation ();
00038 m_strategies [COLOR_FILTER_MODE_VALUE ] = new ColorFilterStrategyValue ();
00039 }
00040
00041 void ColorFilter::filterImage (const QImage &imageOriginal,
00042 QImage &imageFiltered,
00043 ColorFilterMode colorFilterMode,
00044 double low,
00045 double high,
00046 QRgb rgbBackground)
00047 {
00048 ENGAUGE_ASSERT (imageOriginal.width () == imageFiltered.width());
00049 ENGAUGE_ASSERT (imageOriginal.height() == imageFiltered.height());
00050 ENGAUGE_ASSERT (imageFiltered.format () == QImage::Format_RGB32);
00051
00052 for (int x = 0; x < imageOriginal.width(); x++) {
00053 for (int y = 0; y < imageOriginal.height (); y++) {
00054
00055 QColor pixel = imageOriginal.pixel (x, y);
00056 bool isOn = false;
00057 if (pixel.rgb() != rgbBackground) {
00058
00059 isOn = pixelUnfilteredIsOn (colorFilterMode,
00060 pixel,
00061 rgbBackground,
00062 low,
00063 high);
00064 }
00065
00066 imageFiltered.setPixel (x, y, (isOn ?
00067 QColor (Qt::black).rgb () :
00068 QColor (Qt::white).rgb ()));
00069 }
00070 }
00071 }
00072
00073 QRgb ColorFilter::marginColor(const QImage *image) const
00074 {
00075
00076 ColorList colorCounts;
00077 for (int x = 0; x < image->width (); x++) {
00078 mergePixelIntoColorCounts (image->pixel (x, 0), colorCounts);
00079 mergePixelIntoColorCounts (image->pixel (x, image->height () - 1), colorCounts);
00080 }
00081 for (int y = 0; y < image->height (); y++) {
00082 mergePixelIntoColorCounts (image->pixel (0, y), colorCounts);
00083 mergePixelIntoColorCounts (image->pixel (image->width () - 1, y), colorCounts);
00084 }
00085
00086
00087 ColorFilterEntry entryMax;
00088 entryMax.count = 0;
00089 for (ColorList::const_iterator itr = colorCounts.begin (); itr != colorCounts.end (); itr++) {
00090 if ((*itr).count > entryMax.count) {
00091 entryMax = *itr;
00092 }
00093 }
00094
00095 return entryMax.color.rgb();
00096 }
00097
00098 void ColorFilter::mergePixelIntoColorCounts (QRgb pixel,
00099 ColorList &colorCounts) const
00100 {
00101 ColorFilterEntry entry;
00102 entry.color = pixel;
00103 entry.count = 0;
00104
00105
00106 bool found = false;
00107 for (ColorList::iterator itr = colorCounts.begin (); itr != colorCounts.end (); itr++) {
00108 if (colorCompare (entry.color.rgb(),
00109 (*itr).color.rgb())) {
00110 found = true;
00111 ++(*itr).count;
00112 break;
00113 }
00114 }
00115
00116 if (!found) {
00117 colorCounts.append (entry);
00118 }
00119 }
00120
00121 bool ColorFilter::pixelFilteredIsOn (const QImage &image,
00122 int x,
00123 int y) const
00124 {
00125 bool rtn = false;
00126
00127 if ((0 <= x) &&
00128 (0 <= y) &&
00129 (x < image.width()) &&
00130 (y < image.height())) {
00131
00132
00133
00134 const int BLACK_WHITE_THRESHOLD = 255 / 2;
00135 int gray = qGray (pixelRGB (image, x, y));
00136 rtn = (gray < BLACK_WHITE_THRESHOLD);
00137
00138 }
00139
00140 return rtn;
00141 }
00142
00143 bool ColorFilter::pixelUnfilteredIsOn (ColorFilterMode colorFilterMode,
00144 const QColor &pixel,
00145 QRgb rgbBackground,
00146 double low0To1,
00147 double high0To1) const
00148 {
00149 bool rtn = false;
00150
00151 double s = pixelToZeroToOneOrMinusOne (colorFilterMode,
00152 pixel,
00153 rgbBackground);
00154 if (s >= 0.0) {
00155 if (low0To1 <= high0To1) {
00156
00157
00158 rtn = (low0To1 <= s) && (s <= high0To1);
00159
00160 } else {
00161
00162
00163 rtn = (s <= high0To1) || (low0To1 <= s);
00164
00165 }
00166 }
00167
00168 return rtn;
00169 }
00170
00171 double ColorFilter::pixelToZeroToOneOrMinusOne (ColorFilterMode colorFilterMode,
00172 const QColor &pixel,
00173 QRgb rgbBackground) const
00174 {
00175 if (m_strategies.contains (colorFilterMode)) {
00176
00177 return m_strategies [colorFilterMode]->pixelToZeroToOne (pixel,
00178 rgbBackground);
00179
00180 } else {
00181
00182 ENGAUGE_ASSERT (false);
00183 return 0.0;
00184
00185 }
00186 }
00187
00188 int ColorFilter::zeroToOneToValue (ColorFilterMode colorFilterMode,
00189 double s) const
00190 {
00191 if (m_strategies.contains (colorFilterMode)) {
00192
00193 return m_strategies [colorFilterMode]->zeroToOneToValue (s);
00194
00195 } else {
00196
00197 ENGAUGE_ASSERT (false);
00198 return 0;
00199
00200 }
00201 }