|
|
@@ -362,24 +362,55 @@ void Window::run() { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void Window__flipBitmap(uint8_t* pixels, int width, int height, int depth) { |
|
|
|
static void Window__flipBitmap(uint8_t* pixels, const int width, const int height, const int depth) { |
|
|
|
for (int y = 0; y < height / 2; y++) { |
|
|
|
const int flipY = height - y - 1; |
|
|
|
uint8_t tmp[width * depth]; |
|
|
|
std::memcpy(tmp, &pixels[y * width * depth], width * depth); |
|
|
|
std::memcpy(&pixels[y * width * depth], &pixels[flipY * width * depth], width * depth); |
|
|
|
std::memmove(&pixels[y * width * depth], &pixels[flipY * width * depth], width * depth); |
|
|
|
std::memcpy(&pixels[flipY * width * depth], tmp, width * depth); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef STBI_WRITE_NO_STDIO |
|
|
|
static void Window__downscaleBitmap(uint8_t* pixels, int& width, int& height) { |
|
|
|
int targetWidth = width; |
|
|
|
int targetHeight = height; |
|
|
|
double scale = 1.0; |
|
|
|
|
|
|
|
if (targetWidth > 300) { |
|
|
|
scale = width / 300.0; |
|
|
|
targetWidth = 300; |
|
|
|
targetHeight = height / scale; |
|
|
|
} |
|
|
|
if (targetHeight > 200) { |
|
|
|
scale = height / 200.0; |
|
|
|
targetHeight = 200; |
|
|
|
targetWidth = width / scale; |
|
|
|
} |
|
|
|
DISTRHO_SAFE_ASSERT_INT_RETURN(targetWidth <= 300, targetWidth,); |
|
|
|
DISTRHO_SAFE_ASSERT_INT_RETURN(targetHeight <= 200, targetHeight,); |
|
|
|
|
|
|
|
// FIXME worst possible quality :/ |
|
|
|
for (int y = 0; y < targetHeight; ++y) { |
|
|
|
const int ys = static_cast<int>(y * scale); |
|
|
|
for (int x = 0; x < targetWidth; ++x) { |
|
|
|
const int xs = static_cast<int>(x * scale); |
|
|
|
std::memmove(pixels + (width * y + x) * 3, pixels + (width * ys + xs) * 3, 3); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
width = targetWidth; |
|
|
|
height = targetHeight; |
|
|
|
} |
|
|
|
|
|
|
|
static void Window__writeImagePNG(void* context, void* data, int size) { |
|
|
|
USE_NAMESPACE_DISTRHO |
|
|
|
UI* const ui = static_cast<UI*>(context); |
|
|
|
String encodedPNG("data:image/png;base64,"); |
|
|
|
encodedPNG += String::asBase64(data, size); |
|
|
|
ui->setState("screenshot", encodedPNG.buffer()); |
|
|
|
ui->setState("screenshot", String::asBase64(data, size).buffer()); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
void Window::step() { |
|
|
@@ -470,28 +501,33 @@ void Window::step() { |
|
|
|
++internal->generateScreenshotStep; |
|
|
|
|
|
|
|
int y = 0; |
|
|
|
#ifndef CARDINAL_TRANSPARENT_SCREENSHOTS |
|
|
|
#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS |
|
|
|
constexpr const int depth = 4; |
|
|
|
#else |
|
|
|
y = APP->scene->menuBar->box.size.y * newPixelRatio; |
|
|
|
constexpr const int depth = 3; |
|
|
|
#endif |
|
|
|
|
|
|
|
// Allocate pixel color buffer |
|
|
|
uint8_t* const pixels = new uint8_t[winHeight * winWidth * 4]; |
|
|
|
uint8_t* const pixels = new uint8_t[winHeight * winWidth * depth]; |
|
|
|
|
|
|
|
// glReadPixels defaults to GL_BACK, but the back-buffer is unstable, so use the front buffer (what the user sees) |
|
|
|
glReadBuffer(GL_FRONT); |
|
|
|
glReadPixels(0, 0, winWidth, winHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
|
|
|
glReadPixels(0, 0, winWidth, winHeight, depth == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
|
|
|
|
|
|
|
if (internal->generateScreenshotStep == kScreenshotStepSaving) |
|
|
|
{ |
|
|
|
// Write pixels to PNG |
|
|
|
const int stride = winWidth * 4; |
|
|
|
const uint8_t* const pixelsWithOffset = pixels + (stride * y); |
|
|
|
Window__flipBitmap(pixels, winWidth, winHeight, 4); |
|
|
|
const int stride = winWidth * depth; |
|
|
|
uint8_t* const pixelsWithOffset = pixels + (stride * y); |
|
|
|
Window__flipBitmap(pixels, winWidth, winHeight, depth); |
|
|
|
winHeight -= y; |
|
|
|
#ifdef STBI_WRITE_NO_STDIO |
|
|
|
Window__downscaleBitmap(pixelsWithOffset, winWidth, winHeight); |
|
|
|
stbi_write_png_to_func(Window__writeImagePNG, internal->ui, |
|
|
|
winWidth, winHeight - y, 4, pixelsWithOffset, stride); |
|
|
|
winWidth, winHeight, depth, pixelsWithOffset, stride); |
|
|
|
#else |
|
|
|
stbi_write_png("screenshot.png", winWidth, winHeight - y, 4, pixelsWithOffset, stride); |
|
|
|
stbi_write_png("screenshot.png", winWidth, winHeight, depth, pixelsWithOffset, stride); |
|
|
|
#endif |
|
|
|
|
|
|
|
internal->generateScreenshotStep = kScreenshotStepNone; |
|
|
|