Thu, 23 Feb 2017 23:29:16 +0200
Turned GLRenderer::pixelCapture to GLRenderer::screenCapture() which encapsulates screen capturing properly and returns a ready image.
--- a/src/glrenderer.cpp Thu Feb 23 23:17:10 2017 +0200 +++ b/src/glrenderer.cpp Thu Feb 23 23:29:16 2017 +0200 @@ -805,17 +805,21 @@ m_objectAtCursor = nullptr; } -// ============================================================================= -// -QByteArray GLRenderer::capturePixels() +/* + * Returns an image containing the current render of the scene. + */ +QImage GLRenderer::screenCapture() { - QByteArray result; - result.resize (4 * width() * height()); - m_takingScreenCapture = true; - update(); // Smile! - m_takingScreenCapture = false; - glReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, result.data()); - return result; + // Read the current render to a buffer of pixels. We use RGBA format even though the image should be fully opaque at all times. + // This is because apparently GL_RGBA/GL_UNSIGNED_BYTE is the only setting pair that is guaranteed to actually work! + // ref: https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glReadPixels.xml + QByteArray pixelData; + pixelData.resize(4 * width() * height()); + glReadPixels(0, 0, width(), height(), GL_RGBA, GL_UNSIGNED_BYTE, pixelData.data()); + + // Prepare the image and return it. It appears that GL and Qt formats have red and blue swapped and the Y axis flipped. + QImage image {reinterpret_cast<const uchar*>(pixelData.constData()), width(), height(), QImage::Format_ARGB32}; + return image.rgbSwapped().mirrored(); } /*
--- a/src/glrenderer.h Thu Feb 23 23:17:10 2017 +0200 +++ b/src/glrenderer.h Thu Feb 23 23:29:16 2017 +0200 @@ -78,7 +78,6 @@ ~GLRenderer(); Camera camera() const; - QByteArray capturePixels(); GLCamera& currentCamera(); const GLCamera& currentCamera() const; Qt::KeyboardModifiers keyboardModifiers() const; @@ -90,6 +89,7 @@ LDObject* pick(int mouseX, int mouseY); void resetAllAngles(); void resetAngles(); + QImage screenCapture(); void setBackground(); void setCamera(Camera cam); QPen textPen() const; @@ -145,7 +145,6 @@ QGenericMatrix<4, 4, GLfloat> m_rotationMatrix; GLCamera m_cameras[7]; bool m_useDarkBackground = false; - bool m_takingScreenCapture = false; bool m_panning = false; bool m_initialized = false; bool m_isDrawingSelectionScene = false;
--- a/src/toolsets/viewtoolset.cpp Thu Feb 23 23:17:10 2017 +0200 +++ b/src/toolsets/viewtoolset.cpp Thu Feb 23 23:29:16 2017 +0200 @@ -104,21 +104,16 @@ void ViewToolset::screenshot() { - const char* imageformats = "PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;" - "PPM images (*.ppm);;X11 Bitmaps (*.xbm);;X11 Pixmaps (*.xpm);;All Files (*.*)"; - int width = m_window->renderer()->width(); - int height = m_window->renderer()->height(); - QByteArray capture = m_window->renderer()->capturePixels(); - const uchar* imagedata = reinterpret_cast<const uchar*> (capture.constData()); - // GL and Qt formats have R and B swapped. Also, GL flips Y - correct it as well. - QImage image = QImage (imagedata, width, height, QImage::Format_ARGB32).rgbSwapped().mirrored(); + const char* imageFormats = "PNG images (*.png);;JPG images (*.jpg);;BMP images (*.bmp);;" + "PPM images (*.ppm);;X11 Bitmaps (*.xbm);;X11 Pixmaps (*.xpm);;All Files (*.*)"; + QImage image = m_window->renderer()->screenCapture(); QString root = Basename (currentDocument()->name()); if (root.right (4) == ".dat") root.chop (4); QString defaultname = (not root.isEmpty()) ? format ("%1.png", root) : ""; - QString filename = QFileDialog::getSaveFileName (m_window, "Save Screencap", defaultname, imageformats); + QString filename = QFileDialog::getSaveFileName (m_window, "Save Screencap", defaultname, imageFormats); if (not filename.isEmpty() and not image.save (filename)) {