• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KImgIO

eps.cpp

Go to the documentation of this file.
00001 // This library is distributed under the conditions of the GNU LGPL.
00002 #include <unistd.h>
00003 #include <stdio.h>
00004 #include <qimage.h>
00005 #include <qfile.h>
00006 #include <qpainter.h>
00007 #include <qprinter.h>
00008 #include <kapplication.h>
00009 #include <ktempfile.h>
00010 #include <kdebug.h>
00011 #include "eps.h"
00012 
00013 #define BUFLEN 200
00014 
00015 #define BBOX "%%BoundingBox:"
00016 #define BBOX_LEN strlen(BBOX)
00017 
00018 static bool seekToCodeStart( QIODevice * io, Q_UINT32 & ps_offset, Q_UINT32 & ps_size )
00019 {
00020     char buf[4]; // We at most need to read 4 bytes at a time
00021     ps_offset=0L;
00022     ps_size=0L;
00023 
00024     if ( io->readBlock(buf, 2)!=2 ) // Read first two bytes
00025     {
00026         kdError(399) << "kimgio EPS: EPS file has less than 2 bytes." << endl;
00027         return false;
00028     }
00029 
00030     if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
00031     {
00032         kdDebug(399) << "kimgio EPS: normal EPS file" << endl;
00033     }
00034     else if ( buf[0]==char(0xc5) && buf[1]==char(0xd0) ) // Check start of MS-DOS EPS magic
00035     {   // May be a MS-DOS EPS file
00036         if ( io->readBlock(buf+2, 2)!=2 ) // Read further bytes of MS-DOS EPS magic
00037         {
00038             kdError(399) << "kimgio EPS: potential MS-DOS EPS file has less than 4 bytes." << endl;
00039             return false;
00040         }
00041         if ( buf[2]==char(0xd3) && buf[3]==char(0xc6) ) // Check last bytes of MS-DOS EPS magic
00042         {
00043             if (io->readBlock(buf, 4)!=4) // Get offset of PostScript code in the MS-DOS EPS file.
00044             {
00045                 kdError(399) << "kimgio EPS: cannot read offset of MS-DOS EPS file" << endl;
00046                 return false;
00047             }
00048             ps_offset // Offset is in little endian
00049                 = ((unsigned char) buf[0])
00050                 + ((unsigned char) buf[1] << 8)
00051                 + ((unsigned char) buf[2] << 16)
00052                 + ((unsigned char) buf[3] << 24);
00053             if (io->readBlock(buf, 4)!=4) // Get size of PostScript code in the MS-DOS EPS file.
00054             {
00055                 kdError(399) << "kimgio EPS: cannot read size of MS-DOS EPS file" << endl;
00056                 return false;
00057             }
00058             ps_size // Size is in little endian
00059                 = ((unsigned char) buf[0])
00060                 + ((unsigned char) buf[1] << 8)
00061                 + ((unsigned char) buf[2] << 16)
00062                 + ((unsigned char) buf[3] << 24);
00063             kdDebug(399) << "kimgio EPS: Offset: " << ps_offset <<" Size: " << ps_size << endl;
00064             if ( !io->at(ps_offset) ) // Get offset of PostScript code in the MS-DOS EPS file.
00065             {
00066                 kdError(399) << "kimgio EPS: cannot seek in MS-DOS EPS file" << endl;
00067                 return false;
00068             }
00069             if ( io->readBlock(buf, 2)!=2 ) // Read first two bytes of what should be the Postscript code
00070             {
00071                 kdError(399) << "kimgio EPS: PostScript code has less than 2 bytes." << endl;
00072                 return false;
00073             }
00074             if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
00075             {
00076                 kdDebug(399) << "kimgio EPS: MS-DOS EPS file" << endl;
00077             }
00078             else
00079             {
00080                 kdError(399) << "kimgio EPS: supposed Postscript code of a MS-DOS EPS file doe not start with %!." << endl;
00081                 return false;
00082             }
00083         }
00084         else
00085         {
00086             kdError(399) << "kimgio EPS: wrong magic for potential MS-DOS EPS file!" << endl;
00087             return false;
00088         }
00089     }
00090     else
00091     {
00092         kdError(399) << "kimgio EPS: not an EPS file!" << endl;
00093         return false;
00094     }
00095     return true;
00096 }
00097 
00098 static bool bbox ( QIODevice *io, int *x1, int *y1, int *x2, int *y2)
00099 {
00100         char buf[BUFLEN+1];
00101 
00102         bool ret = false;
00103 
00104         while (io->readLine(buf, BUFLEN) > 0)
00105         {
00106                 if (strncmp (buf, BBOX, BBOX_LEN) == 0)
00107                 {
00108                         // Some EPS files have non-integer values for the bbox
00109                         // We don't support that currently, but at least we parse it
00110                         float _x1, _y1, _x2, _y2;
00111                         if ( sscanf (buf, "%*s %f %f %f %f",
00112                                 &_x1, &_y1, &_x2, &_y2) == 4) {
00113                                 kdDebug(399) << "kimgio EPS BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2 << endl;
00114                                 *x1=(int)_x1; *y1=(int)_y1; *x2=(int)_x2; *y2=(int)_y2;
00115                                 ret = true;
00116                                 break;
00117                         }
00118                 }
00119         }
00120 
00121         return ret;
00122 }
00123 
00124 KDE_EXPORT void kimgio_eps_read (QImageIO *image)
00125 {
00126         kdDebug(399) << "kimgio EPS: starting..." << endl;
00127 
00128         FILE * ghostfd;
00129         int x1, y1, x2, y2;
00130         //QTime dt;
00131         //dt.start();
00132 
00133         QString cmdBuf;
00134         QString tmp;
00135 
00136         QIODevice* io = image->ioDevice();
00137         Q_UINT32 ps_offset, ps_size;
00138 
00139         // find start of PostScript code
00140         if ( !seekToCodeStart(io, ps_offset, ps_size) )
00141             return;
00142 
00143         // find bounding box
00144         if ( !bbox (io, &x1, &y1, &x2, &y2)) {
00145             kdError(399) << "kimgio EPS: no bounding box found!" << endl;
00146             return;
00147         }
00148 
00149         KTempFile tmpFile;
00150         tmpFile.setAutoDelete(true);
00151 
00152         if( tmpFile.status() != 0 ) {
00153             kdError(399) << "kimgio EPS: no temp file!" << endl;
00154             return;
00155         }
00156         tmpFile.close(); // Close the file, we just want the filename
00157 
00158         // x1, y1 -> translation
00159         // x2, y2 -> new size
00160 
00161         x2 -= x1;
00162         y2 -= y1;
00163         //kdDebug(399) << "origin point: " << x1 << "," << y1 << "  size:" << x2 << "," << y2 << endl;
00164         double xScale = 1.0;
00165         double yScale = 1.0;
00166     bool needsScaling = false;
00167         int wantedWidth = x2;
00168         int wantedHeight = y2;
00169 
00170         if (image->parameters())
00171         {
00172             // Size forced by the caller
00173             QStringList params = QStringList::split(':', image->parameters());
00174             if (params.count() >= 2 && x2 != 0.0 && y2 != 0.0)
00175             {
00176                 wantedWidth = params[0].toInt();
00177                 xScale = (double)wantedWidth / (double)x2;
00178                 wantedHeight = params[1].toInt();
00179                 yScale = (double)wantedHeight / (double)y2;
00180                 //kdDebug(399) << "wanted size:" << wantedWidth << "x" << wantedHeight << endl;
00181                 //kdDebug(399) << "scaling:" << xScale << "," << yScale << endl;
00182         needsScaling = true;
00183             }
00184         }
00185 
00186         // create GS command line
00187 
00188         cmdBuf = "gs -sOutputFile=";
00189         cmdBuf += tmpFile.name();
00190         cmdBuf += " -q -g";
00191         tmp.setNum( wantedWidth );
00192         cmdBuf += tmp;
00193         tmp.setNum( wantedHeight );
00194         cmdBuf += "x";
00195         cmdBuf += tmp;
00196         cmdBuf += " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
00197                 "0 0 moveto "
00198                 "1000 0 lineto "
00199                 "1000 1000 lineto "
00200                 "0 1000 lineto "
00201                 "1 1 254 255 div setrgbcolor fill "
00202                 "0 0 0 setrgbcolor - -c showpage quit";
00203 
00204         // run ghostview
00205 
00206         ghostfd = popen (QFile::encodeName(cmdBuf), "w");
00207 
00208         if ( ghostfd == 0 ) {
00209             kdError(399) << "kimgio EPS: no GhostScript?" << endl;
00210             return;
00211         }
00212 
00213         fprintf (ghostfd, "\n%d %d translate\n", -qRound(x1*xScale), -qRound(y1*yScale));
00214         if ( needsScaling )
00215             fprintf (ghostfd, "%g %g scale\n", xScale, yScale);
00216 
00217         // write image to gs
00218 
00219         io->reset(); // Go back to start of file to give all the file to GhostScript
00220         if (ps_offset>0L) // We have an offset
00221               io->at(ps_offset);
00222         QByteArray buffer ( io->readAll() );
00223 
00224         // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
00225         if (ps_size<=0L || ps_size>buffer.size())
00226             ps_size=buffer.size();
00227 
00228         fwrite(buffer.data(), sizeof(char), ps_size, ghostfd);
00229         buffer.resize(0);
00230 
00231         pclose ( ghostfd );
00232 
00233         // load image
00234         QImage myimage;
00235         if( myimage.load (tmpFile.name()) ) {
00236                 image->setImage (myimage);
00237                 image->setStatus (0);
00238                 kdDebug(399) << "kimgio EPS: success!" << endl;
00239         }
00240         else
00241             kdError(399) << "kimgio EPS: no image!" << endl;
00242 
00243         //kdDebug(399) << "Loading EPS took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
00244         return;
00245 }
00246 
00247 // Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot)
00248 KDE_EXPORT void kimgio_eps_write( QImageIO *imageio )
00249 {
00250   QPrinter psOut(QPrinter::PrinterResolution);
00251   QPainter p;
00252 
00253   // making some definitions (papersize, output to file, filename):
00254   psOut.setCreator( "KDE " KDE_VERSION_STRING  );
00255   psOut.setOutputToFile( true );
00256 
00257   // Extension must be .eps so that Qt generates EPS file
00258   KTempFile tmpFile(QString::null, ".eps");
00259   tmpFile.setAutoDelete(true);
00260   if ( tmpFile.status() != 0)
00261      return;
00262   tmpFile.close(); // Close the file, we just want the filename
00263 
00264   psOut.setOutputFileName(tmpFile.name());
00265   psOut.setFullPage(true);
00266 
00267   // painting the pixmap to the "printer" which is a file
00268   p.begin( &psOut );
00269   // Qt uses the clip rect for the bounding box
00270   p.setClipRect( 0, 0, imageio->image().width(), imageio->image().height(), QPainter::CoordPainter);
00271   p.drawImage( QPoint( 0, 0 ), imageio->image() );
00272   p.end();
00273 
00274   // Copy file to imageio struct
00275   QFile inFile(tmpFile.name());
00276   inFile.open( IO_ReadOnly );
00277 
00278   QTextStream in( &inFile );
00279   in.setEncoding( QTextStream::Latin1 );
00280   QTextStream out( imageio->ioDevice() );
00281   out.setEncoding( QTextStream::Latin1 );
00282 
00283   QString szInLine = in.readLine();
00284   out << szInLine << '\n';
00285 
00286   while( !in.atEnd() ){
00287     szInLine = in.readLine();
00288     out << szInLine << '\n';
00289   }
00290 
00291   inFile.close();
00292 
00293   imageio->setStatus(0);
00294 }

KImgIO

Skip menu "KImgIO"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal