00001
00002
00003
00004
00005
00006
00007 #include "CmdMediator.h"
00008 #include "CmdSettingsColorFilter.h"
00009 #include "ColorFilter.h"
00010 #include "ColorFilterHistogram.h"
00011 #include "DigitizeStateContext.h"
00012 #include "DigitizeStateColorPicker.h"
00013 #include "DocumentModelColorFilter.h"
00014 #include "EngaugeAssert.h"
00015 #include "Logger.h"
00016 #include "MainWindow.h"
00017 #include <QBitmap>
00018 #include <QGraphicsPixmapItem>
00019 #include <QGraphicsScene>
00020 #include <QImage>
00021 #include <QMessageBox>
00022
00023 DigitizeStateColorPicker::DigitizeStateColorPicker (DigitizeStateContext &context) :
00024 DigitizeStateAbstractBase (context)
00025 {
00026 }
00027
00028 DigitizeStateColorPicker::~DigitizeStateColorPicker ()
00029 {
00030 }
00031
00032 QString DigitizeStateColorPicker::activeCurve () const
00033 {
00034 return context().mainWindow().selectedGraphCurve();
00035 }
00036
00037 void DigitizeStateColorPicker::begin (CmdMediator *cmdMediator,
00038 DigitizeState previousState)
00039 {
00040 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::begin";
00041
00042 setCursor(cmdMediator);
00043 context().setDragMode(QGraphicsView::NoDrag);
00044
00045
00046 m_previousDigitizeState = previousState;
00047 m_previousBackground = context().mainWindow().selectOriginal(BACKGROUND_IMAGE_ORIGINAL);
00048
00049 context().mainWindow().updateViewsOfSettings(activeCurve ());
00050 }
00051
00052 bool DigitizeStateColorPicker::computeFilterFromPixel (CmdMediator *cmdMediator,
00053 const QPointF &posScreen,
00054 const QString &curveName,
00055 DocumentModelColorFilter &modelColorFilterAfter)
00056 {
00057 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::computeFilterFromPixel";
00058
00059 bool rtn = false;
00060
00061
00062 ColorFilter filter;
00063 QImage image = cmdMediator->document().pixmap().toImage();
00064 QRgb rgbBackground = filter.marginColor(&image);
00065
00066
00067 QPointF posScreenPlusHalf = posScreen - QPointF (0.5, 0.5);
00068
00069 QColor pixel;
00070 rtn = findNearestNonBackgroundPixel (cmdMediator,
00071 image,
00072 posScreenPlusHalf,
00073 rgbBackground,
00074 pixel);
00075 if (rtn) {
00076
00077
00078
00079 int r = qRed (pixel.rgb());
00080 int g = qGreen (pixel.rgb());
00081 int b = qBlue (pixel.rgb());
00082 if (r == g && g == b) {
00083
00084
00085 modelColorFilterAfter.setColorFilterMode (curveName,
00086 COLOR_FILTER_MODE_INTENSITY);
00087
00088 } else {
00089
00090
00091 modelColorFilterAfter.setColorFilterMode (curveName,
00092 COLOR_FILTER_MODE_HUE);
00093
00094 }
00095
00096
00097 double *histogramBins = new double [ColorFilterHistogram::HISTOGRAM_BINS ()];
00098
00099 ColorFilterHistogram filterHistogram;
00100 int maxBinCount;
00101 filterHistogram.generate (filter,
00102 histogramBins,
00103 modelColorFilterAfter.colorFilterMode (curveName),
00104 image,
00105 maxBinCount);
00106
00107
00108 int pixelBin = filterHistogram.binFromPixel(filter,
00109 modelColorFilterAfter.colorFilterMode (curveName),
00110 pixel,
00111 rgbBackground);
00112
00113
00114
00115 int lowerBin = pixelBin, upperBin = pixelBin;
00116 while ((lowerBin > 0) &&
00117 (histogramBins [lowerBin - 1] <= histogramBins [lowerBin]) &&
00118 (histogramBins [lowerBin] > 0)) {
00119 --lowerBin;
00120 }
00121 while ((upperBin < ColorFilterHistogram::HISTOGRAM_BINS () - 1) &&
00122 (histogramBins [upperBin + 1] <= histogramBins [upperBin]) &&
00123 (histogramBins [upperBin] > 0)) {
00124 ++upperBin;
00125 }
00126
00127
00128 int lowerValue = filterHistogram.valueFromBin(filter,
00129 modelColorFilterAfter.colorFilterMode (curveName),
00130 lowerBin);
00131 int upperValue = filterHistogram.valueFromBin(filter,
00132 modelColorFilterAfter.colorFilterMode (curveName),
00133 upperBin);
00134
00135 saveLowerValueUpperValue (modelColorFilterAfter,
00136 curveName,
00137 lowerValue,
00138 upperValue);
00139
00140 delete [] histogramBins;
00141
00142 } else {
00143
00144 QMessageBox::warning (0,
00145 QObject::tr ("Color Picker"),
00146 QObject::tr ("Sorry, but the color picker point must be near a non-background pixel. Please try again."));
00147
00148 }
00149
00150 return rtn;
00151 }
00152
00153 QCursor DigitizeStateColorPicker::cursor(CmdMediator * ) const
00154 {
00155
00156 const int HOT_X_IN_BITMAP = 8;
00157 const int HOT_Y_IN_BITMAP = 24;
00158 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStateColorPicker::cursor";
00159
00160 QBitmap bitmap (":/engauge/img/cursor_eyedropper.xpm");
00161 QBitmap bitmapMask (":/engauge/img/cursor_eyedropper_mask.xpm");
00162 return QCursor (bitmap,
00163 bitmapMask,
00164 HOT_X_IN_BITMAP,
00165 HOT_Y_IN_BITMAP);
00166 }
00167
00168 void DigitizeStateColorPicker::end ()
00169 {
00170 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::end";
00171
00172
00173
00174 context().mainWindow().selectOriginal(m_previousBackground);
00175 }
00176
00177 bool DigitizeStateColorPicker::findNearestNonBackgroundPixel (CmdMediator *cmdMediator,
00178 const QImage &image,
00179 const QPointF &posScreenPlusHalf,
00180 const QRgb &rgbBackground,
00181 QColor &pixel)
00182 {
00183 QPoint pos = posScreenPlusHalf.toPoint ();
00184
00185 int maxRadiusForSearch = cmdMediator->document().modelGeneral().cursorSize();
00186
00187
00188 for (int radius = 0; radius < maxRadiusForSearch; radius++) {
00189
00190 for (int xOffset = -radius; xOffset <= radius; xOffset++) {
00191 for (int yOffset = -radius; yOffset <= radius; yOffset++) {
00192
00193
00194 pixel = image.pixel (pos.x () + xOffset, pos.y () - radius);
00195 if (pixel != rgbBackground) {
00196 return true;
00197 }
00198
00199
00200 pixel = image.pixel (pos.x () + xOffset, pos.y () + radius);
00201 if (pixel != rgbBackground) {
00202 return true;
00203 }
00204
00205
00206 pixel = image.pixel (pos.x () - radius, pos.y () - yOffset);
00207 if (pixel != rgbBackground) {
00208 return true;
00209 }
00210
00211
00212 pixel = image.pixel (pos.x () + radius, pos.y () + yOffset);
00213 if (pixel != rgbBackground) {
00214 return true;
00215 }
00216 }
00217 }
00218 }
00219
00220 return false;
00221 }
00222
00223 void DigitizeStateColorPicker::handleCurveChange(CmdMediator * )
00224 {
00225 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleCurveChange";
00226 }
00227
00228 void DigitizeStateColorPicker::handleKeyPress (CmdMediator * ,
00229 Qt::Key key,
00230 bool )
00231 {
00232 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleKeyPress"
00233 << " key=" << QKeySequence (key).toString ().toLatin1 ().data ();
00234 }
00235
00236 void DigitizeStateColorPicker::handleMouseMove (CmdMediator * ,
00237 QPointF )
00238 {
00239
00240 }
00241
00242 void DigitizeStateColorPicker::handleMousePress (CmdMediator * ,
00243 QPointF )
00244 {
00245 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleMousePress";
00246 }
00247
00248 void DigitizeStateColorPicker::handleMouseRelease (CmdMediator *cmdMediator,
00249 QPointF posScreen)
00250 {
00251 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::handleMouseRelease";
00252
00253 DocumentModelColorFilter modelColorFilterBefore = cmdMediator->document().modelColorFilter();
00254 DocumentModelColorFilter modelColorFilterAfter = cmdMediator->document().modelColorFilter();
00255 if (computeFilterFromPixel (cmdMediator,
00256 posScreen,
00257 context().mainWindow().selectedGraphCurve(),
00258 modelColorFilterAfter)) {
00259
00260
00261 context().requestDelayedStateTransition(m_previousDigitizeState);
00262
00263
00264 QUndoCommand *cmd = new CmdSettingsColorFilter (context ().mainWindow(),
00265 cmdMediator->document (),
00266 modelColorFilterBefore,
00267 modelColorFilterAfter);
00268 context().appendNewCmd(cmdMediator,
00269 cmd);
00270 }
00271 }
00272
00273 void DigitizeStateColorPicker::saveLowerValueUpperValue (DocumentModelColorFilter &modelColorFilterAfter,
00274 const QString &curveName,
00275 double lowerValue,
00276 double upperValue)
00277 {
00278 switch (modelColorFilterAfter.colorFilterMode (curveName)) {
00279 case COLOR_FILTER_MODE_FOREGROUND:
00280 modelColorFilterAfter.setForegroundLow(curveName,
00281 lowerValue);
00282 modelColorFilterAfter.setForegroundHigh(curveName,
00283 upperValue);
00284 break;
00285
00286 case COLOR_FILTER_MODE_HUE:
00287 modelColorFilterAfter.setHueLow(curveName,
00288 lowerValue);
00289 modelColorFilterAfter.setHueHigh(curveName,
00290 upperValue);
00291 break;
00292
00293 case COLOR_FILTER_MODE_INTENSITY:
00294 modelColorFilterAfter.setIntensityLow(curveName,
00295 lowerValue);
00296 modelColorFilterAfter.setIntensityHigh(curveName,
00297 upperValue);
00298 break;
00299
00300 case COLOR_FILTER_MODE_SATURATION:
00301 modelColorFilterAfter.setSaturationLow(curveName,
00302 lowerValue);
00303 modelColorFilterAfter.setSaturationHigh(curveName,
00304 upperValue);
00305 break;
00306
00307 case COLOR_FILTER_MODE_VALUE:
00308 modelColorFilterAfter.setValueLow(curveName,
00309 lowerValue);
00310 modelColorFilterAfter.setValueHigh(curveName,
00311 upperValue);
00312 break;
00313
00314 default:
00315 ENGAUGE_ASSERT (false);
00316 }
00317 }
00318
00319 QString DigitizeStateColorPicker::state() const
00320 {
00321 return "DigitizeStateColorPicker";
00322 }
00323
00324 void DigitizeStateColorPicker::updateModelDigitizeCurve (CmdMediator * ,
00325 const DocumentModelDigitizeCurve & )
00326 {
00327 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::updateModelDigitizeCurve";
00328 }
00329
00330 void DigitizeStateColorPicker::updateModelSegments(const DocumentModelSegments & )
00331 {
00332 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStateColorPicker::updateModelSegments";
00333 }