29 #include "ksane_viewer.moc"
32 #include <QGraphicsPixmapItem>
33 #include <QGraphicsScene>
34 #include <QGraphicsRectItem>
35 #include <QWheelEvent>
50 struct KSaneViewer::Private
53 SelectionItem *selection;
86 d->scene->setSceneRect(0, 0, img->
width(), img->
height());
90 d->selection->setZValue(10);
91 d->selection->setSaved(
false);
92 d->selection->setMaxRight(img->
width());
93 d->selection->setMaxBottom(img->
height());
94 d->selection->setRect(d->scene->sceneRect());
95 d->selection->setVisible(
false);
103 d->hideTop->setOpacity(0.4);
104 d->hideBottom->setOpacity(0.4);
105 d->hideRight->setOpacity(0.4);
106 d->hideLeft->setOpacity(0.4);
107 d->hideArea->setOpacity(0.6);
109 d->hideTop->setPen(Qt::NoPen);
110 d->hideBottom->setPen(Qt::NoPen);
111 d->hideRight->setPen(Qt::NoPen);
112 d->hideLeft->setPen(Qt::NoPen);
113 d->hideArea->setPen(Qt::NoPen);
115 d->hideTop->setBrush(
QBrush(Qt::black));
116 d->hideBottom->setBrush(
QBrush(Qt::black));
117 d->hideRight->setBrush(
QBrush(Qt::black));
118 d->hideLeft->setBrush(
QBrush(Qt::black));
120 d->scene->addItem(d->selection);
121 d->scene->addItem(d->hideLeft);
122 d->scene->addItem(d->hideRight);
123 d->scene->addItem(d->hideTop);
124 d->scene->addItem(d->hideBottom);
125 d->scene->addItem(d->hideArea);
128 d->selectionList.clear();
131 d->zoomInAction =
new QAction(KIcon(
"zoom-in"), i18n(
"Zoom In"),
this);
132 connect(d->zoomInAction, SIGNAL(triggered()),
this, SLOT(
zoomIn()));
134 d->zoomOutAction =
new QAction(KIcon(
"zoom-out"), i18n(
"Zoom Out"),
this);
135 connect(d->zoomOutAction, SIGNAL(triggered()),
this, SLOT(
zoomOut()));
137 d->zoomSelAction =
new QAction(KIcon(
"zoom-fit-best"), i18n(
"Zoom to Selection"),
this);
138 connect(d->zoomSelAction, SIGNAL(triggered()),
this, SLOT(
zoomSel()));
140 d->zoom2FitAction =
new QAction(KIcon(
"document-preview"), i18n(
"Zoom to Fit"),
this);
141 connect(d->zoom2FitAction, SIGNAL(triggered()),
this, SLOT(
zoom2Fit()));
143 d->clrSelAction =
new QAction(KIcon(
"edit-clear"), i18n(
"Clear Selections"),
this);
173 if (img == 0)
return;
181 d->scene->setSceneRect(0, 0, img->
width(), img->
height());
182 d->selection->setMaxRight(img->
width());
183 d->selection->setMaxBottom(img->
height());
199 d->selection->saveZoom(
transform().m11());
200 for (
int i=0; i<d->selectionList.size(); ++i) {
201 d->selectionList[i]->saveZoom(
transform().m11());
208 scale(1.0 / 1.5, 1.0 / 1.5);
209 d->selection->saveZoom(
transform().m11());
210 for (
int i=0; i<d->selectionList.size(); ++i) {
211 d->selectionList[i]->saveZoom(
transform().m11());
218 if (d->selection->isVisible()) {
219 fitInView(d->selection->boundingRect() , Qt::KeepAspectRatio);
220 d->selection->saveZoom(
transform().m11());
221 for (
int i=0; i<d->selectionList.size(); ++i) {
222 d->selectionList[i]->saveZoom(
transform().m11());
233 fitInView(d->img->rect(), Qt::KeepAspectRatio);
234 d->selection->saveZoom(
transform().m11());
235 for (
int i=0; i<d->selectionList.size(); ++i) {
236 d->selectionList[i]->saveZoom(
transform().m11());
243 if (!d->selection->isVisible())
return;
245 rect.
setLeft(ratio * d->img->width());
246 d->selection->setRect(rect);
247 updateSelVisibility();
253 if (!d->selection->isVisible())
return;
255 rect.
setTop(ratio * d->img->height());
256 d->selection->setRect(rect);
257 updateSelVisibility();
263 if (!d->selection->isVisible())
return;
265 rect.
setRight(ratio * d->img->width());
266 d->selection->setRect(rect);
267 updateSelVisibility();
273 if (!d->selection->isVisible())
return;
275 rect.
setBottom(ratio * d->img->height());
276 d->selection->setRect(rect);
277 updateSelVisibility();
285 tl_y * d->img->height(),
286 br_x * d->img->width(),
287 br_y * d->img->height());
289 d->selection->setRect(rect);
290 updateSelVisibility();
299 rect.
setCoords(0,0, tl_x * d->img->width(), d->img->height());
300 d->hideLeft->setRect(rect);
307 d->hideRight->setRect(rect);
312 br_x * d->img->width(),
313 tl_y * d->img->height());
314 d->hideTop->setRect(rect);
318 br_y * d->img->height(),
319 br_x * d->img->width(),
321 d->hideBottom->setRect(rect);
324 rect.
setCoords(tl_x * d->img->width(), tl_y* d->img->height(),
325 br_x * d->img->width(), br_y* d->img->height());
327 d->hideArea->setRect(rect);
330 d->hideRight->show();
332 d->hideBottom->show();
340 if (percentage >= 100) {
345 d->hideArea->setBrush(hideColor);
347 qreal diff = d->hideBottom->rect().top() - d->hideTop->rect().bottom();
348 diff -= (diff * percentage) / 100;
351 rect.
setTop(d->hideBottom->rect().top() - diff);
353 d->hideArea->setRect(rect);
359 void KSaneViewer::updateHighlight()
361 if (d->selection->isVisible()) {
364 rect.
setCoords(0,0, d->selection->rect().left(), d->img->height());
365 d->hideLeft->setRect(rect);
368 rect.
setCoords(d->selection->rect().right(),
372 d->hideRight->setRect(rect);
375 rect.
setCoords(d->selection->rect().left(),
377 d->selection->rect().right(),
378 d->selection->rect().top());
379 d->hideTop->setRect(rect);
382 rect.
setCoords(d->selection->rect().left(),
383 d->selection->rect().bottom(),
384 d->selection->rect().right(),
386 d->hideBottom->setRect(rect);
389 d->hideRight->show();
391 d->hideBottom->show();
396 d->hideRight->hide();
398 d->hideBottom->hide();
408 d->hideRight->hide();
410 d->hideBottom->hide();
415 void KSaneViewer::updateSelVisibility()
417 if ((d->selection->rect().width() >0.001) &&
418 (d->selection->rect().height() > 0.001) &&
419 ((d->img->width() - d->selection->rect().width() > 0.1) ||
420 (d->img->height() - d->selection->rect().height() > 0.1)))
422 d->selection->setVisible(
true);
425 d->selection->setVisible(
false);
432 if (d->selection->isVisible()) {
433 return (d->selectionList.size() + 1);
436 return d->selectionList.size();
443 if ((index < 0) || (index > d->selectionList.size())) {
444 activeSelection(tl_x, tl_y, br_x, br_y);
447 if (index == d->selectionList.size()) {
448 return activeSelection(tl_x, tl_y, br_x, br_y);
451 tl_x = d->selectionList[index]->rect().left() / d->img->width();
452 tl_y = d->selectionList[index]->rect().top() / d->img->height();
453 br_x = d->selectionList[index]->rect().right() / d->img->width();
454 br_y = d->selectionList[index]->rect().bottom() / d->img->height();
459 bool KSaneViewer::activeSelection(
float &tl_x,
float &tl_y,
float &br_x,
float &br_y)
461 if (!d->selection->isVisible()) {
469 tl_x = d->selection->rect().left() / d->img->width();
470 tl_y = d->selection->rect().top() / d->img->height();
471 br_x = d->selection->rect().right() / d->img->width();
472 br_y = d->selection->rect().bottom() / d->img->height();
474 if ((tl_x == br_x) || (tl_y == br_y)) {
487 d->selection->setRect(
QRectF(0,0,0,0));
488 d->selection->intersects(
QPointF(100,100));
489 d->selection->setVisible(
false);
497 while (!d->selectionList.isEmpty()) {
498 tmp = d->selectionList.takeFirst();
499 d->scene->removeItem(tmp);
514 if(e->
modifiers() == Qt::ControlModifier) {
528 if (e->
button() == Qt::LeftButton)
530 d->m_left_last_x = e->
x();
531 d->m_left_last_y = e->
y();
533 d->lastSPoint = scenePoint;
534 if (e->
modifiers() != Qt::ControlModifier) {
535 if (!d->selection->isVisible()) {
536 d->selection->setVisible(
true);
538 d->selection->intersects(scenePoint);
554 bool removed =
false;
555 if (e->
button() == Qt::LeftButton) {
556 if ((d->selection->rect().width() < 0.001) ||
557 (d->selection->rect().height() < 0.001))
564 for (
int i=0; i<d->selectionList.size(); i++) {
566 d->scene->removeItem(d->selectionList[i]);
568 d->selectionList.removeAt(i);
569 d->selection->setVisible(
true);
570 d->selection->setRect(tmp->
rect());
571 d->selection->intersects(scenePoint);
580 d->selectionList.push_back(tmp);
581 d->selectionList.back()->setSaved(
true);
582 d->selectionList.back()->saveZoom(
transform().m11());
583 d->scene->addItem(d->selectionList.back());
584 d->selectionList.back()->setZValue(9);
585 d->selectionList.back()->intersects(scenePoint);
593 if ((e->
modifiers() != Qt::ControlModifier) &&
594 (d->selection->isVisible()) &&
595 (d->img->width() > 0.001) &&
596 (d->img->height() > 0.001))
598 float tlx = d->selection->rect().left() / d->img->width();
599 float tly = d->selection->rect().top() / d->img->height();
600 float brx = d->selection->rect().right() / d->img->width();
601 float bry = d->selection->rect().bottom() / d->img->height();
614 if (e->
buttons()&Qt::LeftButton)
616 if (e->
modifiers() == Qt::ControlModifier)
618 int dx = e->
x() - d->m_left_last_x;
619 int dy = e->
y() - d->m_left_last_y;
622 d->m_left_last_x = e->
x();
623 d->m_left_last_y = e->
y();
627 QRectF rect = d->selection->rect();
710 rect.
translate(d->selection->fixTranslation(scenePoint-d->lastSPoint));
716 d->selection->setRect(rect);
719 else if (d->selection->isVisible()) {
720 d->change = d->selection->intersects(scenePoint);
764 for (
int i=0; i<d->selectionList.size(); i++) {
770 d->lastSPoint = scenePoint;
800 float multiplier = sqrt(area/(d->img->height() * d->img->width()));
802 int width = (int)(d->img->width() * multiplier);
803 int height = (int)(d->img->height() * multiplier);
805 QImage img = d->img->scaled(width, height, Qt::KeepAspectRatio);
821 for (
int h=1; h<
height; h++) {
825 pix = qGray(img.
pixel(0, h));
826 diff = qAbs(pix - qGray(img.
pixel(1, h)));
827 diff += qAbs(pix - qGray(img.
pixel(0, h-1)));
828 diff += qAbs(pix - qGray(img.
pixel(0, h+1)));
835 pix = qGray(img.
pixel(width - 1, h));
836 diff = qAbs(pix - qGray(img.
pixel(width - 2, h)));
837 diff += qAbs(pix - qGray(img.
pixel(width - 1, h-1)));
838 diff += qAbs(pix - qGray(img.
pixel(width - 1, h+1)));
840 colSums[width - 1] += diff;
844 for (
int w=1; w < (width - 1); w++) {
845 pix = qGray(img.
pixel(w, h));
848 diff += qAbs(pix - qGray(img.
pixel(w - 1, h)));
849 diff += qAbs(pix - qGray(img.
pixel(w + 1, h)));
850 diff += qAbs(pix - qGray(img.
pixel(w, h - 1)));
851 diff += qAbs(pix - qGray(img.
pixel(w, h + 1)));
866 if (hSelStart >= 0) {
867 if (hSelMargin > 0) hSelMargin--;
869 if ((hSelStart > -1) && ((hSelMargin == 0) || (h==height-1))) {
871 hSelEnd = h - hSelMargin;
878 for (
int w=0; w <=
width; w++) {
886 if (wSelStart >= 0) {
887 if (wSelMargin > 0) wSelMargin--;
889 if ((wSelStart >= 0) && ((wSelMargin == 0) || (w == width))) {
898 if ((wSelEnd-wSelStart) < width) {
901 int x1 = wSelStart / multiplier;
902 int y1 = hSelStart / multiplier;
903 int x2 = wSelEnd / multiplier;
904 int y2 = hSelEnd / multiplier;
905 float selArea = (float)(wSelEnd - wSelStart) * (float)(hSelEnd-hSelStart);
908 d->selectionList.push_back(tmp);
909 d->selectionList.back()->setSaved(
true);
910 d->selectionList.back()->saveZoom(
transform().m11());
911 d->scene->addItem(d->selectionList.back());
912 d->selectionList.back()->setZValue(9);
938 refineSelections(qRound(1/multiplier));
940 float minArea = d->img->height() * d->img->width() *
MIN_AREA_SIZE;
943 while (i < d->selectionList.size()) {
944 if ((d->selectionList[i]->rect().width() * d->selectionList[i]->rect().height()) < minArea) {
945 d->scene->removeItem(d->selectionList[i]);
946 d->selectionList.removeAt(i);
957 return QSize(250, 300);
960 void KSaneViewer::refineSelections(
int pixelMargin)
968 for (
int i=0; i<d->selectionList.size(); i++) {
969 QRectF selRect = d->selectionList.at(i)->rect();
972 hSelStart = (int)selRect.
top();
973 hSelEnd = (int)selRect.
bottom();
974 wSelStart = (int)selRect.
left();
975 wSelEnd = (int)selRect.
right();
979 hSelStart = refineRow(hSelStart - pixelMargin, hSelEnd, wSelStart, wSelEnd);
982 hSelEnd = refineRow(hSelEnd + pixelMargin, hSelStart, wSelStart, wSelEnd);
985 wSelStart = refineColumn(wSelStart - pixelMargin, wSelEnd, hSelStart, hSelEnd);
988 wSelEnd = refineColumn(wSelEnd + pixelMargin, wSelStart, hSelStart, hSelEnd);
991 d->selectionList.at(i)->setRect(
QRectF(
QPointF(wSelStart, hSelStart),
QPointF(wSelEnd, hSelEnd)));
995 int KSaneViewer::refineRow(
int fromRow,
int toRow,
int colStart,
int colEnd)
1001 int addSub = (fromRow < toRow) ? 1 : -1;
1006 if (colStart < 1) colStart = 1;
1007 if (colEnd >= d->img->width()-1) colEnd = d->img->width() - 2;
1009 if (fromRow < 1) fromRow = 1;
1010 if (fromRow >= d->img->height()-1) fromRow = d->img->height() - 2;
1012 if (toRow < 1) toRow = 1;
1013 if (toRow >= d->img->height()-1) toRow = d->img->height() - 2;
1016 while (row != toRow) {
1018 for (
int w=colStart; w<colEnd; w++) {
1020 pix = qGray(d->img->pixel(w, row));
1022 diff += qAbs(pix - qGray(d->img->pixel(w-1, row)));
1023 diff += qAbs(pix - qGray(d->img->pixel(w+1, row)));
1024 diff += qAbs(pix - qGray(d->img->pixel(w, row-1)));
1025 diff += qAbs(pix - qGray(d->img->pixel(w, row+1)));
1038 if (row == 1) row = 0;
1039 if (row == (d->img->width() -2)) row = d->img->width();
1047 int KSaneViewer::refineColumn(
int fromCol,
int toCol,
int rowStart,
int rowEnd)
1054 int addSub = (fromCol < toCol) ? 1 : -1;
1059 if (rowStart < 1) rowStart = 1;
1060 if (rowEnd >= d->img->height()-1) rowEnd = d->img->height() - 2;
1062 if (fromCol < 1) fromCol = 1;
1063 if (fromCol >= d->img->width()-1) fromCol = d->img->width() - 2;
1065 if (toCol < 1) toCol = 1;
1066 if (toCol >= d->img->width()-1) toCol = d->img->width() - 2;
1069 while (col != toCol) {
1072 for (
int row=rowStart; row<rowEnd; row++) {
1075 pix = qGray(d->img->pixel(col, row));
1077 diff += qAbs(pix - qGray(d->img->pixel(col-1, row)));
1078 diff += qAbs(pix - qGray(d->img->pixel(col+1, row)));
1079 diff += qAbs(pix - qGray(d->img->pixel(col, row-1)));
1080 diff += qAbs(pix - qGray(d->img->pixel(col, row+1)));
1093 if (col == 1) col = 0;
1094 if (col == (d->img->width() -2)) col = d->img->width();
virtual void mouseMoveEvent(QMouseEvent *event)
static const int DIFF_TRIGGER
void mousePressEvent(QMouseEvent *e)
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setMatrix(const QMatrix &matrix, bool combine)
void setQImage(QImage *img)
static const int SUM_TRIGGER
QVector< T > & fill(const T &value, int size)
QPointF mapToScene(const QPoint &point) const
void setHighlightArea(float tl_x, float tl_y, float br_x, float br_y)
This function is used to darken everything except what is inside the given area.
virtual void mouseReleaseEvent(QMouseEvent *event)
QGraphicsScene * scene() const
void setSelection(float tl_x, float tl_y, float br_x, float br_y)
This function is used to set a selection without the user setting it.
void scale(qreal sx, qreal sy)
void mouseReleaseEvent(QMouseEvent *e)
QRgb pixel(int x, int y) const
void translate(qreal dx, qreal dy)
void drawBackground(QPainter *painter, const QRectF &rect)
void setHighlightShown(int percentage, QColor hideColor=Qt::white)
This function sets the percentage of the highlighted area that is visible.
void findSelections(float area=10000.0)
Find selections in the picture.
static const int AVERAGE_MULT
static const int AVERAGE_COUNT
void setScene(QGraphicsScene *scene)
void setCacheMode(QFlags< QGraphicsView::CacheModeFlag > mode)
KSaneViewer(QImage *img, QWidget *parent=0)
virtual QSize sizeHint() const
static const int AVERAGE_TRIGGER
virtual void mousePressEvent(QMouseEvent *event)
void mouseMoveEvent(QMouseEvent *e)
void clearSavedSelections()
void ensureVisible(const QRectF &rect, int xmargin, int ymargin)
static const int MAX_NUM_SELECTIONS
static const float MIN_AREA_SIZE
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
static const int SEL_MARGIN
void setCoords(qreal x1, qreal y1, qreal x2, qreal y2)
bool selectionAt(int index, float &tl_x, float &tl_y, float &br_x, float &br_y)
void clearActiveSelection()
void newSelection(float tl_x, float tl_y, float br_x, float br_y)
const QPoint & pos() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void clearHighlight()
This function removes the highlight area.
virtual void wheelEvent(QWheelEvent *event)
void wheelEvent(QWheelEvent *e)
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)