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

KImgIO

eps.cpp

Go to the documentation of this file.
00001 
00007 #include "eps.h"
00008 #include <unistd.h>
00009 #include <stdio.h>
00010 #include <QtGui/QImage>
00011 #include <QtCore/QFile>
00012 #include <QtGui/QPainter>
00013 #include <QtGui/QPrinter>
00014 #include <QtCore/QTextStream>
00015 #include <QtCore/QTemporaryFile>
00016 #include <kapplication.h>
00017 #include <kdebug.h>
00018 
00019 #define BUFLEN 200
00020 
00021 #define BBOX "%%BoundingBox:"
00022 #define BBOX_LEN strlen(BBOX)
00023 
00024 static bool seekToCodeStart( QIODevice * io, quint32 & ps_offset, quint32 & ps_size )
00025 {
00026     char buf[4]; // We at most need to read 4 bytes at a time
00027     ps_offset=0L;
00028     ps_size=0L;
00029 
00030     if ( io->read(buf, 2)!=2 ) // Read first two bytes
00031     {
00032         kError(399) << "kimgio EPS: EPS file has less than 2 bytes." << endl;
00033         return false;
00034     }
00035 
00036     if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
00037     {
00038         kDebug(399) << "kimgio EPS: normal EPS file";
00039     }
00040     else if ( buf[0]==char(0xc5) && buf[1]==char(0xd0) ) // Check start of MS-DOS EPS magic
00041     {   // May be a MS-DOS EPS file
00042         if ( io->read(buf+2, 2)!=2 ) // Read further bytes of MS-DOS EPS magic
00043         {
00044             kError(399) << "kimgio EPS: potential MS-DOS EPS file has less than 4 bytes." << endl;
00045             return false;
00046         }
00047         if ( buf[2]==char(0xd3) && buf[3]==char(0xc6) ) // Check last bytes of MS-DOS EPS magic
00048         {
00049             if (io->read(buf, 4)!=4) // Get offset of PostScript code in the MS-DOS EPS file.
00050             {
00051                 kError(399) << "kimgio EPS: cannot read offset of MS-DOS EPS file" << endl;
00052                 return false;
00053             }
00054             ps_offset // Offset is in little endian
00055                 = ((unsigned char) buf[0])
00056                 + ((unsigned char) buf[1] << 8)
00057                 + ((unsigned char) buf[2] << 16)
00058                 + ((unsigned char) buf[3] << 24);
00059             if (io->read(buf, 4)!=4) // Get size of PostScript code in the MS-DOS EPS file.
00060             {
00061                 kError(399) << "kimgio EPS: cannot read size of MS-DOS EPS file" << endl;
00062                 return false;
00063             }
00064             ps_size // Size is in little endian
00065                 = ((unsigned char) buf[0])
00066                 + ((unsigned char) buf[1] << 8)
00067                 + ((unsigned char) buf[2] << 16)
00068                 + ((unsigned char) buf[3] << 24);
00069             kDebug(399) << "kimgio EPS: Offset: " << ps_offset <<" Size: " << ps_size;
00070             if ( !io->seek(ps_offset) ) // Get offset of PostScript code in the MS-DOS EPS file.
00071             {
00072                 kError(399) << "kimgio EPS: cannot seek in MS-DOS EPS file" << endl;
00073                 return false;
00074             }
00075             if ( io->read(buf, 2)!=2 ) // Read first two bytes of what should be the Postscript code
00076             {
00077                 kError(399) << "kimgio EPS: PostScript code has less than 2 bytes." << endl;
00078                 return false;
00079             }
00080             if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
00081             {
00082                 kDebug(399) << "kimgio EPS: MS-DOS EPS file";
00083             }
00084             else
00085             {
00086                 kError(399) << "kimgio EPS: supposed Postscript code of a MS-DOS EPS file doe not start with %!." << endl;
00087                 return false;
00088             }
00089         }
00090         else
00091         {
00092             kError(399) << "kimgio EPS: wrong magic for potential MS-DOS EPS file!" << endl;
00093             return false;
00094         }
00095     }
00096     else
00097     {
00098         kError(399) << "kimgio EPS: not an EPS file!" << endl;
00099         return false;
00100     }
00101     return true;
00102 }
00103 
00104 static bool bbox ( QIODevice *io, int *x1, int *y1, int *x2, int *y2)
00105 {
00106         char buf[BUFLEN+1];
00107 
00108         bool ret = false;
00109 
00110         while (io->readLine(buf, BUFLEN) > 0)
00111         {
00112                 if (strncmp (buf, BBOX, BBOX_LEN) == 0)
00113                 {
00114                         // Some EPS files have non-integer values for the bbox
00115                         // We don't support that currently, but at least we parse it
00116                         float _x1, _y1, _x2, _y2;
00117                         if ( sscanf (buf, "%*s %f %f %f %f",
00118                                 &_x1, &_y1, &_x2, &_y2) == 4) {
00119                                 kDebug(399) << "kimgio EPS BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2;
00120                                 *x1=(int)_x1; *y1=(int)_y1; *x2=(int)_x2; *y2=(int)_y2;
00121                                 ret = true;
00122                                 break;
00123                         }
00124                 }
00125         }
00126 
00127         return ret;
00128 }
00129 
00130 EPSHandler::EPSHandler()
00131 {
00132 }
00133 
00134 bool EPSHandler::canRead() const
00135 {
00136     if (canRead(device())) {
00137         setFormat("eps");
00138         return true;
00139     }
00140     return false;
00141 }
00142 
00143 bool EPSHandler::read(QImage *image)
00144 {
00145     kDebug(399) << "kimgio EPS: starting...";
00146 
00147     FILE * ghostfd;
00148     int x1, y1, x2, y2;
00149     //QTime dt;
00150     //dt.start();
00151 
00152     QString cmdBuf;
00153     QString tmp;
00154 
00155     QIODevice* io = device();
00156     quint32 ps_offset, ps_size;
00157 
00158     // find start of PostScript code
00159     if ( !seekToCodeStart(io, ps_offset, ps_size) )
00160         return false;
00161 
00162     // find bounding box
00163     if ( !bbox (io, &x1, &y1, &x2, &y2)) {
00164         kError(399) << "kimgio EPS: no bounding box found!" << endl;
00165         return false;
00166     }
00167 
00168     QTemporaryFile tmpFile;
00169     if( !tmpFile.open() ) {
00170         kError(399) << "kimgio EPS: no temp file!" << endl;
00171         return false;
00172     }
00173 
00174     // x1, y1 -> translation
00175     // x2, y2 -> new size
00176 
00177     x2 -= x1;
00178     y2 -= y1;
00179     //kDebug(399) << "origin point: " << x1 << "," << y1 << "  size:" << x2 << "," << y2;
00180     double xScale = 1.0;
00181     double yScale = 1.0;
00182     int wantedWidth = x2;
00183     int wantedHeight = y2;
00184 
00185     // create GS command line
00186 
00187     cmdBuf = "gs -sOutputFile=";
00188     cmdBuf += tmpFile.fileName();
00189     cmdBuf += " -q -g";
00190     tmp.setNum( wantedWidth );
00191     cmdBuf += tmp;
00192     tmp.setNum( wantedHeight );
00193     cmdBuf += 'x';
00194     cmdBuf += tmp;
00195     cmdBuf += " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
00196               "0 0 moveto "
00197               "1000 0 lineto "
00198               "1000 1000 lineto "
00199               "0 1000 lineto "
00200               "1 1 254 255 div setrgbcolor fill "
00201               "0 0 0 setrgbcolor - -c showpage quit";
00202 
00203     // run ghostview
00204 
00205     ghostfd = popen (QFile::encodeName(cmdBuf), "w");
00206 
00207     if ( ghostfd == 0 ) {
00208         kError(399) << "kimgio EPS: no GhostScript?" << endl;
00209         return false;
00210     }
00211 
00212     fprintf (ghostfd, "\n%d %d translate\n", -qRound(x1*xScale), -qRound(y1*yScale));
00213 
00214     // write image to gs
00215 
00216     io->reset(); // Go back to start of file to give all the file to GhostScript
00217     if (ps_offset>0L) // We have an offset
00218         io->seek(ps_offset);
00219     QByteArray buffer ( io->readAll() );
00220 
00221     // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
00222     if (ps_size<=0 || ps_size>(unsigned int)buffer.size())
00223         ps_size=buffer.size();
00224 
00225     fwrite(buffer.data(), sizeof(char), ps_size, ghostfd);
00226     buffer.resize(0);
00227 
00228     pclose ( ghostfd );
00229 
00230     // load image
00231     if( image->load (tmpFile.fileName()) ) {
00232         kDebug(399) << "kimgio EPS: success!";
00233         //kDebug(399) << "Loading EPS took " << (float)(dt.elapsed()) / 1000 << " seconds";
00234         return true;
00235     }
00236 
00237     kError(399) << "kimgio EPS: no image!" << endl;
00238     return false;
00239 }
00240 
00241 
00242 // Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot)
00243 bool EPSHandler::write(const QImage &image)
00244 {
00245     QPrinter psOut(QPrinter::PrinterResolution);
00246     QPainter p;
00247 
00248     // making some definitions (papersize, output to file, filename):
00249     psOut.setCreator( "KDE " KDE_VERSION_STRING  );
00250     if ( psOut.outputFileName().isEmpty() )
00251       psOut.setOutputFileName( "untitled_printer_document" );
00252 
00253     // Extension must be .eps so that Qt generates EPS file
00254     QTemporaryFile tmpFile("XXXXXXXX.eps");
00255     if ( !tmpFile.open() )
00256         return false;
00257 
00258     psOut.setOutputFileName(tmpFile.fileName());
00259     psOut.setFullPage(true);
00260 
00261     // painting the pixmap to the "printer" which is a file
00262     p.begin( &psOut );
00263     // Qt uses the clip rect for the bounding box
00264     p.setClipRect( 0, 0, image.width(), image.height());
00265     p.drawImage( QPoint( 0, 0 ), image );
00266     p.end();
00267 
00268     // Copy file to imageio struct
00269     QFile inFile(tmpFile.fileName());
00270     inFile.open( QIODevice::ReadOnly );
00271 
00272     QTextStream in( &inFile );
00273     in.setCodec( "ISO-8859-1" );
00274     QTextStream out( device() );
00275     out.setCodec( "ISO-8859-1" );
00276 
00277     QString szInLine = in.readLine();
00278     out << szInLine << '\n';
00279 
00280     while( !in.atEnd() ){
00281         szInLine = in.readLine();
00282         out << szInLine << '\n';
00283     }
00284 
00285     inFile.close();
00286 
00287     return true;
00288 }
00289 
00290 QByteArray EPSHandler::name() const
00291 {
00292     return "eps";
00293 }
00294 
00295 bool EPSHandler::canRead(QIODevice *device)
00296 {
00297     if (!device) {
00298         qWarning("EPSHandler::canRead() called with no device");
00299         return false;
00300     }
00301 
00302     qint64 oldPos = device->pos();
00303 
00304     QByteArray head = device->readLine(64);
00305     int readBytes = head.size();
00306     if (device->isSequential()) {
00307         while (readBytes > 0)
00308             device->ungetChar(head[readBytes-- - 1]);
00309     } else {
00310         device->seek(oldPos);
00311     }
00312 
00313     return head.contains("%!PS-Adobe");
00314 }
00315 
00316 class EPSPlugin : public QImageIOPlugin
00317 {
00318 public:
00319     QStringList keys() const;
00320     Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
00321     QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
00322 };
00323 
00324 QStringList EPSPlugin::keys() const
00325 {
00326     return QStringList() << "eps" << "EPS" << "epsi" << "EPSI" << "epsf" << "EPSF";
00327 }
00328 
00329 QImageIOPlugin::Capabilities EPSPlugin::capabilities(QIODevice *device, const QByteArray &format) const
00330 {
00331     if (format == "eps" || format == "epsi" || format == "EPS" || format == "EPSI" ||
00332         format == "epsf" || format == "EPSF")
00333         return Capabilities(CanRead | CanWrite);
00334     if (!format.isEmpty())
00335         return 0;
00336     if (!device->isOpen())
00337         return 0;
00338 
00339     Capabilities cap;
00340     if (device->isReadable() && EPSHandler::canRead(device))
00341         cap |= CanRead;
00342     if (device->isWritable())
00343         cap |= CanWrite;
00344     return cap;
00345 }
00346 
00347 QImageIOHandler *EPSPlugin::create(QIODevice *device, const QByteArray &format) const
00348 {
00349     QImageIOHandler *handler = new EPSHandler;
00350     handler->setDevice(device);
00351     handler->setFormat(format);
00352     return handler;
00353 }
00354 
00355 Q_EXPORT_STATIC_PLUGIN(EPSPlugin)
00356 Q_EXPORT_PLUGIN2(eps, EPSPlugin)

KImgIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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