mrmBot-Matrix/natives/speed.cc

102 lines
2.9 KiB
C++
Raw Normal View History

2022-12-12 18:13:03 +00:00
#include <iostream>
#include <map>
2022-04-30 21:41:44 +00:00
#include <vips/vips8>
2020-07-22 18:12:38 +00:00
#include "common.h"
2020-07-22 18:12:38 +00:00
using namespace std;
2022-04-30 21:41:44 +00:00
using namespace vips;
2020-07-22 18:12:38 +00:00
void *memset16(void *m, uint16_t val, size_t count) {
uint16_t *buf = (uint16_t *)m;
while (count--) *buf++ = val;
return m;
}
2022-12-12 18:13:03 +00:00
char *vipsRemove(char *data, size_t length, size_t *DataSize, int speed) {
2022-04-30 21:41:44 +00:00
VOption *options = VImage::option()->set("access", "sequential");
2022-12-12 18:13:03 +00:00
VImage in = VImage::new_from_buffer(data, length, "", options->set("n", -1))
2022-04-30 21:41:44 +00:00
.colourspace(VIPS_INTERPRETATION_sRGB);
if (!in.has_alpha()) in = in.bandjoin(255);
2022-04-30 21:41:44 +00:00
int width = in.width();
2022-06-20 06:05:06 +00:00
int pageHeight = vips_image_get_page_height(in.get_image());
int nPages = vips_image_get_n_pages(in.get_image());
2022-04-30 21:41:44 +00:00
vector<VImage> img;
for (int i = 0; i < nPages; i += speed) {
2022-06-20 06:05:06 +00:00
VImage img_frame = in.crop(0, i * pageHeight, width, pageHeight);
2022-04-30 21:41:44 +00:00
img.push_back(img_frame);
}
VImage out = VImage::arrayjoin(img, VImage::option()->set("across", 1));
2022-06-20 06:05:06 +00:00
out.set(VIPS_META_PAGE_HEIGHT, pageHeight);
2022-04-30 21:41:44 +00:00
void *buf;
2022-12-12 18:13:03 +00:00
out.write_to_buffer(".gif", &buf, DataSize);
2022-04-30 21:41:44 +00:00
2022-12-12 18:13:03 +00:00
return (char *)buf;
2022-04-30 21:41:44 +00:00
}
2022-12-28 06:20:17 +00:00
char *Speed(string *type, char *BufferData, size_t BufferLength,
2022-12-12 18:13:03 +00:00
ArgumentMap Arguments, size_t *DataSize) {
bool slow = GetArgumentWithFallback<bool>(Arguments, "slow", false);
int speed = GetArgumentWithFallback<int>(Arguments, "speed", 2);
char *fileData = (char *)malloc(BufferLength);
memcpy(fileData, BufferData, BufferLength);
char *match = (char *)"\x00\x21\xF9\x04";
vector<uint16_t> old_delays;
bool removeFrames = false;
char *lastPos;
int amount = 0;
lastPos = (char *)memchr(fileData, '\x00', BufferLength);
while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) {
lastPos = (char *)memchr(lastPos + 1, '\x00',
2022-12-12 18:13:03 +00:00
(BufferLength - (lastPos - fileData)) - 1);
continue;
}
2022-12-12 18:13:03 +00:00
++amount;
uint16_t old_delay;
memcpy(&old_delay, lastPos + 5, 2);
old_delays.push_back(old_delay);
lastPos = (char *)memchr(lastPos + 1, '\x00',
(BufferLength - (lastPos - fileData)) - 1);
}
2020-07-22 18:12:38 +00:00
2022-12-12 18:13:03 +00:00
int currentFrame = 0;
lastPos = (char *)memchr(fileData, '\x00', BufferLength);
while (lastPos != NULL) {
if (memcmp(lastPos, match, 4) != 0) {
lastPos = (char *)memchr(lastPos + 1, '\x00',
2022-12-12 18:13:03 +00:00
(BufferLength - (lastPos - fileData)) - 1);
continue;
}
uint16_t new_delay = slow ? old_delays[currentFrame] * speed
: old_delays[currentFrame] / speed;
if (!slow && new_delay <= 1) {
removeFrames = true;
break;
}
2020-07-22 18:12:38 +00:00
2022-12-12 18:13:03 +00:00
memset16(lastPos + 5, new_delay, 1);
2022-12-12 18:13:03 +00:00
lastPos = (char *)memchr(lastPos + 1, '\x00',
(BufferLength - (lastPos - fileData)) - 1);
++currentFrame;
}
2022-12-12 18:13:03 +00:00
if (removeFrames) {
fileData = vipsRemove(BufferData, BufferLength, DataSize, speed);
} else {
*DataSize = BufferLength;
}
2022-06-28 03:50:53 +00:00
2022-12-12 18:13:03 +00:00
return fileData;
2022-04-30 21:41:44 +00:00
}