23 #include "qglviewer.h"
25 #ifndef NO_VECTORIAL_RENDER
26 # if QT_VERSION >= 0x040000
27 # include "ui_VRenderInterface.Qt4.h"
29 # include <qcheckbox.h>
30 # include <qcombobox.h>
31 # include "VRenderInterface.Qt3.h"
33 # include "VRender/VRender.h"
36 #if QT_VERSION >= 0x040000
37 # include "ui_ImageInterface.Qt4.h"
39 # include <qspinbox.h>
40 # include <qcheckbox.h>
41 # include "ImageInterface.Qt3.h"
45 #if QT_VERSION < 0x040000
48 # include <QImageWriter>
51 #include <qfileinfo.h>
52 #include <qfiledialog.h>
53 #include <qmessagebox.h>
54 #include <qapplication.h>
56 #include <qinputdialog.h>
57 #include <qprogressdialog.h>
64 static QString formats;
66 static QMap<QString, QString> Qtformat;
68 static QMap<QString, QString> FDFormatString;
70 static QMap<QString, QString> extension;
76 #if QT_VERSION >= 0x040000
77 snapshotFileName_ = QFileInfo(name).absoluteFilePath();
79 snapshotFileName_ = QFileInfo(name).absFilePath();
84 const QString& QGLViewer::snapshotFilename()
const
86 qWarning(
"snapshotFilename is deprecated. Use snapshotFileName() (uppercase N) instead.");
87 return snapshotFileName();
100 #if QT_VERSION >= 0x040000
101 QStringList list = formats.split(
";;", QString::SkipEmptyParts);
102 int current = list.indexOf(FDFormatString[snapshotFormat()]);
103 QString format = QInputDialog::getItem(
this,
"Snapshot format",
"Select a snapshot format", list, current,
false, &ok);
105 QStringList list = QStringList::split(
";;", formats);
106 int current = list.findIndex(FDFormatString[snapshotFormat()]);
107 QString format = QInputDialog::getItem(
"Snapshot format",
"Select a snapshot format", list, current,
false, &ok,
this);
110 setSnapshotFormat(Qtformat[format]);
117 void QGLViewer::initializeSnapshotFormats()
119 #if QT_VERSION >= 0x040000
120 QList<QByteArray> list = QImageWriter::supportedImageFormats();
121 QStringList formatList;
122 for (
int i=0; i < list.size(); ++i)
123 formatList << QString(list.at(i).toUpper());
125 QStringList formatList = QImage::outputFormatList();
132 #ifndef NO_VECTORIAL_RENDER
136 formatList +=
"XFIG";
141 QStringList QtText, MenuText, Ext;
142 QtText +=
"JPEG"; MenuText +=
"JPEG (*.jpg)"; Ext +=
"jpg";
143 QtText +=
"PNG"; MenuText +=
"PNG (*.png)"; Ext +=
"png";
144 QtText +=
"EPS"; MenuText +=
"Encapsulated Postscript (*.eps)"; Ext +=
"eps";
145 QtText +=
"PS"; MenuText +=
"Postscript (*.ps)"; Ext +=
"ps";
146 QtText +=
"PPM"; MenuText +=
"24bit RGB Bitmap (*.ppm)"; Ext +=
"ppm";
147 QtText +=
"BMP"; MenuText +=
"Windows Bitmap (*.bmp)"; Ext +=
"bmp";
148 QtText +=
"XFIG"; MenuText +=
"XFig (*.fig)"; Ext +=
"fig";
150 #if QT_VERSION < 0x030000
151 QStringList::Iterator itText = QtText.begin();
152 QStringList::Iterator itMenu = MenuText.begin();
153 QStringList::Iterator itExt = Ext.begin();
155 QStringList::iterator itText = QtText.begin();
156 QStringList::iterator itMenu = MenuText.begin();
157 QStringList::iterator itExt = Ext.begin();
159 while (itText != QtText.end())
162 if (formatList.contains((*itText)))
165 if (formats.isEmpty())
166 setSnapshotFormat(*itText);
169 formats += (*itMenu);
170 Qtformat[(*itMenu)] = (*itText);
171 FDFormatString[(*itText)] = (*itMenu);
172 extension[(*itText)] = (*itExt);
182 static bool checkFileName(QString& fileName, QWidget* widget,
const QString& snapshotFormat)
184 if (fileName.isEmpty())
188 QFileInfo info(fileName);
190 #if QT_VERSION >= 0x040000
191 if (info.suffix().isEmpty())
193 if (info.extension(
false).isEmpty())
197 if (fileName.right(1) !=
".")
199 fileName += extension[snapshotFormat];
200 info.setFile(fileName);
202 #if QT_VERSION >= 0x040000
203 else if (info.suffix() != extension[snapshotFormat])
205 else if (info.extension(
false) != extension[snapshotFormat])
209 #if QT_VERSION >= 0x040000
210 QString modifiedName = info.absolutePath() +
'/' + info.baseName() +
"." + extension[snapshotFormat];
212 # if QT_VERSION >= 0x030000
213 QString modifiedName = info.dirPath() +
'/' + info.baseName(
true) +
'.' + extension[snapshotFormat];
215 QString modifiedName = info.dirPath() +
'/' + info.baseName() +
'.' + extension[snapshotFormat];
218 QFileInfo modifInfo(modifiedName);
219 int i=(QMessageBox::warning(widget,
"Wrong extension",
220 info.fileName()+
" has a wrong extension.\nSave as "+modifInfo.fileName()+
" instead ?",
223 QMessageBox::Cancel));
224 if (i==QMessageBox::Cancel)
227 if (i==QMessageBox::Yes)
229 fileName = modifiedName;
230 info.setFile(fileName);
237 #ifndef NO_VECTORIAL_RENDER
239 void drawVectorial(
void* param)
248 static void showProgressDialog(QGLWidget* parent);
249 static void updateProgress(
float progress,
const QString& stepString);
250 static void hideProgressDialog();
253 static QProgressDialog* progressDialog;
256 QProgressDialog* ProgressDialog::progressDialog = NULL;
258 void ProgressDialog::showProgressDialog(QGLWidget* parent)
260 progressDialog =
new QProgressDialog(parent);
261 #if QT_VERSION >= 0x040000
262 progressDialog->setWindowTitle(
"Image rendering progress");
264 progressDialog->setCaption(
"Image rendering progress");
266 progressDialog->setMinimumSize(300, 40);
267 progressDialog->setCancelButton(NULL);
268 progressDialog->show();
271 void ProgressDialog::updateProgress(
float progress,
const QString& stepString)
273 #if QT_VERSION >= 0x040000
274 progressDialog->setValue(
int(progress*100));
276 progressDialog->setProgress(
int(progress*100));
278 QString message(stepString);
279 if (message.length() > 33)
280 message = message.left(17) +
"..." + message.right(12);
281 progressDialog->setLabelText(message);
282 progressDialog->update();
283 qApp->processEvents();
286 void ProgressDialog::hideProgressDialog()
288 progressDialog->close();
289 delete progressDialog;
290 progressDialog = NULL;
293 #if QT_VERSION >= 0x040000
294 class VRenderInterface:
public QDialog,
public Ui::VRenderInterface
296 public: VRenderInterface(QWidget *parent) : QDialog(parent) { setupUi(
this); }
304 static int saveVectorialSnapshot(
const QString& fileName, QGLWidget* widget,
const QString& snapshotFormat)
306 static VRenderInterface* VRinterface = NULL;
309 #if QT_VERSION >= 0x030000
310 VRinterface =
new VRenderInterface(widget);
312 VRinterface =
new VRenderInterface(widget,
"",
true);
317 if (snapshotFormat ==
"XFIG")
319 VRinterface->tightenBBox->setEnabled(
false);
320 VRinterface->colorBackground->setEnabled(
false);
324 VRinterface->tightenBBox->setEnabled(
true);
325 VRinterface->colorBackground->setEnabled(
true);
328 if (VRinterface->exec() == QDialog::Rejected)
331 vrender::VRenderParams vparams;
332 vparams.setFilename(fileName);
334 if (snapshotFormat ==
"EPS") vparams.setFormat(vrender::VRenderParams::EPS);
335 if (snapshotFormat ==
"PS") vparams.setFormat(vrender::VRenderParams::PS);
336 if (snapshotFormat ==
"XFIG") vparams.setFormat(vrender::VRenderParams::XFIG);
338 vparams.setOption(vrender::VRenderParams::CullHiddenFaces, !(VRinterface->includeHidden->isChecked()));
339 vparams.setOption(vrender::VRenderParams::OptimizeBackFaceCulling, VRinterface->cullBackFaces->isChecked());
340 vparams.setOption(vrender::VRenderParams::RenderBlackAndWhite, VRinterface->blackAndWhite->isChecked());
341 vparams.setOption(vrender::VRenderParams::AddBackground, VRinterface->colorBackground->isChecked());
342 vparams.setOption(vrender::VRenderParams::TightenBoundingBox, VRinterface->tightenBBox->isChecked());
344 #if QT_VERSION >= 0x040000
345 switch (VRinterface->sortMethod->currentIndex())
347 switch (VRinterface->sortMethod->currentItem())
350 case 0: vparams.setSortMethod(vrender::VRenderParams::NoSorting);
break;
351 case 1: vparams.setSortMethod(vrender::VRenderParams::BSPSort);
break;
352 case 2: vparams.setSortMethod(vrender::VRenderParams::TopologicalSort);
break;
353 case 3: vparams.setSortMethod(vrender::VRenderParams::AdvancedTopologicalSort);
break;
355 qWarning(
"VRenderInterface::saveVectorialSnapshot: Unknown SortMethod");
358 vparams.setProgressFunction(&ProgressDialog::updateProgress);
359 ProgressDialog::showProgressDialog(widget);
360 widget->makeCurrent();
362 vrender::VectorialRender(drawVectorial, (
void*) widget, vparams);
363 ProgressDialog::hideProgressDialog();
364 #if QT_VERSION < 0x030000
365 widget->setCursor(Qt::arrowCursor);
367 widget->setCursor(QCursor(Qt::ArrowCursor));
373 #endif // NO_VECTORIAL_RENDER
376 #if QT_VERSION >= 0x040000
377 class ImageInterface:
public QDialog,
public Ui::ImageInterface
379 public: ImageInterface(QWidget *parent) : QDialog(parent) { setupUi(
this); }
386 bool QGLViewer::saveImageSnapshot(
const QString& fileName)
388 static ImageInterface* imageInterface = NULL;
391 #if QT_VERSION >= 0x030000
392 imageInterface =
new ImageInterface(
this);
394 imageInterface =
new ImageInterface(
this,
"",
true);
398 if ((imageInterface->imgWidth->value() == 1) && (imageInterface->imgHeight->value() == 1))
400 imageInterface->imgWidth->setValue(width());
401 imageInterface->imgHeight->setValue(height());
404 imageInterface->imgQuality->setValue(snapshotQuality());
406 if (imageInterface->exec() == QDialog::Rejected)
410 qApp->processEvents();
412 setSnapshotQuality(imageInterface->imgQuality->value());
414 QColor previousBGColor = backgroundColor();
415 if (imageInterface->whiteBackground->isChecked())
416 setBackgroundColor(Qt::white);
418 QSize finalSize(imageInterface->imgWidth->value(), imageInterface->imgHeight->value());
420 double oversampling = imageInterface->oversampling->value();
421 QSize subSize(
int(this->width()/oversampling),
int(this->height()/oversampling));
423 double aspectRatio = width() /
static_cast<double>(height());
424 double newAspectRatio = finalSize.width() /
static_cast<double>(finalSize.height());
426 double zNear = camera()->zNear();
427 double zFar = camera()->zFar();
430 bool expand = imageInterface->expandFrustum->isChecked();
431 if (camera()->type() == qglviewer::Camera::PERSPECTIVE)
432 if ((expand && (newAspectRatio>aspectRatio)) || (!expand && (newAspectRatio<aspectRatio)))
434 yMin = zNear * tan(camera()->fieldOfView() / 2.0);
435 xMin = newAspectRatio * yMin;
439 xMin = zNear * tan(camera()->fieldOfView() / 2.0) * aspectRatio;
440 yMin = xMin / newAspectRatio;
444 camera()->getOrthoWidthHeight(xMin, yMin);
445 if ((expand && (newAspectRatio>aspectRatio)) || (!expand && (newAspectRatio<aspectRatio)))
446 xMin = newAspectRatio * yMin;
448 yMin = xMin / newAspectRatio;
451 #if QT_VERSION >= 0x040000
452 QImage image(finalSize.width(), finalSize.height(), QImage::Format_ARGB32);
454 QImage image(finalSize.width(), finalSize.height(), 32);
459 QMessageBox::warning(
this,
"Image saving error",
460 "Unable to create resulting image",
461 QMessageBox::Ok, QMessageBox::NoButton);
468 double scaleX = subSize.width() /
static_cast<double>(finalSize.width());
469 double scaleY = subSize.height() /
static_cast<double>(finalSize.height());
471 double deltaX = 2.0 * xMin * scaleX;
472 double deltaY = 2.0 * yMin * scaleY;
474 int nbX = finalSize.width() / subSize.width();
475 int nbY = finalSize.height() / subSize.height();
478 if (nbX * subSize.width() < finalSize.width())
480 if (nbY * subSize.height() < finalSize.height())
487 tileRegion_ =
new TileRegion();
488 double tileXMin, tileWidth, tileYMin, tileHeight;
489 if ((expand && (newAspectRatio>aspectRatio)) || (!expand && (newAspectRatio<aspectRatio)))
491 double tileTotalWidth = newAspectRatio * height();
492 tileXMin = (width() - tileTotalWidth) / 2.0;
493 tileWidth = tileTotalWidth * scaleX;
495 tileHeight = height() * scaleY;
496 tileRegion_->textScale = 1.0 / scaleY;
500 double tileTotalHeight = width() / newAspectRatio;
501 tileYMin = (height() - tileTotalHeight) / 2.0;
502 tileHeight = tileTotalHeight * scaleY;
504 tileWidth = width() * scaleX;
505 tileRegion_->textScale = 1.0 / scaleX;
509 for (
int i=0; i<nbX; i++)
510 for (
int j=0; j<nbY; j++)
515 glMatrixMode(GL_PROJECTION);
517 if (camera()->type() == qglviewer::Camera::PERSPECTIVE)
518 glFrustum(-xMin + i*deltaX, -xMin + (i+1)*deltaX, yMin - (j+1)*deltaY, yMin - j*deltaY, zNear, zFar);
520 glOrtho(-xMin + i*deltaX, -xMin + (i+1)*deltaX, yMin - (j+1)*deltaY, yMin - j*deltaY, zNear, zFar);
521 glMatrixMode(GL_MODELVIEW);
523 tileRegion_->xMin = tileXMin + i * tileWidth;
524 tileRegion_->xMax = tileXMin + (i+1) * tileWidth;
525 tileRegion_->yMin = tileYMin + j * tileHeight;
526 tileRegion_->yMax = tileYMin + (j+1) * tileHeight;
534 QImage snapshot = grabFrameBuffer(
true);
541 #if QT_VERSION >= 0x040000
542 QImage subImage = snapshot.scaled(subSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
544 # if QT_VERSION >= 0x030000
545 QImage subImage = snapshot.scale(subSize, QImage::ScaleFree);
547 QImage subImage = snapshot.smoothScale(subSize.width(), subSize.height());
552 for (
int ii=0; ii<subSize.width(); ii++)
554 int fi = i*subSize.width() + ii;
555 if (fi == image.width())
557 for (
int jj=0; jj<subSize.height(); jj++)
559 int fj = j*subSize.height() + jj;
560 if (fj == image.height())
562 image.setPixel(fi, fj, subImage.pixel(ii,jj));
568 #if QT_VERSION >= 0x040000
569 bool saveOK = image.save(fileName, snapshotFormat().toLatin1().constData(), snapshotQuality());
571 bool saveOK = image.save(fileName, snapshotFormat(), snapshotQuality());
585 if (imageInterface->whiteBackground->isChecked())
586 setBackgroundColor(previousBGColor);
644 if (snapshotFileName().isEmpty() || !automatic)
647 #if QT_VERSION < 0x030000
648 if (openSnapshotFormatDialog())
649 fileName = QFileDialog::getSaveFileName(snapshotFileName(), FDFormatString[snapshotFormat()]+
";;All files (*.*)",
this,
"Save dialog");
653 QString selectedFormat = FDFormatString[snapshotFormat()];
654 # if QT_VERSION >= 0x040000
655 fileName = QFileDialog::getSaveFileName(
this,
"Choose a file name to save under", snapshotFileName(), formats, &selectedFormat,
656 overwrite?QFileDialog::DontConfirmOverwrite:QFlag(0));
658 fileName = QFileDialog::getSaveFileName(snapshotFileName(), formats,
this,
659 "Save Snapshot dialog",
"Choose a file name to save under", &selectedFormat);
661 setSnapshotFormat(Qtformat[selectedFormat]);
664 if (checkFileName(fileName,
this, snapshotFormat()))
665 setSnapshotFileName(fileName);
670 QFileInfo fileInfo(snapshotFileName());
672 if ((automatic) && (snapshotCounter() >= 0))
675 const QString baseName = fileInfo.baseName();
677 count.sprintf(
"%.04d", snapshotCounter_++);
679 #if QT_VERSION >= 0x040000
680 suffix = fileInfo.suffix();
681 if (suffix.isEmpty())
682 suffix = extension[snapshotFormat()];
683 fileInfo.setFile(fileInfo.absolutePath()+
'/' + baseName +
'-' + count +
'.' + suffix);
685 suffix = fileInfo.extension();
686 if (suffix.isEmpty())
687 suffix = extension[snapshotFormat()];
688 fileInfo.setFile(fileInfo.dirPath()+
'/' + baseName +
'-' + count +
'.' + suffix);
692 while (fileInfo.exists())
694 count.sprintf(
"%.04d", snapshotCounter_++);
695 #if QT_VERSION >= 0x040000
696 fileInfo.setFile(fileInfo.absolutePath() +
'/' +baseName +
'-' + count +
'.' + fileInfo.suffix());
698 fileInfo.setFile(fileInfo.dirPath() +
'/' + baseName +
'-' + count +
'.' + fileInfo.extension());
703 #if QT_VERSION < 0x040000
704 if ((fileInfo.exists()) && (!overwrite) &&
705 (QMessageBox::warning(
this,
"Overwrite file ?",
706 "File "+fileInfo.fileName()+
" already exists.\nOverwrite ?",
708 QMessageBox::Cancel) == QMessageBox::Cancel))
713 #ifndef NO_VECTORIAL_RENDER
714 if ( (snapshotFormat() ==
"EPS") || (snapshotFormat() ==
"PS") || (snapshotFormat() ==
"XFIG") )
716 saveOK = (saveVectorialSnapshot(fileInfo.filePath(),
this, snapshotFormat()) <= 0);
721 QImage snapshot = frameBufferSnapshot();
722 #if QT_VERSION >= 0x040000
723 saveOK = snapshot.save(fileInfo.filePath(), snapshotFormat().toLatin1().constData(), snapshotQuality());
725 saveOK = snapshot.save(fileInfo.filePath(), snapshotFormat(), snapshotQuality());
729 saveOK = saveImageSnapshot(fileInfo.filePath());
732 QMessageBox::warning(
this,
"Snapshot problem",
"Unable to save snapshot in\n"+fileInfo.filePath());
735 QImage QGLViewer::frameBufferSnapshot()
744 return grabFrameBuffer(
true);
760 const QString previousName = snapshotFileName();
761 const int previousCounter = snapshotCounter();
762 setSnapshotFileName(fileName);
763 setSnapshotCounter(-1);
764 saveSnapshot(
true, overwrite);
765 setSnapshotFileName(previousName);
766 setSnapshotCounter(previousCounter);
775 QClipboard *cb = QApplication::clipboard();
776 cb->setImage(frameBufferSnapshot());
779 #if QT_VERSION < 0x030000
782 QImage QGLViewer::grabFrameBuffer(
bool withAlpha)
790 res = QImage(w, h, 32);
791 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, res.bits());
792 if (QImage::systemByteOrder() == QImage::BigEndian)
795 uint *p = (uint*)res.bits();
797 if (withAlpha && format().alpha())
817 res.setAlphaBuffer(withAlpha && format().alpha());
821 #if defined (Q_WS_WIN)
822 res = QImage(w, h, 8);
823 glReadPixels(0, 0, w, h, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, res.bits());
838 #endif // QT_VERSION < 0x030000