Feed
Requirement: Load a picture and display it, zoom in and out, you can capture a rectangle of the picture and save it.
Originally thought quite simple a function, actually still is a little small complex.
The simplest QT Image browser can refer to the QT demo:image Viewer Example
Take a look at the final implementation:
Load display of pictures
It is necessary to implement a Qimageviewer class that inherits from Qwidget.
Pictures with Qpixmap to load and display, there are three members are the image of the zoom factor, whether the picture has been loaded, whether the viewer has been initialized, is in the clipping state.
Private:qpixmap m_pixmap;float scalling;bool isloaded;bool isintialised;bool iscropping;
The scalling value is the scale used to record the picture.
As long as the image is redefined paintevent, the M_pixmap will be drawn on it.
void Qimageviewer::p aintevent (qpaintevent *event) {qwidget::p aintevent (event), if (M_pixmap.isnull ()) {return;} qpainter painter (this); if (isLoaded) {painter.setrenderhint (qpainter::smoothpixmaptransform); Qsize pixsize = M_pixmap.size ();//for canvas ' s size not change when window ' s size change.if (!isinitialised) {qsize Initial Size = Event->rect (). Size (), scaling = 1.0 * initialsize.width ()/Pixsize.width (); isinitialised = true;} Pixsize.scale (Scaling * pixsize, qt::keepaspectratio); This->setminimumsize (pixsize); Qpoint Topleft;topleft.setx ((This->width ()-pixsize.width ())/2); Topleft.sety ((This->height ()- Pixsize.height ())/2);p Ainter.drawpixmap (TopLeft, m_pixmap.scaled (Pixsize, Qt::keepaspectratio, Qt:: smoothtransformation));}}
The idea is simple, first choose to enter the cropping mode (you can add an action in the menu or a shortcut key), and then drag a rectangle on the picture, and finally press ENTER, the interception is complete, Ctrl + s save.
The main use is the Qpixmap::copy (Qrect rect) method.
The first step is to implement a Croprect class that records the truncated rectangle.
#ifndef croprect_h#define croprect_h#include <QPoint> #include <qpainter>class croprect{public:croprect ( {}~croprect () {}void Setstart (Qpoint s) {start = s;} void SetEnd (Qpoint e) {end = e;} Qpoint startPoint () const{return start;} Qpoint endPoint () const{return end;} void Reset () {Qpoint P (0,0); start = P;end = P;} qsize& size () Const{return qsize (width (), height ());} int height () const{return qabs (StartPoint (). Y ()-EndPoint (). Y ());} int width () const{return qabs (StartPoint (). x ()-EndPoint (). x ());} Private:qpoint start; Qpoint end;}; #endif//Croprect_h
Note that both start and end are relative to the current position of the image being captured, i.e. the coordinates of the upper-left corner of the picture are the origin of the croprect.
Then two auxiliary methods are implemented in Qimageviewer.
Because the picture is not exactly filled with the form, so in the setting of the Crop box, the mouse if there is no point in the picture, it should not be cropped, so you should first determine whether a point on the screen is on the picture.
BOOL Qimageviewer::iscontainpoint (Qpoint &p) {qsize s = m_pixmap.size (); S.scale (Scaling * s, qt::keepaspectratio); /if pixmap bigger than current Window.if ((S.height () > This->rect (). Height ()) && (S.width () > This->r ECT (). Width ())) {return true;} Qpoint Topleft;topleft.setx ((This->width ()-s.width ())/2); Topleft.sety ((This->height ()-s.height ())/2); Qrect rect (topleft, s); return Rect.contains (P);}
The second way is to map the position of the mouse to the position on the picture, because it is primarily about manipulating the picture.
There are four cases of picture size and window size, the first is that the height and width of the picture are greater than the form.
The logic is to add the red and green parts, to get the position of the point for the current picture (scaled), and then divide it by scalling.
There is also a picture in the window completely inside
In this case, the red minus the green part, the point for the current picture (scaled) position, and finally divided by scalling. There are two simple cases that do not unfold, the specific code is as follows:
Qpoint Qimageviewer::maptopixmap (Qpoint &screenpoint) {qsize pixmapsize = m_pixmap.size ();p Ixmapsize.scale ( Scaling * pixmapsize, qt::keepaspectratio);//get the position of Screenpoint to the pixmap in show. Qpoint tmppos;if (Pixmapsize.width () > This->width () && pixmapsize.height () > This->height ()) { Tmppos.setx (Pixmapsize.width ()-(This->width ()-screenpoint.x ()); Tmppos.sety (Pixmapsize.height ()-(this-> Height ()-screenpoint.y ()));} else if (Pixmapsize.width () < This->width () && pixmapsize.height () > This->height ()) {Tmppos.setx ( Screenpoint.x ()-(This->width ()-pixmapsize.width ())/2); Tmppos.sety (Pixmapsize.height ()-(This->height ()- Screenpoint.y ()));} else if (Pixmapsize.width () > This->width () && pixmapsize.height () < This->height ()) {Tmppos.setx ( Pixmapsize.width ()-(This->width ()-screenpoint.x ()); Tmppos.sety (Screenpoint.y ()-(This->height ()- Pixmapsize.height ())/2);} Else{qpoint Topleft;topLeft.setx ((This->width ()-pixmapsize.width ())/2); Topleft.sety ((This->height ()-pixmapsize.height ())/2); Tmppos.setx (Screenpoint.x ()-topleft.x ()); Tmppos.sety (Screenpoint.y ()-topleft.y ());} Return the position to the real Pixmap.*/return Qpoint (tmppos.x ()/Scaling, tmppos.y ()/scaling);}
Here took an opportunistic approach, that is, using the Qpoint.setx () and Qpoint.sety () method if the transmission is negative, then it is equal to pass in 0, so less than 0 of the judgment.
Next is the corresponding mouse event to determine the size of the cropping box
void Qimageviewer::mousepressevent (Qmouseevent *event) {if (event->buttons () = = Qt::leftbutton) && Iscontainpoint (Event->pos ()) && iscropping) {Croprect.setstart (Maptopixmap ())); Croprect.setend (Maptopixmap (Event->pos ())); isstartingcrop = True;}} void Qimageviewer::mousemoveevent (Qmouseevent *event) {if (event->buttons () = = Qt::leftbutton) && Isstartingcrop) {if (Iscontainpoint (Event->pos ())) {Croprect.setend (Maptopixmap ()); Update ();}}} void Qimageviewer::mousereleaseevent (Qmouseevent *e) {qrect rect (Croprect.startpoint (), Croprect.endpoint ()); Isstartingcrop = false;}
Crop box Drawing related code, here also according to the relative position of startpoint and endpoint, there are several situations need to pay attention to. The more cool dynamic ant line can be referenced by:draw ant line in Qt
if (iscropping) {qdebug () << croprect.width () << croprect.height ();//painter.setpen (Qt::d arkgreen); Qpen Pen;pen.setbrush (qt::red);p En.setstyle (Qt::D ashline);p en.setwidth (1);p Ainter.setpen (pen);//start Point in the Left to the end Point.if (Croprect.startpoint (). x () < Croprect.endpoint (). x ()) {if (Croprect.startpoint (). Y () < Croprect.endpoint (). Y ()) {//start point in the top to the end Point.painter.drawRect (topleft.x () + Croprect.startpoint (). X () * Scaling, TOPLEFT.Y () + Croprect.startpoint (). Y () * scaling, croprect.width () * Scaling, croprect.height () * scaling) ;} Else{//start the bottom to the end Point.painter.drawRect (topleft.x () + Croprect.startpoint (). x () * Scaling, TOPL Eft.y () + Croprect.endpoint (). Y () * scaling, croprect.width () * Scaling, croprect.height () * scaling);}} Else{if (Croprect.startpoint (). Y () > Croprect.endpoint (). Y ()) {Painter.drawrect (Topleft.x () + croprect.endpoint () . x () * Scaling, TOPLEFT.Y () + Croprect.endpoint (). Y () * Scaling, Croprect. Width () * scaling, croprect.height () * scaling);} Else{painter.drawrect (Topleft.x () + Croprect.endpoint (). x () * Scaling, TOPLEFT.Y () + Croprect.startpoint (). Y () * Scaling, croprect.width () * Scaling, croprect.height () * scaling);}}}
And finally, it's cropped .
void Qimageviewer::cropfinished () {Qrect crop (croprect.startpoint (), Qsize (Croprect.width (), Croprect.height ())); Qpixmap cropped = m_pixmap.copy (crop); m_pixmap = Cropped;croprect.reset (); iscropping = False;this->update ();}
Finish the call.
The realization of the function in QT