Main Page | Class List | File List | Class Members | File Members | Related Pages

grabber.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Bojan D.                                        *
00003  *   bojan_d@users.sourceforge.net                                         *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00027 #include <ksavefile.h>
00028 #include <kimageio.h>
00029 #include <klocale.h>
00030 #include <kurl.h>
00031 #include <kapplication.h>
00032 
00033 #include <qbitmap.h>
00034 #include <qimage.h>
00035 #include <qregexp.h>
00036 #include <qpainter.h>
00037 #include <qpaintdevicemetrics.h>
00038 #include <qfile.h>
00039 #include <qregion.h>
00040 
00041 #include <stdlib.h>
00042 
00043 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
00044 #include <X11/extensions/shape.h>
00045 #endif
00046 
00047 #include "grabber.h"
00048 
00049 Grabber::Grabber(QObject *parent, const char *name)
00050  : QObject(parent, name),
00051  m_snapshot()
00052 {
00053 }
00054 
00055 Grabber::~Grabber()
00056 {
00057 }
00058 
00059 QPixmap Grabber::capture()
00060 {
00061         emit startCapture();
00062         emit message(i18n("Taking snapshot..."));
00063         // make sure the UI is updated.
00064         kapp->processEvents();
00065         
00066         XGrabServer( qt_xdisplay());
00067         if ( Config().Capture.CaptureMode == Configuration::WindowUnderCursor ) 
00068         {
00069                 Window root;
00070                 Window child;
00071                 uint mask;
00072                 int rootX, rootY, winX, winY;
00073                 XQueryPointer(  qt_xdisplay(), qt_xrootwin(), &root, &child,
00074                                         &rootX, &rootY, &winX, &winY,
00075                                         &mask);
00076         if( child == None )
00077             child = qt_xrootwin();
00078                 if( !Config().Capture.IncludeWD) 
00079                 {
00080                         Window real_child = findRealWindow( child );
00081                         if( real_child != None ) // test just in case
00082                                 child = real_child;
00083                 }
00084                 
00085                 int x, y;
00086                 unsigned int w, h;
00087                 unsigned int border;
00088                 unsigned int depth;
00089                 XGetGeometry( qt_xdisplay(), child, &root, &x, &y, &w, &h, &border, &depth );
00090         w += 2 * border;
00091         h += 2 * border;
00092 
00093                 Window parent;
00094                 Window* children;
00095                 unsigned int nchildren;
00096                 if( XQueryTree( qt_xdisplay(), child, &root, &parent, &children, &nchildren ) != 0 ) 
00097                 {
00098                 if( children != NULL )
00099                                 XFree( children );
00100             
00101                         int newx, newy;
00102                 Window dummy;
00103                 if( XTranslateCoordinates( qt_xdisplay(), parent, qt_xrootwin(),
00104                         x, y, &newx, &newy, &dummy )) 
00105                         {
00106                                 x = newx;
00107                                 y = newy;
00108                         }
00109                 }
00110 
00111                 m_snapshot = QPixmap::grabWindow( qt_xrootwin(), x, y, w, h );
00112 
00113 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
00114                 //No XShape - no work.
00115                 if (haveXShape) 
00116                 {
00117                 QBitmap mask(w, h);
00118                 //As the first step, get the mask from XShape.
00119                 int count, order;
00120                 XRectangle* rects = XShapeGetRectangles(qt_xdisplay(), child,
00121                                                         ShapeBounding, &count, &order);
00122                 //The ShapeBounding region is the outermost shape of the window;
00123                 //ShapeBounding - ShapeClipping is defined to be the border.
00124                 //Since the border area is part of the window, we use bounding
00125                 // to limit our work region
00126                 if (rects) 
00127                         {
00128                                 //Create a QRegion from the rectangles describing the bounding mask.
00129                                 QRegion contents;
00130                                 for (int pos = 0; pos < count; pos++)
00131                         contents += QRegion(rects[pos].x, rects[pos].y,
00132                                                 rects[pos].width, rects[pos].height);
00133                                 XFree(rects);
00134 
00135                                 //Create the bounding box.
00136                                 QRegion bbox(0, 0, snapshot.width(), snapshot.height());
00137 
00138                 if( border > 0 ) 
00139                                 {
00140                     contents.translate( border, border );
00141                     contents += QRegion( 0, 0, border, h );
00142                     contents += QRegion( 0, 0, w, border );
00143                     contents += QRegion( 0, h - border, w, border );
00144                     contents += QRegion( w - border, 0, border, h );
00145                 }
00146 
00147                                 //Get the masked away area.
00148                                 QRegion maskedAway = bbox - contents;
00149                                 QMemArray<QRect> maskedAwayRects = maskedAway.rects();
00150 
00151                                 //Construct a bitmap mask from the rectangles
00152                                 QPainter p(&mask);
00153                                 p.fillRect(0, 0, w, h, Qt::color1);
00154                                 for (uint pos = 0; pos < maskedAwayRects.count(); pos++)
00155                         p.fillRect(maskedAwayRects[pos], Qt::color0);
00156                                 p.end();
00157 
00158                                 m_snapshot.setMask(mask);
00159                 }
00160                 }
00161 #endif
00162     }
00163     else 
00164         {
00165                 m_snapshot = QPixmap::grabWindow( qt_xrootwin() );
00166     }
00167     XUngrabServer( qt_xdisplay());
00168         
00169         emit message(i18n("Snapshot taken."));
00170         emit finishCapture();
00171         
00172         return m_snapshot;
00173 }
00174 
00175 void Grabber::saveFiles()
00176 {
00177         emit startSave();
00178         emit message(i18n("Saving images..."));
00179         
00180         // make sure the UI is updated.
00181         kapp->processEvents();
00182         
00183         QString fileNameMain = Config().File.PathMain;
00184         saveMain(fileNameMain);
00185         
00186         if(Config().Ftp.UseThumb)
00187         {
00188                 QString fileNameThumb = Config().File.PathThumb;
00189                 saveThumb(fileNameThumb);
00190         }
00191         
00192         emit message(i18n("Images saved."));
00193         emit finishSave();
00194 }
00195         
00196 
00197 Window Grabber::findRealWindow( Window w, int depth)
00198 {
00199         if( depth > 5 )
00200                 return None;
00201     
00202         static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
00203     Atom type;
00204     int format;
00205     unsigned long nitems, after;
00206     unsigned char* prop;
00207     
00208         if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType,
00209         &type, &format, &nitems, &after, &prop ) == Success ) 
00210         {
00211                 if( prop != NULL )
00212                 XFree( prop );
00213                 if( type != None )
00214                 return w;
00215     }
00216     
00217         Window root, parent;
00218     Window* children;
00219     unsigned int nchildren;
00220     Window ret = None;
00221     if( XQueryTree( qt_xdisplay(), w, &root, &parent, &children, &nchildren ) != 0 ) 
00222         {
00223                 for( unsigned int i = 0; i < nchildren && ret == None; ++i )
00224                 ret = findRealWindow( children[ i ], depth + 1 );
00225                 if( children != NULL )
00226                 XFree( children );
00227     }
00228     return ret;
00229 }
00230 
00231 void Grabber::saveMain( const QString & fileName )
00232 {
00233         QImage temp = m_snapshot.convertToImage();
00234 
00235         if(Config().Capture.ScaleMode == Configuration::ScalePercent)
00236         {
00237                 int scale = Config().Capture.ScaleMain;
00238                 if(scale != 100)
00239                 {
00240                         int neww = (int)((double)m_snapshot.width() * ((double)scale / 100.0));
00241                         int newh = (int)((double)m_snapshot.height() * ((double)scale / 100.0));
00242                         temp = temp.scale(neww, newh, QImage::ScaleMin);
00243                 }
00244         }
00245         else if(Config().Capture.ScaleMode == Configuration::ScalePixel)
00246         {
00247                 int neww = Config().Capture.ScaleMain;
00248                 if(neww != m_snapshot.width())
00249                 {
00250                         double scale = (double)neww / (double) m_snapshot.width();
00251                         int newh = (int)((double)m_snapshot.height() *((double)scale));
00252                         temp = temp.scale(neww, newh, QImage::ScaleMin);
00253                 }
00254         }
00255 
00256         if(Config().Caption.UseCaption)
00257         {
00258                 QImage temp2 = drawCaption(temp);
00259 
00260                 if(!temp2.isNull())
00261                 {
00262                         temp = temp2;
00263                 }
00264                 else
00265                 {
00266                         emit message(i18n("Could not draw caption on main image."), Configuration::Debug);              
00267                 }
00268         }
00269 
00270         saveImage(fileName, temp);
00271 }
00272 
00273 void Grabber::saveThumb( const QString & fileName )
00274 {
00275         QImage temp = m_snapshot.convertToImage();
00276 
00277         if(Config().Caption.UseCaption)
00278         {
00279                 QImage temp2 = drawCaption(temp);
00280 
00281                 if(!temp2.isNull())
00282                 {
00283                         temp = temp2;
00284                 }
00285                 else
00286                 {
00287                         emit message(i18n("Could not draw caption on thumbnail image."), Configuration::Debug);
00288                 }
00289         }
00290         
00291         if(Config().Capture.ScaleMode == Configuration::ScalePercent)
00292         {
00293                 int scale = Config().Capture.ScaleThumb;
00294                 if(scale != 100)
00295                 {
00296                         int neww = (int)((double)m_snapshot.width() * ((double)scale / 100.0));
00297                         int newh = (int)((double)m_snapshot.height() * ((double)scale / 100.0));
00298                         temp = temp.scale(neww, newh, QImage::ScaleMin);
00299                 }
00300         }
00301         else if(Config().Capture.ScaleMode == Configuration::ScalePixel)
00302         {
00303                 int neww = Config().Capture.ScaleThumb;
00304                 if(neww != m_snapshot.width())
00305                 {
00306                         double scale = (double)neww / (double) m_snapshot.width();
00307                         int newh = (int)((double)m_snapshot.height() *((double)scale));
00308                         temp = temp.scale(neww, newh, QImage::ScaleMin);
00309                 }
00310         }       
00311         
00312         saveImage(fileName, temp);
00313 }
00314 
00315 void Grabber::saveImage(const QString& fileName, const QImage& image)
00316 {
00317         KURL url(fileName);
00318         
00319         if ( !url.isValid() )
00320         {
00321                 
00322         return;
00323         }
00324 
00325     QString type( KImageIO::type(url.path()) );
00326         if ( type.isNull() )
00327                 type = "PNG";
00328                 
00329         bool ok = false;
00330         
00331         KSaveFile saveFile( url.path() );
00332         if ( saveFile.status() == 0 ) 
00333         {
00334             if ( image.save( saveFile.file(), type.latin1(), Config().Capture.PictureQuality ) )
00335                         ok = saveFile.close();
00336         }
00337         
00338         if ( !ok ) 
00339                 emit message(i18n("Unable to save the image."), Configuration::Debug);
00340 }
00341 
00342 QImage Grabber::drawCaption(const QImage& image)
00343 {
00344         QString text = Config().Caption.Text;
00345 
00346         QPixmap pic(image);
00347         QPainter paint;
00348         paint.begin(&pic);
00349         paint.setFont(Config().Caption.Font);
00350         paint.setPen(Config().Caption.Color);
00351 
00352         if(Config().Caption.CustomPos)
00353         {
00354                 paint.drawText(Config().Caption.PositionX, Config().Caption.PositionY,  text);
00355         }
00356         else
00357         {
00358                 paint.drawText(pic.rect(),  Config().Caption.Position | Qt::WordBreak, text);
00359         }
00360 
00361         paint.end();
00362         return pic.convertToImage();
00363 }
00364 
00365 #include "grabber.moc"

Generated on Mon Sep 5 12:52:33 2005 for kwebsnap.kdevelop by  doxygen 1.3.9.1