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

KImgIO

  • sources
  • kde-4.12
  • kdelibs
  • kimgio
eps.cpp
Go to the documentation of this file.
1 
7 #include "eps.h"
8 #include <unistd.h>
9 #include <stdio.h>
10 #include <QtGui/QImage>
11 #include <QtCore/QFile>
12 #include <QtGui/QPainter>
13 #include <QtGui/QPrinter>
14 #include <QtCore/QTextStream>
15 #include <QtCore/QTemporaryFile>
16 #include <kapplication.h>
17 #include <kdebug.h>
18 
19 #define BUFLEN 200
20 
21 #define BBOX "%%BoundingBox:"
22 #define BBOX_LEN strlen(BBOX)
23 
24 static bool seekToCodeStart( QIODevice * io, quint32 & ps_offset, quint32 & ps_size )
25 {
26  char buf[4]; // We at most need to read 4 bytes at a time
27  ps_offset=0L;
28  ps_size=0L;
29 
30  if ( io->read(buf, 2)!=2 ) // Read first two bytes
31  {
32  kError(399) << "kimgio EPS: EPS file has less than 2 bytes." << endl;
33  return false;
34  }
35 
36  if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
37  {
38  kDebug(399) << "kimgio EPS: normal EPS file";
39  }
40  else if ( buf[0]==char(0xc5) && buf[1]==char(0xd0) ) // Check start of MS-DOS EPS magic
41  { // May be a MS-DOS EPS file
42  if ( io->read(buf+2, 2)!=2 ) // Read further bytes of MS-DOS EPS magic
43  {
44  kError(399) << "kimgio EPS: potential MS-DOS EPS file has less than 4 bytes." << endl;
45  return false;
46  }
47  if ( buf[2]==char(0xd3) && buf[3]==char(0xc6) ) // Check last bytes of MS-DOS EPS magic
48  {
49  if (io->read(buf, 4)!=4) // Get offset of PostScript code in the MS-DOS EPS file.
50  {
51  kError(399) << "kimgio EPS: cannot read offset of MS-DOS EPS file" << endl;
52  return false;
53  }
54  ps_offset // Offset is in little endian
55  = ((unsigned char) buf[0])
56  + ((unsigned char) buf[1] << 8)
57  + ((unsigned char) buf[2] << 16)
58  + ((unsigned char) buf[3] << 24);
59  if (io->read(buf, 4)!=4) // Get size of PostScript code in the MS-DOS EPS file.
60  {
61  kError(399) << "kimgio EPS: cannot read size of MS-DOS EPS file" << endl;
62  return false;
63  }
64  ps_size // Size is in little endian
65  = ((unsigned char) buf[0])
66  + ((unsigned char) buf[1] << 8)
67  + ((unsigned char) buf[2] << 16)
68  + ((unsigned char) buf[3] << 24);
69  kDebug(399) << "kimgio EPS: Offset: " << ps_offset <<" Size: " << ps_size;
70  if ( !io->seek(ps_offset) ) // Get offset of PostScript code in the MS-DOS EPS file.
71  {
72  kError(399) << "kimgio EPS: cannot seek in MS-DOS EPS file" << endl;
73  return false;
74  }
75  if ( io->read(buf, 2)!=2 ) // Read first two bytes of what should be the Postscript code
76  {
77  kError(399) << "kimgio EPS: PostScript code has less than 2 bytes." << endl;
78  return false;
79  }
80  if ( buf[0]=='%' && buf[1]=='!' ) // Check %! magic
81  {
82  kDebug(399) << "kimgio EPS: MS-DOS EPS file";
83  }
84  else
85  {
86  kError(399) << "kimgio EPS: supposed Postscript code of a MS-DOS EPS file doe not start with %!." << endl;
87  return false;
88  }
89  }
90  else
91  {
92  kError(399) << "kimgio EPS: wrong magic for potential MS-DOS EPS file!" << endl;
93  return false;
94  }
95  }
96  else
97  {
98  kError(399) << "kimgio EPS: not an EPS file!" << endl;
99  return false;
100  }
101  return true;
102 }
103 
104 static bool bbox ( QIODevice *io, int *x1, int *y1, int *x2, int *y2)
105 {
106  char buf[BUFLEN+1];
107 
108  bool ret = false;
109 
110  while (io->readLine(buf, BUFLEN) > 0)
111  {
112  if (strncmp (buf, BBOX, BBOX_LEN) == 0)
113  {
114  // Some EPS files have non-integer values for the bbox
115  // We don't support that currently, but at least we parse it
116  float _x1, _y1, _x2, _y2;
117  if ( sscanf (buf, "%*s %f %f %f %f",
118  &_x1, &_y1, &_x2, &_y2) == 4) {
119  kDebug(399) << "kimgio EPS BBOX: " << _x1 << " " << _y1 << " " << _x2 << " " << _y2;
120  *x1=(int)_x1; *y1=(int)_y1; *x2=(int)_x2; *y2=(int)_y2;
121  ret = true;
122  break;
123  }
124  }
125  }
126 
127  return ret;
128 }
129 
130 EPSHandler::EPSHandler()
131 {
132 }
133 
134 bool EPSHandler::canRead() const
135 {
136  if (canRead(device())) {
137  setFormat("eps");
138  return true;
139  }
140  return false;
141 }
142 
143 bool EPSHandler::read(QImage *image)
144 {
145  kDebug(399) << "kimgio EPS: starting...";
146 
147  FILE * ghostfd;
148  int x1, y1, x2, y2;
149  //QTime dt;
150  //dt.start();
151 
152  QString cmdBuf;
153  QString tmp;
154 
155  QIODevice* io = device();
156  quint32 ps_offset, ps_size;
157 
158  // find start of PostScript code
159  if ( !seekToCodeStart(io, ps_offset, ps_size) )
160  return false;
161 
162  // find bounding box
163  if ( !bbox (io, &x1, &y1, &x2, &y2)) {
164  kError(399) << "kimgio EPS: no bounding box found!" << endl;
165  return false;
166  }
167 
168  QTemporaryFile tmpFile;
169  if( !tmpFile.open() ) {
170  kError(399) << "kimgio EPS: no temp file!" << endl;
171  return false;
172  }
173 
174  // x1, y1 -> translation
175  // x2, y2 -> new size
176 
177  x2 -= x1;
178  y2 -= y1;
179  //kDebug(399) << "origin point: " << x1 << "," << y1 << " size:" << x2 << "," << y2;
180  double xScale = 1.0;
181  double yScale = 1.0;
182  int wantedWidth = x2;
183  int wantedHeight = y2;
184 
185  // create GS command line
186 
187  cmdBuf = "gs -sOutputFile=";
188  cmdBuf += tmpFile.fileName();
189  cmdBuf += " -q -g";
190  tmp.setNum( wantedWidth );
191  cmdBuf += tmp;
192  tmp.setNum( wantedHeight );
193  cmdBuf += 'x';
194  cmdBuf += tmp;
195  cmdBuf += " -dSAFER -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ppm -c "
196  "0 0 moveto "
197  "1000 0 lineto "
198  "1000 1000 lineto "
199  "0 1000 lineto "
200  "1 1 254 255 div setrgbcolor fill "
201  "0 0 0 setrgbcolor - -c showpage quit";
202 
203  // run ghostview
204 
205  ghostfd = popen (QFile::encodeName(cmdBuf), "w");
206 
207  if ( ghostfd == 0 ) {
208  kError(399) << "kimgio EPS: no GhostScript?" << endl;
209  return false;
210  }
211 
212  fprintf (ghostfd, "\n%d %d translate\n", -qRound(x1*xScale), -qRound(y1*yScale));
213 
214  // write image to gs
215 
216  io->reset(); // Go back to start of file to give all the file to GhostScript
217  if (ps_offset>0L) // We have an offset
218  io->seek(ps_offset);
219  QByteArray buffer ( io->readAll() );
220 
221  // If we have no MS-DOS EPS file or if the size seems wrong, then choose the buffer size
222  if (ps_size<=0 || ps_size>(unsigned int)buffer.size())
223  ps_size=buffer.size();
224 
225  fwrite(buffer.data(), sizeof(char), ps_size, ghostfd);
226  buffer.resize(0);
227 
228  pclose ( ghostfd );
229 
230  // load image
231  if( image->load (tmpFile.fileName()) ) {
232  kDebug(399) << "kimgio EPS: success!";
233  //kDebug(399) << "Loading EPS took " << (float)(dt.elapsed()) / 1000 << " seconds";
234  return true;
235  }
236 
237  kError(399) << "kimgio EPS: no image!" << endl;
238  return false;
239 }
240 
241 
242 // Sven Wiegand <SWiegand@tfh-berlin.de> -- eps output filter (from KSnapshot)
243 bool EPSHandler::write(const QImage &image)
244 {
245  QPrinter psOut(QPrinter::PrinterResolution);
246  QPainter p;
247 
248  // making some definitions (papersize, output to file, filename):
249  psOut.setCreator( "KDE " KDE_VERSION_STRING );
250  if ( psOut.outputFileName().isEmpty() )
251  psOut.setOutputFileName( "untitled_printer_document" );
252 
253  // Extension must be .eps so that Qt generates EPS file
254  QTemporaryFile tmpFile("XXXXXXXX.eps");
255  if ( !tmpFile.open() )
256  return false;
257 
258  psOut.setOutputFileName(tmpFile.fileName());
259  psOut.setOutputFormat(QPrinter::PostScriptFormat);
260  psOut.setFullPage(true);
261  psOut.setPaperSize(image.size(), QPrinter::DevicePixel);
262 
263  // painting the pixmap to the "printer" which is a file
264  p.begin( &psOut );
265  p.drawImage( QPoint( 0, 0 ), image );
266  p.end();
267 
268  // Copy file to imageio struct
269  QFile inFile(tmpFile.fileName());
270  if ( !inFile.open( QIODevice::ReadOnly ) )
271  return false;
272 
273  QTextStream in( &inFile );
274  in.setCodec( "ISO-8859-1" );
275  QTextStream out( device() );
276  out.setCodec( "ISO-8859-1" );
277 
278  QString szInLine = in.readLine();
279  out << szInLine << '\n';
280 
281  while( !in.atEnd() ){
282  szInLine = in.readLine();
283  out << szInLine << '\n';
284  }
285 
286  inFile.close();
287 
288  return true;
289 }
290 
291 QByteArray EPSHandler::name() const
292 {
293  return "eps";
294 }
295 
296 bool EPSHandler::canRead(QIODevice *device)
297 {
298  if (!device) {
299  qWarning("EPSHandler::canRead() called with no device");
300  return false;
301  }
302 
303  qint64 oldPos = device->pos();
304 
305  QByteArray head = device->readLine(64);
306  int readBytes = head.size();
307  if (device->isSequential()) {
308  while (readBytes > 0)
309  device->ungetChar(head[readBytes-- - 1]);
310  } else {
311  device->seek(oldPos);
312  }
313 
314  return head.contains("%!PS-Adobe");
315 }
316 
317 class EPSPlugin : public QImageIOPlugin
318 {
319 public:
320  QStringList keys() const;
321  Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
322  QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
323 };
324 
325 QStringList EPSPlugin::keys() const
326 {
327  return QStringList() << "eps" << "EPS" << "epsi" << "EPSI" << "epsf" << "EPSF";
328 }
329 
330 QImageIOPlugin::Capabilities EPSPlugin::capabilities(QIODevice *device, const QByteArray &format) const
331 {
332  if (format == "eps" || format == "epsi" || format == "EPS" || format == "EPSI" ||
333  format == "epsf" || format == "EPSF")
334  return Capabilities(CanRead | CanWrite);
335  if (!format.isEmpty())
336  return 0;
337  if (!device->isOpen())
338  return 0;
339 
340  Capabilities cap;
341  if (device->isReadable() && EPSHandler::canRead(device))
342  cap |= CanRead;
343  if (device->isWritable())
344  cap |= CanWrite;
345  return cap;
346 }
347 
348 QImageIOHandler *EPSPlugin::create(QIODevice *device, const QByteArray &format) const
349 {
350  QImageIOHandler *handler = new EPSHandler;
351  handler->setDevice(device);
352  handler->setFormat(format);
353  return handler;
354 }
355 
356 Q_EXPORT_STATIC_PLUGIN(EPSPlugin)
357 Q_EXPORT_PLUGIN2(eps, EPSPlugin)
seekToCodeStart
static bool seekToCodeStart(QIODevice *io, quint32 &ps_offset, quint32 &ps_size)
Definition: eps.cpp:24
EPSHandler::name
QByteArray name() const
Definition: eps.cpp:291
EPSHandler::EPSHandler
EPSHandler()
Definition: eps.cpp:130
bbox
static bool bbox(QIODevice *io, int *x1, int *y1, int *x2, int *y2)
Definition: eps.cpp:104
eps.h
EPSHandler::write
bool write(const QImage &image)
Definition: eps.cpp:243
BUFLEN
#define BUFLEN
QImageIO Routines to read/write EPS images.
Definition: eps.cpp:19
EPSHandler::canRead
bool canRead() const
Definition: eps.cpp:134
QImageIOHandler
BBOX
#define BBOX
Definition: eps.cpp:21
EPSHandler::read
bool read(QImage *image)
Definition: eps.cpp:143
EPSHandler
QImageIO Routines to read/write EPS images.
Definition: eps.h:13
BBOX_LEN
#define BBOX_LEN
Definition: eps.cpp:22
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KImgIO

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal