Browse Source

More screenshot tweaks, send blob to remote

Signed-off-by: falkTX <falktx@falktx.com>
tags/22.02
falkTX 3 years ago
parent
commit
a2b917c163
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 63 additions and 18 deletions
  1. +6
    -4
      src/CardinalPlugin.cpp
  2. +8
    -1
      src/override/Scene.cpp
  3. +49
    -13
      src/override/Window.cpp

+ 6
- 4
src/CardinalPlugin.cpp View File

@@ -34,9 +34,11 @@
# undef DEBUG
#endif
#if defined(HAVE_LIBLO) && defined(HEADLESS)
# include <lo/lo.h>
# include "extra/Thread.hpp"
#ifdef HAVE_LIBLO
# ifdef HEADLESS
# include <lo/lo.h>
# include "extra/Thread.hpp"
# endif
# include "CardinalCommon.hpp"
#endif
@@ -815,7 +817,7 @@ protected:
if (std::strcmp(key, "screenshot") == 0)
{
fStateScreenshot = value;
#if defined(HAVE_LIBLO) && defined(HEADLESS)
#if defined(HAVE_LIBLO) && !defined(HEADLESS)
patchUtils::sendScreenshotToRemote(value);
#endif
return;


+ 8
- 1
src/override/Scene.cpp View File

@@ -51,6 +51,7 @@
#endif

#include "../CardinalCommon.hpp"
#include "extra/Base64.hpp"
#include "DistrhoUtils.hpp"


@@ -549,7 +550,13 @@ void sendScreenshotToRemote(const char* const screenshot) {
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);

lo_send(addr, "/screenshot", "s", screenshot);
std::vector<uint8_t> data(d_getChunkFromBase64String(screenshot));

if (const lo_blob blob = lo_blob_new(data.size(), data.data())) {
lo_send(addr, "/screenshot", "b", blob);
lo_blob_free(blob);
}

lo_address_free(addr);
#endif
}


+ 49
- 13
src/override/Window.cpp View File

@@ -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;


Loading…
Cancel
Save