More screenshot tweaks, send blob to remote
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
be0ae63541
commit
a2b917c163
3 changed files with 63 additions and 18 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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…
Add table
Add a link
Reference in a new issue