📄 imageview.cc
字号:
void ImageView::updateFullScreen() { applyZoom();}/** Update data_rect*/void ImageView::setDataRect() { //Get image dimensions int dx=image->x(); int dy=image->y(); //Get image screen dimensions (may differ if zoom is set) int screen_dx=dx*zoom/100; int screen_dy=dy*zoom/100; int x=d->width(); int y=d->height(); int wx=x; int wy=dy*wx/dx; if (wy>y) { wy=y; wx=dx*wy/dy; } if (isSet("scale")) { if (!isSet("center")) { data_rect=QRect(0,0,wx,wy); } else { data_rect=QRect(max((x-wx)/2,0),max((y-wy)/2,0),wx,wy); } } else { if (!isSet("center")) { data_rect=QRect(0,0,screen_dx,screen_dy); } else { data_rect=QRect(max((x-screen_dx)/2,0),max((y-screen_dy)/2,0),screen_dx,screen_dy); } }}/** Repaint the image using given painter and size of output window @param x width of output window @param y height of output window @param p QPainter to use @param src Which part of image to repaint (when not in fullscreen)*/void ImageView::repaint(int x,int y,QPainter &p,const QRect &src) { if (isSet("antialias")) { //Set antialiasing p.setRenderHint(QPainter::SmoothPixmapTransform,true); } p.setPen(Qt::blue); QBrush black(QColor(0,0,0)); if (!image) { //No image is loaded p.drawRect(0,0,x-1,y-1); p.fillRect(1,1,x-2,y-2,black); p.drawText(0,0,x,y,Qt::AlignVCenter | Qt::AlignCenter,tr("No image loaded")); return; } if (image->x()<=0 || image->y()<=0) { //Invalid image is loaded p.drawRect(0,0,x-1,y-1); p.fillRect(1,1,x-2,y-2,black); p.drawText(0,0,x,y,Qt::AlignVCenter | Qt::AlignCenter,tr("Invalid image")); return; } //Rectangle specifying entire window QRect wnd=QRect(0,0,x,y); //Determine target rectangle at screen //Update data rectangle for mouse navigation setDataRect(); //Repaint stripes around image if needed if (data_rect.left()>src.left()) { //repaint stripe on left QRect tmp(0,0,data_rect.left(),y); p.fillRect(tmp & src,black); } if (data_rect.right()<src.right()) { //repaint on right QRect tmp(data_rect.right(),0,x-data_rect.right(),y); p.fillRect(tmp & src,black); } if (data_rect.top()>src.top()) { //repaint on top QRect tmp(data_rect.left(),0,data_rect.width(),data_rect.top()); p.fillRect(tmp & src,black); } if (data_rect.bottom()<src.bottom()) { //repaint on bottom QRect tmp(data_rect.left(),data_rect.bottom(),data_rect.width(),y-data_rect.bottom()); p.fillRect(tmp & src,black); } if (isSet("scale")) { //Show scaled to window //Set target to data rectangle QRect target=data_rect; //Draw entire image scaled QRect source(0,0,image->x(),image->y()); image->draw(&p,source,target); } else { //No scaling - show 1:1 or show with arbitrary zoom //Cut out anything outside the actual image QRect target=src & data_rect; if (!target.isEmpty()) { //Is there anything left to draw? if (zoom==100) { //No resizing - copy the image int ix=target.left()-data_rect.left(); int iy=target.top()-data_rect.top(); int isx=target.width(); int isy=target.height(); QRect source(ix,iy,isx,isy); //Paint it image->draw(&p,source,target); } else {//#if QT_VERSION < 0x040200 //Partial workaround for rounding errors (QT 4.1.x or earlier) target.setWidth(target.width()+1); target.setHeight(target.height()+1); target=target & data_rect;//#endif //Draw part of image double fx=(double)(target.left()-data_rect.left())*100.0/(double)zoom; double fy=(double)(target.top()-data_rect.top())*100.0/(double)zoom; double fsx=(double)target.width()*100.0/(double)zoom; double fsy=(double)target.height()*100.0/(double)zoom;// cout << fx << "," << fy << " " << fsx << "x" << fsy << endl;/*#if QT_VERSION >= 0x040200 QRect sourcebound((int)floor(fx),(int)floor(fy),(int)ceil(fsx),(int)ceil(fsy)); //This code is correct in Qt4.2. Qt4.1 can't work with subpixel precision on input QRectF source(fx,fy,fsx,fsy); //Paint it image->draw(&p,sourcebound,target,source);#else*/ //Workaround for QT 4.1.x //This code is "most correct" QRect sourcebound((int)floor(fx),(int)floor(fy),(int)ceil(fsx+frac(fx)),(int)ceil(fsy+frac(fy))); //Recalculate target from sourcebound (to avoid painting non-integer number of pixels from source) target.setLeft(sourcebound.left()*zoom/100+data_rect.left()); target.setTop(sourcebound.top()*zoom/100+data_rect.top()); target.setWidth(sourcebound.width()*zoom/100); target.setHeight(sourcebound.height()*zoom/100); target=target & data_rect; //Paint it image->draw(&p,sourcebound,target); //Perfectly accurate, but insanely slow solution //QRect source(0,0,dx,dy); //p.setClipRect(target); //image->draw(&p,source,data_rect);//#endif } } }}/** Cancel any picks (coordinates, pixel intensity) that may be in progress Should be called before setting any picking mode and setting up own signal for it */void ImageView::cancelPicks() { if (mode==view) return; //nothing to cancel emit cancelledPick(); setMode(view);}/** Scroll the area by x pixels down and y pixels to the right @param x How many pixels to sroll to down @param y How many pixels to sroll to right*/void ImageView::scrollBy(int x,int y) { QScrollBar *h=horizontalScrollBar(); QScrollBar *v=verticalScrollBar(); h->setValue(h->value()+x); v->setValue(v->value()+y);}/** Handler called when key is pressed @param e event data*/void ImageView::keyPressEvent(QKeyEvent *e) { if (image) { int key=e->key(); switch (key) { case Qt::Key_Escape: cancelPicks(); break; case Qt::Key_Up: scrollBy(0,-16); break; case Qt::Key_Down: scrollBy(0,16); break; case Qt::Key_Left: scrollBy(-16,0); break; case Qt::Key_Right: scrollBy(16,0); break; case Qt::Key_Home: scrollBy(-QWIDGETSIZE_MAX,0); break; case Qt::Key_End: scrollBy(QWIDGETSIZE_MAX,0); break; case Qt::Key_PageUp: scrollBy(0,-height()); break; case Qt::Key_PageDown: scrollBy(0,height()); break; case '+': case '=': zoomStep(true); break; case '-': zoomStep(false); break; default: return; } return; } e->ignore();}/** Changes zoom to given percentage @param nzoom New zoom, in percent*/void ImageView::setZoom(int nzoom) { zoom=nzoom; applyZoom();}/** Fix zoom value to be within allowed limits and apply new zoom value*/void ImageView::applyZoom() { if (zoom<MIN_ZOOM) zoom=MIN_ZOOM; if (zoom>MAX_ZOOM) zoom=MAX_ZOOM; update();//Will update data_rect if (selection.isValid()) { setDataRect(); d->moveRubberBand(selectionFromImageCoords(selection)); } emit zoomChanged(zoom);}/** Changes zoom in given direction @param steps Number of steps to zoom in (positive) or out (negative)*/void ImageView::zoomSteps(int steps) { if (!steps) return; //Zero? while (steps<0) { // Zoom -N zoomStepInternal(false); steps++; if (zoom<MIN_ZOOM) break;//Too much zoom } while (steps>0) { // Zoom +N zoomStepInternal(true); steps--; if (zoom>MAX_ZOOM) break;//Too much zoom } applyZoom();}/** Changes zoom in given direction @param zoomIn True if zoom in, else zoom out*/void ImageView::zoomStep(bool zoomIn) { zoomStepInternal(zoomIn); applyZoom();}/** Changes zoom in given direction without applying it @param zoomIn True if zoom in, else zoom out*/void ImageView::zoomStepInternal(bool zoomIn) { int step=10; if (!zoomIn) { if (zoom<=50) step=5; if (zoom<=20) step=2; if (zoom<=10) step=1; if (zoom>200) step=25; if (zoom>500) step=100; if (zoom>1000) step=200; if (zoom>2000) step=500; zoom-=step; } else { if (zoom<50) step=5; if (zoom<20) step=2; if (zoom<10) step=1; if (zoom>=200) step=25; if (zoom>=500) step=100; if (zoom>=1000) step=200; if (zoom>=2000) step=500; zoom+=step; }}/** Handler called when key is released @param e event data*/void ImageView::keyReleaseEvent(QKeyEvent *e) { e->ignore();}/** Handler called when mouse is moved over the widget @param e event data*/void ImageView::mouseMoveEvent(QMouseEvent *e) { if (!image) { e->ignore(); return; } int mx=e->x(); int my=e->y(); if (e->buttons() & Qt::RightButton) { //right mouse button pressed scrollBy(mouse_ex-mx,mouse_ey-my); mouse_ex=mx; mouse_ey=my; }}/** Return string representation of channel count @param c number of channels*/QString ImageView::channelsToString(int c) { if (c==1) return "L"; //luminosity (greyscale) if (c==2) return "LA"; //luminosity (greyscale)+alpha if (c==3) return "RGB"; //RGB if (c==4) return "RGBA"; //RGB+Alpha return QString("(%1C)").arg(c);}/** Handler called when mouse is moved over the widget @param e event data*/void ImageView::mouseCoordEvent(QMouseEvent *e) { if (!image) { e->ignore(); return; } int mx=e->x(); int my=e->y(); QString value=""; if (!(mx<data_rect.x() || my<data_rect.y() || mx>data_rect.right() || my>data_rect.bottom())) { // Mouse move within the image mx-=data_rect.x(); my-=data_rect.y(); mouse_x=mx*image->x()/data_rect.width(); mouse_y=my*image->y()/data_rect.height(); int c=image->channels(); value=channelsToString(c); value+="="; for (int i=0;i<c;i++) { //Image values value+=QString::number(image->value(mouse_x,mouse_y,i)); if (i<c-1) value+=","; } value+=" (#"; for (int i=0;i<c;i++) { //Image values in hex value+=image->valueHex(mouse_x,mouse_y,i); } value+=")"; //Mouse coords value=QString("[")+QString::number(mouse_x)+","+QString::number(mouse_y)+"] "+value; } if (!selectionText.isNull()) { emit selectionInfo(selectionText); } else { emit selectionInfo(""); } emit info(value);}/** Mouse press handler @param e event data */void ImageView::mousePressEvent(QMouseEvent *e) { if (!image) { e->ignore(); return; } if (e->button()==Qt::LeftButton) { if (mode==crosshair) { setMode(view); return; } } if (e->button()==Qt::RightButton) {#if QT_VERSION >= 0x040200 //Only Qt 4.2 or newer d->setCursor(Qt::ClosedHandCursor);#else d->setCursor(Qt::SizeAllCursor);#endif mouse_ex=e->x(); mouse_ey=e->y(); } else { e->ignore(); }}/** Handler called when one of the mouse buttons is released @param e event data*/void ImageView::mouseReleaseEvent(QMouseEvent *e) { // "reset" current mode setMode(mode); e->ignore();}/** Handler called when wheel on the mouse is scrolled @param e event data*/void ImageView::wheelEvent (QWheelEvent *e) { if (!image) return; int z=e->delta()/4; scrollBy(0,-z); update();}/** default destructor */ImageView::~ImageView() { if (image) delete image;}} // namespace gui
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -