#include "led-matrix.h"
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <exception>
#include <Magick++.h>
#include <magick/image.h>
using rgb_matrix::Canvas;
using rgb_matrix::RGBMatrix;
using rgb_matrix::FrameCanvas;
volatile bool interrupt_received = false;
static void InterruptHandler(int signo) {
interrupt_received = true;
}
using ImageVector = std::vector<Magick::Image>;
static ImageVector LoadImageAndScaleImage(const char *filename,
int target_width,
int target_height) {
ImageVector result;
ImageVector frames;
try {
readImages(&frames, filename);
} catch (std::exception &e) {
if (e.what())
fprintf(stderr, "%s\n", e.what());
return result;
}
if (frames.empty()) {
fprintf(stderr, "No image found.");
return result;
}
if (frames.size() > 1) {
Magick::coalesceImages(&result, frames.begin(), frames.end());
} else {
result.push_back(frames[0]); }
for (Magick::Image &image : result) {
image.scale(Magick::Geometry(target_width, target_height));
}
return result;
}
void CopyImageToCanvas(const Magick::Image &image, Canvas *canvas) {
const int offset_x = 0, offset_y = 0; for (size_t y = 0; y < image.rows(); ++y) {
for (size_t x = 0; x < image.columns(); ++x) {
const Magick::Color &c = image.pixelColor(x, y);
if (c.alphaQuantum() < 256) {
canvas->SetPixel(x + offset_x, y + offset_y,
ScaleQuantumToChar(c.redQuantum()),
ScaleQuantumToChar(c.greenQuantum()),
ScaleQuantumToChar(c.blueQuantum()));
}
}
}
}
void ShowAnimatedImage(const ImageVector &images, RGBMatrix *matrix) {
FrameCanvas *offscreen_canvas = matrix->CreateFrameCanvas();
while (!interrupt_received) {
for (const auto &image : images) {
if (interrupt_received) break;
CopyImageToCanvas(image, offscreen_canvas);
offscreen_canvas = matrix->SwapOnVSync(offscreen_canvas);
usleep(image.animationDelay() * 10000); }
}
}
int usage(const char *progname) {
fprintf(stderr, "Usage: %s [led-matrix-options] <image-filename>\n",
progname);
rgb_matrix::PrintMatrixFlags(stderr);
return 1;
}
int main(int argc, char *argv[]) {
Magick::InitializeMagick(*argv);
RGBMatrix::Options matrix_options;
rgb_matrix::RuntimeOptions runtime_opt;
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
&matrix_options, &runtime_opt)) {
return usage(argv[0]);
}
if (argc != 2)
return usage(argv[0]);
const char *filename = argv[1];
signal(SIGTERM, InterruptHandler);
signal(SIGINT, InterruptHandler);
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
if (matrix == NULL)
return 1;
ImageVector images = LoadImageAndScaleImage(filename,
matrix->width(),
matrix->height());
switch (images.size()) {
case 0: break;
case 1: CopyImageToCanvas(images[0], matrix);
while (!interrupt_received) sleep(1000); break;
default: ShowAnimatedImage(images, matrix);
break;
}
matrix->Clear();
delete matrix;
return 0;
}