#include <cstdlib> #include <iostream> #include <QtGui> #include "bsprofileitem.h" #include "directionalscanner.h" using namespace std; const int BSProfileItem::DISPLAY_INTENSITY = 1; const int BSProfileItem::DISPLAY_GRADIENT = 2; const int BSProfileItem::DISPLAY_CORRELATION_MEAN_1D = 3; const int BSProfileItem::DISPLAY_CORRELATION_FULL_2D = 4; const int BSProfileItem::DISPLAY_CORRELATION_MEAN_2D = 5; const int BSProfileItem::DISPLAY_MIN = DISPLAY_INTENSITY; const int BSProfileItem::DISPLAY_MAX = DISPLAY_CORRELATION_MEAN_2D; const int BSProfileItem::MIN_SCAN = 8; BSProfileItem::BSProfileItem () { profileWidth = 400; profileRatio = 3; gradientUnRatio = 40; gradientLow = 0; stripeWidth = 200; stripeMargin = 5; stripeResol = 4; widWidth = profileWidth + stripeWidth + 2 * stripeMargin; widHeight = 610; profileLow = (256 - (widHeight / profileRatio)) / 2; image = NULL; imageWidth = 0; imageHeight = 0; gMap = NULL; displayItem = DISPLAY_INTENSITY; stripe = 0; correlWidth = 7; correlThick = 3; correlRatio = 4; } QRectF BSProfileItem::boundingRect () const { return QRectF (0, 0, widWidth, widHeight); } void BSProfileItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED (option); Q_UNUSED (widget); paintStripes (painter); switch (displayItem) { case DISPLAY_INTENSITY : paintIntensityProfile (painter); break; case DISPLAY_GRADIENT : paintGradientProfile (painter); break; case DISPLAY_CORRELATION_MEAN_1D : if (setMeanCorrelationStripes ()) paintCorrelationProfile (painter); painter->drawText (100, 20, QString ("W : Correl width = ") + QString::number (correlWidth)); painter->drawText (100, 40, QString ("T : Correl thick = ") + QString::number (correlThick)); break; case DISPLAY_CORRELATION_FULL_2D : if (setFull2dCorrelationStripes ()) paintCorrelationProfile (painter); painter->drawText (100, 20, QString ("W : Correl width = ") + QString::number (correlWidth)); painter->drawText (100, 40, QString ("T : Correl thick = ") + QString::number (correlThick)); break; case DISPLAY_CORRELATION_MEAN_2D : if (setMean2dCorrelationStripes ()) paintCorrelationProfile (painter); painter->drawText (100, 20, QString ("W : Correl width = ") + QString::number (correlWidth)); painter->drawText (100, 40, QString ("T : Correl thick = ") + QString::number (correlThick)); break; } } void BSProfileItem::setImage (QImage *image, VMap *idata) { this->image = image; this->gMap = idata; this->imageWidth = image->width (); this->imageHeight = image->height (); scanp.setSize (image->width (), image->height ()); } void BSProfileItem::buildScans (Pt2i p1, Pt2i p2) { // Updates the central scan end points for parallel display this->pt1 = p1; this->pt2 = p2; // Resets the profiles rightscan.clear (); leftscan.clear (); rightCorrel.clear (); leftCorrel.clear (); rightReCorrel.clear (); leftReCorrel.clear (); stripe = 0; // Gets a scan iterator DirectionalScanner *ds = scanp.getScanner (p1, p2); // Extracts the left scan (with central one) vector<Pt2i> pix; if (ds->first (pix) < MIN_SCAN) { delete ds; return;} leftscan.push_back (pix); bool leftScanOn = true; maxStripe = 0; while (leftScanOn) { vector<Pt2i> scan; if (ds->nextOnLeft (scan) < MIN_SCAN) leftScanOn = false; else { leftscan.push_back (scan); maxStripe ++; } } // Extracts the right scans bool rightScanOn = true; minStripe = 1; while (rightScanOn) { vector<Pt2i> scan; if (ds->nextOnRight (scan) < MIN_SCAN) rightScanOn = false; else { rightscan.push_back (scan); minStripe --; } } // Frees the scan iterator delete ds; } void BSProfileItem::incStripe (int inc) { stripe += inc; if (stripe > maxStripe) stripe = maxStripe; else if (stripe < minStripe) stripe = minStripe; } void BSProfileItem::incCorrelWidth (int down) { if (displayItem <= DISPLAY_CORRELATION_MEAN_2D && displayItem >= DISPLAY_CORRELATION_MEAN_1D) { if (down) { if (correlWidth >= 5) correlWidth -= 2; } else if (correlWidth <= 19) correlWidth += 2; } } void BSProfileItem::incCorrelThick (int down) { if (displayItem <= DISPLAY_CORRELATION_MEAN_2D && displayItem >= DISPLAY_CORRELATION_MEAN_1D) { if (down) { if (correlThick >= 3) correlThick -= 2; } else if (correlThick <= 17) correlThick += 2; } } void BSProfileItem::incCorrelRatio (int down) { if (displayItem <= DISPLAY_CORRELATION_MEAN_2D && displayItem >= DISPLAY_CORRELATION_MEAN_1D) { if (down) { if (correlRatio > 1) correlRatio /= 2; } else correlRatio *= 2; } } void BSProfileItem::toggleDisplay (bool next) { if (displayItem == DISPLAY_CORRELATION_FULL_2D) correlRatio *= 4; displayItem += (next ? 1 : -1); if (displayItem > DISPLAY_MAX) displayItem = DISPLAY_MIN; else if (displayItem < DISPLAY_MIN) displayItem = DISPLAY_MAX; if (displayItem == DISPLAY_CORRELATION_FULL_2D) correlRatio /= 4; } /** * Correlation calculation (first release). * Compares portions of scan bars with a profile extracted at * the first scan centered on the blurred segment. */ void BSProfileItem::setCorrelationStripes (Pt2i p1, Pt2i p2, int segwidth) { leftCorrel.clear (); rightCorrel.clear (); leftReCorrel.clear (); rightReCorrel.clear (); int correlWidth = segwidth; if (correlWidth > (int) leftscan.at(0).size ()) { cerr << "Can't get correlation stripes" << endl; return; } // Gets the central index Pt2i pc ((p1.x () + p2.x ()) / 2, (p1.y () + p2.y ()) / 2); vector<Pt2i>::iterator it = leftscan.at(0).begin (); int dist, pos = 0, minPos = 0; int minDist = (pc.x() - (*it).x()) * (pc.x() - (*it).x()) + (pc.y() - (*it).y()) * (pc.y() - (*it).y()); it ++; while (it != leftscan.at(0).end ()) { dist = (pc.x() - (*it).x()) * (pc.x() - (*it).x()) + (pc.y() - (*it).y()) * (pc.y() - (*it).y()); if (dist < minDist) { minDist = dist; minPos = pos; } it ++; pos ++; } if (minPos - correlWidth / 2 < 0 || minPos + correlWidth / 2 >= (int) leftscan.size ()) { cerr << "Excentred stripe" << endl; return; } // Gets the central template int *centralShape = new int[correlWidth]; for (int i = 0; i < correlWidth; i++) { Pt2i pix = leftscan.at(0).at(minPos-correlWidth/2+i); centralShape[i] = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } // Computes the left correlation stripes vector <vector <Pt2i> >::iterator scit = leftscan.begin (); while (scit != leftscan.end ()) { vector<int> corr; vector<int> recorr; if ((int) ((*scit).size ()) >= correlWidth) { for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { Pt2i pix = (*scit).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } leftCorrel.push_back (corr); leftReCorrel.push_back (recorr); scit ++; } // Computes the right correlation stripes scit = rightscan.begin (); while (scit != rightscan.end ()) { vector<int> corr; vector<int> recorr; if ((int) ((*scit).size ()) >= correlWidth) { for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { Pt2i pix = (*scit).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } rightCorrel.push_back (corr); rightReCorrel.push_back (recorr); scit ++; } } /** Correlation calculation (second release). * Compares portions of scan bars with a mean profile extracted at * the center of the first Nth scans (N = correlThick). */ bool BSProfileItem::setMeanCorrelationStripes () { leftCorrel.clear (); rightCorrel.clear (); leftReCorrel.clear (); rightReCorrel.clear (); int minPos = (int) leftscan.at(0).size () / 2; if (correlWidth > (int) leftscan.at(0).size ()) { cerr << "Can't get correlation stripes" << endl; return false; } // Gets the central template int *centralShape = new int[correlWidth]; for (int i = 0; i < correlWidth; i++) { centralShape[i] = 0; for (int j = 0; j < correlThick; j++) { Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i); centralShape[i] += ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } centralShape[i] /= correlThick; } // Computes the left correlation stripes vector <vector <Pt2i> >::iterator scit = leftscan.begin (); while (scit != leftscan.end ()) { vector<int> corr; vector<int> recorr; if ((int) ((*scit).size ()) >= correlWidth) { for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { Pt2i pix = (*scit).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } leftCorrel.push_back (corr); leftReCorrel.push_back (recorr); scit ++; } // Computes the right correlation stripes scit = rightscan.begin (); while (scit != rightscan.end ()) { vector<int> corr; vector<int> recorr; if ((int) ((*scit).size ()) >= correlWidth) { for (int j = 0; j < ((int) (*scit).size ()) - correlWidth + 1; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { Pt2i pix = (*scit).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } rightCorrel.push_back (corr); rightReCorrel.push_back (recorr); scit ++; } return true; } /** Correlation calculation (third release). * Compares 2D portions of scan bars (N = correlThick) with a 2D profile * extracted at the center of the first Nth scans (N = correlThick). */ bool BSProfileItem::setFull2dCorrelationStripes () { leftCorrel.clear (); rightCorrel.clear (); leftReCorrel.clear (); rightReCorrel.clear (); if ((int) leftscan.size () <= correlThick) { cerr << "Can't get correlation stripes : not enough left scans" << endl; return false; } int minPos = (int) leftscan.at(0).size () / 2; if (correlWidth > (int) leftscan.at(0).size ()) { cerr << "Can't get correlation stripes : scans too narrow" << endl; return false; } // Gets the central template int *centralShape = new int[correlThick * correlWidth]; for (int i = 0; i < correlWidth; i++) for (int j = 0; j < correlThick; j++) { Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i); centralShape[j * correlWidth + i] = ((QColor) image->pixel ( QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } // Computes the left correlation stripes for (int i = 0; i < (int) leftscan.size () - correlThick - 2; i++) { vector<int> corr; vector<int> recorr; if ((int) ((leftscan.at(i)).size ()) >= correlWidth) for (int j = 0; j < ((int) (leftscan.at(i)).size ()) - correlWidth; j++) { int val = 0; for (int cw = 0; cw < correlThick; cw ++) for (int k = 0; k < correlWidth; k++) if ((int) leftscan.at(i+cw).size () > j+k) { Pt2i pix = (leftscan.at(i+cw)).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[cw * correlWidth + k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } leftCorrel.push_back (corr); leftReCorrel.push_back (recorr); } // Computes the right correlation stripes for (int i = correlThick - 1; i < (int) rightscan.size () - 1; i++) { vector<int> corr; vector<int> recorr; if ((int) ((rightscan.at(i)).size ()) >= correlWidth) { for (int j = 0; j < ((int) (rightscan.at(i)).size ()) - correlWidth; j++) { int val = 0; for (int cw = 0; cw < correlThick; cw ++) for (int k = 0; k < correlWidth; k++) if ((int) rightscan.at(i-cw).size () > j+k) { Pt2i pix = (rightscan.at(i-cw)).at(j+k); int diff = ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value () - centralShape[cw * correlWidth + k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } rightCorrel.push_back (corr); rightReCorrel.push_back (recorr); } return true; } /** Correlation calculation (ourth release). * Compares mean portions of scan bars (N = correlThick) with a mean * profile extracted at the center of the first Nth scans (N = correlThick). */ bool BSProfileItem::setMean2dCorrelationStripes () { leftCorrel.clear (); rightCorrel.clear (); leftReCorrel.clear (); rightReCorrel.clear (); if ((int) leftscan.size () <= correlThick) { cerr << "Can't get correlation stripes : not enough left scans" << endl; return false; } int minPos = (int) leftscan.at(0).size () / 2; if (correlWidth > (int) leftscan.at(0).size ()) { cerr << "Can't get correlation stripes : scans too narrow" << endl; return false; } // Gets the central template int *centralShape = new int[correlWidth]; for (int i = 0; i < correlWidth; i++) { centralShape[i] = 0; for (int j = 0; j < correlThick; j++) { Pt2i pix = leftscan.at(j).at(minPos-correlWidth/2+i); centralShape[i] += ((QColor) image->pixel ( QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } centralShape[i] /= correlThick; } // Computes the left correlation stripes for (int i = 0; i < (int) leftscan.size () - correlThick - 2; i++) { vector<int> corr; vector<int> recorr; if ((int) ((leftscan.at(i)).size ()) >= correlWidth) for (int j = 0; j < ((int) (leftscan.at(i)).size ()) - correlWidth; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { int nbval = 0; int locval = 0; for (int cw = 0; cw < correlThick; cw ++) { if ((int) leftscan.at(i+cw).size () > j+k) { nbval ++; Pt2i pix = (leftscan.at(i+cw)).at(j+k); locval += ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } } int diff = locval / nbval - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } leftCorrel.push_back (corr); leftReCorrel.push_back (recorr); } // Computes the right correlation stripes for (int i = correlThick - 1; i < (int) rightscan.size () - 1; i++) { vector<int> corr; vector<int> recorr; if ((int) ((rightscan.at(i)).size ()) >= correlWidth) { for (int j = 0; j < ((int) (rightscan.at(i)).size ()) - correlWidth; j++) { int val = 0; for (int k = 0; k < correlWidth; k++) { int nbval = 0; int locval = 0; for (int cw = 0; cw < correlThick; cw ++) { if ((int) rightscan.at(i-cw).size () > j+k) { nbval ++; Pt2i pix = (rightscan.at(i-cw)).at(j+k); locval += ((QColor) image->pixel (QPoint (pix.x (), imageHeight - 1 - pix.y ()))).value (); } } int diff = locval / nbval - centralShape[k]; val += (diff < 0 ? - diff : diff); } corr.push_back (val); recorr.push_back ((int) val); } } rightCorrel.push_back (corr); rightReCorrel.push_back (recorr); } return true; } void BSProfileItem::getLocalMinimaIndices (vector<int> &indices, const vector<int> &signal) const { int ng = signal.size (); int offset = 0; bool up = true; // Gets the first distinct value from start while (offset < ng - 1 && signal.at (offset) == signal.at (0)) { if (signal.at (offset) - signal.at (offset + 1) < 0) { up = true; break; } if (signal.at (offset) - signal.at (offset + 1) > 0) { up = false; break; } offset++; } for(int i = offset; i < ng - 1; i++) { if (up) { if ((signal.at (i + 1) - signal.at (i)) < 0) up = false; } else { if (signal.at (i + 1) - signal.at (i) > 0) { up = true; int k = i; while (signal.at (k) == signal.at (i)) k--; indices.push_back (k + 1 + (i - k - 1) / 2); } } } } void BSProfileItem::paintStripes (QPainter *painter) { int lx = profileWidth + stripeMargin + stripeWidth / 2 - stripeResol / 2; int cx = 0, cy = widHeight / 2; vector <vector <Pt2i> >::iterator bigit; if (rightscan.size ()) lx -= rightscan.at(0).size () * stripeResol / 2; else if (leftscan.size ()) lx -= leftscan.at(0).size () * stripeResol / 2; painter->setPen (QPen (Qt::red, 2)); painter->drawRect (profileWidth + stripeMargin - 1, stripeMargin - 1, stripeWidth + 2, widHeight - 2 * stripeMargin + 2); // Lower part (right side) if (rightscan.size ()) { bigit = rightscan.begin (); while (cy <= widHeight - stripeMargin - stripeResol && bigit != rightscan.end ()) { cx = lx; vector<Pt2i> scan = *bigit; vector<Pt2i>::iterator it = scan.begin (); while (cx < widWidth - stripeMargin - stripeResol && it != scan.end ()) { if (cx >= profileWidth + stripeMargin) painter->fillRect (cx, cy, stripeResol, stripeResol, QBrush (image->pixel ((*it).x (), imageHeight - 1 - (*it).y ()))); it ++; cx += stripeResol; } bigit ++; cy += stripeResol; } } // Upper part (left side) if (leftscan.size ()) { cy = widHeight / 2 - 2 * stripeResol; bigit = leftscan.begin (); while (cy >= stripeResol + 1 && bigit != leftscan.end ()) { cx = lx; vector<Pt2i> scan = *bigit; vector<Pt2i>::iterator it = scan.begin (); while (cx < widHeight - stripeMargin - stripeResol && it != scan.end ()) { if (cx >= profileWidth + stripeMargin) painter->fillRect (cx, cy, stripeResol, stripeResol, QBrush (image->pixel ((*it).x (), imageHeight - 1 - (*it).y ()))); it ++; cx += stripeResol; } bigit ++; cy -= stripeResol; } } // Enclosing the central scan if (stripe >= 0) cy = widHeight / 2 - 1 - 2 * stripeResol - stripe * stripeResol; else cy = widHeight / 2 - 1 - (1 + stripe) * stripeResol; painter->setPen (QPen (Qt::green, 2)); painter->drawRect (profileWidth + stripeMargin - 1, cy, stripeWidth + 2, stripeResol + 2); } void BSProfileItem::paintIntensityProfile (QPainter *painter) { if (rightscan.size () || leftscan.size ()) { vector<Pt2i> scan; if (stripe >= 0) scan = leftscan.at (stripe); else scan = rightscan.at (- stripe - 1); int h, cx = 0, w = profileWidth / (leftscan.at(0)).size (); vector<Pt2i>::iterator it = scan.begin (); while (it != scan.end ()) { if ((*it).x () < 0 || (*it).x () >= imageWidth || (*it).y () < 0 || (*it).y () >= imageHeight) cerr << "OUT OF IMAGE BOUNDS : (" << (*it).x () << "," << imageHeight - 1 - (*it).y () << ")" << endl; else { h = ((QColor) image->pixel (QPoint ((*it).x (), imageHeight - 1 - (*it).y ()))).value (); h = (h - profileLow) * profileRatio; if (h < 0) h = 0; else if (h > widHeight) h = widHeight; if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue)); it ++; cx += w; } } painter->setPen (QPen (Qt::black, 2)); scan = leftscan.at (0); it = scan.begin (); int prevh = ((QColor) image->pixel (QPoint ((*it).x (), imageHeight - 1 - (*it).y ()))).value (); prevh = (prevh - profileLow) * profileRatio; if (prevh < 0) prevh = 0; else if (prevh > widWidth) prevh = widWidth; cx = 0; while (it != scan.end ()) { h = ((QColor) image->pixel (QPoint ((*it).x (), imageHeight - 1 - (*it).y ()))).value (); h = (h - profileLow) * profileRatio; if (h < 0) h = 0; else if (h > widWidth) h = widWidth; painter->drawLine (cx, widWidth - prevh, cx, widWidth - h); painter->drawLine (cx, widWidth - h, cx + w, widWidth - h); prevh = h; it ++; cx += w; } } } void BSProfileItem::paintGradientProfile (QPainter *painter) { if (rightscan.size () || leftscan.size ()) { vector<Pt2i> scan; if (stripe >= 0) scan = leftscan.at (stripe); else scan = rightscan.at (- stripe - 1); int cx = 0, w = profileWidth / (leftscan.at(0)).size (); int h, prevh; vector<Pt2i>::iterator it = scan.begin (); while (it != scan.end ()) { if ((*it).x () < 0 || (*it).x () >= imageWidth || (*it).y () < 0 || (*it).y () >= imageHeight) cerr << "OUT OF IMAGE BOUNDS : (" << (*it).x () << "," << imageHeight - 1 - (*it).y () << ")" << endl; else { h = (gMap->magn ((*it).x (), (*it).y ()) - gradientLow) / gradientUnRatio; if (h < 0) h = 0; else if (h > widHeight) h = widHeight; if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue)); it ++; cx += w; } } painter->setPen (QPen (Qt::black, 2)); scan = leftscan.at (0); it = scan.begin (); prevh = (gMap->magn ((*it).x (), (*it).y ()) - gradientLow) / gradientUnRatio; if (prevh < 0) prevh = 0; else if (prevh > widWidth) prevh = widWidth; cx = 0; while (it != scan.end ()) { h = (gMap->magn ((*it).x (), (*it).y ()) - gradientLow) / gradientUnRatio; if (h < 0) h = 0; else if (h > widWidth) h = widWidth; painter->drawLine (cx, widWidth - prevh, cx, widWidth - h); painter->drawLine (cx, widWidth - h, cx + w, widWidth - h); prevh = h; it ++; cx += w; } } } void BSProfileItem::paintCorrelationProfile (QPainter *painter) { if (rightCorrel.size () || leftCorrel.size ()) { Pt2i gr; vector<int> scan; vector<int> rescan; if (stripe >= 0) { scan = leftCorrel.at (stripe); rescan = leftReCorrel.at (stripe); } else { scan = rightCorrel.at (- stripe - 1); rescan = rightReCorrel.at (- stripe - 1); } int h, cx = 0, w = profileWidth / (leftscan.at(0)).size (); vector<int>::iterator it = scan.begin (); while (it != scan.end ()) { h = (*it) * correlRatio; if (h > widHeight) h = widHeight; if (h) painter->fillRect (cx, widHeight - h, w, h, QBrush (Qt::blue)); it ++; cx += w; } vector<int> locs; getLocalMinimaIndices (locs, rescan); it = locs.begin (); while (it != locs.end ()) { h = scan.at(*it) * correlRatio; painter->fillRect ((*it) * w + 4, widHeight - h - 14, w - 8, 10, QBrush (Qt::red)); it ++; } painter->setPen (QPen (Qt::black, 2)); scan = leftCorrel.at (0); it = scan.begin (); int prevh = (*it) * correlRatio; if (prevh > widWidth) prevh = widWidth; cx = 0; while (it != scan.end ()) { h = (*it) * correlRatio; if (h > widWidth) h = widWidth; painter->drawLine (cx, widWidth - prevh, cx, widWidth - h); painter->drawLine (cx, widWidth - h, cx + w, widWidth - h); prevh = h; it ++; cx += w; } } }