Implement GIF support [read more]

So, it works. Yay! Only one frame though. What could be the issue? Hrm. I'll look around. And open an issue in ginsweater/gif-h to try and work it out.

I am amazed.
This commit is contained in:
ArsenArsen 2017-06-06 12:51:16 +02:00
parent 6e36691f6c
commit c523af9927
4 changed files with 34 additions and 18 deletions

View File

@ -16,7 +16,7 @@ RecordingController::RecordingController() : timer(this) {
} }
bool RecordingController::isRunning() { bool RecordingController::isRunning() {
return timer.isActive(); return preview;
} }
bool RecordingController::start(RecordingContext *context) { bool RecordingController::start(RecordingContext *context) {
@ -31,12 +31,17 @@ bool RecordingController::start(RecordingContext *context) {
bool RecordingController::end() { bool RecordingController::end() {
if (!isRunning()) return false; if (!isRunning()) return false;
area = QRect(); area = QRect();
preview->close(); if (preview) {
preview->close();
preview->deleteLater();
}
preview = 0; preview = 0;
WorkerContext *c = new WorkerContext; WorkerContext *c = new WorkerContext;
c->consumer = [&](QImage) { queue(_context->finalizer()); }; c->consumer = [&](QImage) { queue(_context->finalizer()); };
c->targetFormat = QImage::Format_Alpha8; c->targetFormat = QImage::Format_Alpha8;
c->pixmap = QPixmap(0, 0); c->pixmap = QPixmap(0, 0);
Worker::queue(c);
frame = 0; frame = 0;
time = 0; time = 0;
@ -51,11 +56,15 @@ void RecordingController::queue(QByteArray arr) {
void RecordingController::timeout() { void RecordingController::timeout() {
if (isRunning()) { if (isRunning()) {
if (!_context->validator()) { if (!_context->validator()) {
preview->close(); if (preview) {
preview->close();
preview->deleteLater();
}
frame = 0; frame = 0;
time = 0; time = 0;
preview = 0; preview = 0;
area = QRect(); area = QRect();
return;
} }
time++; time++;
int localTime = time * timer.interval() - 3000; int localTime = time * timer.interval() - 3000;
@ -73,10 +82,11 @@ void RecordingController::timeout() {
} }
long second = localTime / 1000 % 60; long second = localTime / 1000 % 60;
long minute = localTime / 60000; long minute = localTime / 60000;
preview->setTime(QString("%1:%2").arg(QString::number(minute)).arg(QString::number(second)), frame); if (isRunning())
preview->setTime(QString("%1:%2").arg(QString::number(minute)).arg(QString::number(second)), frame);
} else { } else {
QMutexLocker l(&lock); QMutexLocker l(&lock);
UploaderSingleton::inst().upload(uploadQueue.dequeue()); if (!uploadQueue.isEmpty()) UploaderSingleton::inst().upload(uploadQueue.dequeue());
} }
} }

View File

@ -6,6 +6,7 @@
#include <QFile> #include <QFile>
#include <QImage> #include <QImage>
#include <QMutex> #include <QMutex>
#include <QQueue>
#include <QRect> #include <QRect>
#include <QTimer> #include <QTimer>
#include <functional> #include <functional>

View File

@ -2,6 +2,7 @@
#include <QBuffer> #include <QBuffer>
#include <QDateTime> #include <QDateTime>
#include <QDebug>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QStandardPaths> #include <QStandardPaths>
@ -10,6 +11,7 @@
#include <platformbackend.hpp> #include <platformbackend.hpp>
#include <settings.hpp> #include <settings.hpp>
#include <time.h> #include <time.h>
#include <unistd.h>
RecordingFormats::RecordingFormats(RecordingFormats::Format f) { RecordingFormats::RecordingFormats(RecordingFormats::Format f) {
QString path = QStandardPaths::writableLocation(QStandardPaths::TempLocation); QString path = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
@ -25,24 +27,27 @@ RecordingFormats::RecordingFormats(RecordingFormats::Format f) {
tmpDir.cd(name); tmpDir.cd(name);
switch (f) { switch (f) {
case GIF: { case GIF: {
iFormat = QImage::Format_Alpha8; iFormat = QImage::Format_RGBA8888;
validator = [] { return true; }; validator = [] { return true; };
consumer = [&](QImage img) { frames.push_back(img); }; consumer = [&](QImage img) { frames.push_back(img); };
finalizer = [&] { finalizer = [&] {
if (frames.size() == 0) return QByteArray; if (frames.size() == 0) return QByteArray();
int f = 1;
uint32_t d = 1000 / settings::settings().value("recording/framerate", 30).toInt(); uint32_t d = 1000 / settings::settings().value("recording/framerate", 30).toInt();
QImage startImg = frames[0]; QImage &startImg = frames[0];
GifWriter writer; GifWriter writer;
GifBegin(&writer, tmpDir.absoluteFilePath("resulting.gif"), startImg.width(), startImg.height(), d) GifBegin(&writer, tmpDir.absoluteFilePath("resulting.gif").toLocal8Bit().constData(), startImg.width(),
startImg.height(), d);
for (QImage &a : frames){ GifWriteFrame(writer, a.bits(), a.width(), a.height(), d) } QFile res( int i = 0;
tmpDir.absoluteFilePath("resulting.gif")); for (QImage &a : frames) {
QByteArray alpha8((char *)a.bits(), a.byteCount());
GifWriteFrame(&writer, (uint8_t *)alpha8.data(), a.width(), a.height(), d);
}
GifEnd(&writer);
QFile res(tmpDir.absoluteFilePath("resulting.gif"));
if (!res.open(QFile::ReadOnly)) { if (!res.open(QFile::ReadOnly)) {
return QByteArray; return QByteArray();
} }
QByteArray data = res.readAll(); QByteArray data = res.readAll();
tmpDir.removeRecursively();
return data; return data;
}; };
break; break;

View File

@ -11,7 +11,6 @@ RecordingPreview::RecordingPreview(QRect area, QWidget *parent) : QWidget(parent
recordingArea = area; recordingArea = area;
setStyleSheet("background-color: rgba(0, 0, 0, 0.7);"); setStyleSheet("background-color: rgba(0, 0, 0, 0.7);");
setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_DeleteOnClose);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setWindowFlags(windowFlags() | Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); setWindowFlags(windowFlags() | Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
QTimer::singleShot(0, [&] { QTimer::singleShot(0, [&] {
@ -45,6 +44,7 @@ void RecordingPreview::setPixmap(QPixmap map) {
label->setPixmap(map); label->setPixmap(map);
} }
void RecordingPreview::setTime(QString time, int frame) { void RecordingPreview::setTime(QString time, int frame) {
hintLabel->setText(QString("Time: ") + time + "\nFrame: " + QString::number(frame) if (isVisible())
+ "\nStop key: " + hotkeying::sequence("recordingstop")); hintLabel->setText(QString("Time: ") + time + "\nFrame: " + QString::number(frame)
+ "\nStop key: " + hotkeying::sequence("recordingstop"));
} }