Just use ffmpeg

This commit is contained in:
Dane Johnson 2024-10-21 10:51:41 -05:00
parent 51c3aaa092
commit 6d6d1eec18
5 changed files with 17 additions and 109 deletions

View File

@ -1,5 +0,0 @@
(define-module (cgif)
#:use-module (cgif config)
#:export (make-gif))
(load-extension (in-vicinity installdir "libguilecgif") "init_cgif")

View File

@ -1,14 +0,0 @@
INSTALL = $(PWD)
CFLAGS = `pkg-config --cflags guile-cairo cgif`
LIBS = `pkg-config --libs guile-cairo cgif`
all: libguilecgif.so config.scm
libguilecgif.so: guile-cgif.c
$(CC) $(CFLAGS) -shared -fPIC -o $@ $^ $(LIBS)
config.scm: config.scm.in
sed 's|INSTALLDIR|$(INSTALL)|' < $< > $@
clean:
rm -rf libguilecgif.so config.scm

View File

@ -1,4 +0,0 @@
(define-module (cgif config)
#:export (installdir))
(define installdir "INSTALLDIR")

View File

@ -1,80 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <guile-cairo.h>
#include <cgif.h>
const uint8_t PALETTE[] = {
0xFF, 0xFF, 0xFF, // WHITE
0x00, 0x00, 0x00, // BLACK
0xFF, 0x00, 0x00 // RED
};
#define CAIRO_RED 0x00FF0000
#define CAIRO_BLACK 0x00000000
void encode_frame(cairo_surface_t *surface, CGIF_FrameConfig *frameconfig) {
// TODO pull colors from cairo
size_t size = cairo_image_surface_get_width(surface) * cairo_image_surface_get_height(surface);
frameconfig->pLocalPalette = (uint8_t*) &PALETTE;
frameconfig->numLocalPaletteEntries = 3;
frameconfig->pImageData = (uint8_t*)calloc(size, sizeof(uint8_t));
if (cairo_image_surface_get_format(surface) == CAIRO_FORMAT_RGB24) {
uint32_t* pen = (uint32_t*) cairo_image_surface_get_data(surface);
for (size_t i = 0; i < size; i++) {
uint32_t cairo_color = pen[i];
switch (cairo_color & 0x00FFFFFF) {
case CAIRO_BLACK:
frameconfig->pImageData[i] = 1;
break;
case CAIRO_RED:
frameconfig->pImageData[i] = 2;
break;
}
}
}
}
void make_gif_inner(cairo_surface_t *frames[], size_t n_frames, const char* path) {
CGIF_Config cgif_config;
memset(&cgif_config, 0, sizeof(CGIF_Config));
cgif_config.path = path;
cgif_config.attrFlags = CGIF_ATTR_IS_ANIMATED | CGIF_ATTR_NO_GLOBAL_TABLE;
cgif_config.width = cairo_image_surface_get_width(frames[0]);
cgif_config.height = cairo_image_surface_get_height(frames[0]);
CGIF *cgif = cgif_newgif(&cgif_config);
for (size_t i = 0; i < n_frames; i++) {
cairo_surface_t *frame = frames[i];
// Flush pending writes
cairo_surface_flush(frame);
CGIF_FrameConfig cgif_frameconfig;
memset(&cgif_frameconfig, 0, sizeof(CGIF_FrameConfig));
cgif_frameconfig.attrFlags = CGIF_FRAME_ATTR_USE_LOCAL_TABLE;
cgif_frameconfig.delay = 100;
encode_frame(frame, &cgif_frameconfig);
cgif_addframe(cgif, &cgif_frameconfig);
}
cgif_close(cgif);
}
SCM make_gif(SCM frames, SCM path) {
size_t n_frames = scm_to_size_t(scm_length(frames));
cairo_surface_t **c_frames = (cairo_surface_t **) malloc(sizeof(cairo_surface_t*) * n_frames);
for (size_t i = 0; i < n_frames; i++) {
c_frames[i] = scm_to_cairo_surface(scm_list_ref(frames, scm_from_size_t(i)));
}
const char* c_path = scm_to_locale_string(path);
make_gif_inner(c_frames, n_frames, c_path);
return SCM_UNSPECIFIED;
}
void init_cgif() {
scm_c_define_gsubr("make-gif", 2, 0, 0, &make_gif);
}

View File

@ -1,7 +1,6 @@
(define-module (graphgif))
(use-modules (cairo)
(cgif)
(srfi srfi-1))
(re-export (cairo-pattern-create-rgb . create-color))
@ -59,11 +58,6 @@
(cairo-destroy cr)
surface))
(define-public (write-graphs-to-file graphs filename)
(let ([surfaces (map draw-abstract-graph graphs)])
(make-gif surfaces filename)
(for-each (lambda (s) (cairo-surface-destroy s)) surfaces)))
;;;;;;;;;;;;;;;;;;;;;;
;; Graph Generation ;;
;;;;;;;;;;;;;;;;;;;;;;
@ -107,6 +101,23 @@
(reverse lst)
(loop (1+ i) (cons (make-node i) lst)))))
;;;;;;;;;;;;
;; Output ;;
;;;;;;;;;;;;
(define (output-to-file surfaces filename)
(define pngdir (mkdtemp "graphgif_XXXXXX"))
(do ([i 1 (1+ i)]
[surfaces surfaces (cdr surfaces)])
((null? surfaces))
(cairo-surface-write-to-png
(car surfaces)
(string-append pngdir "/img-" (number->string i) ".png")))
(system* "ffmpeg" "-i" (string-append pngdir "/img-%d.png") "-r" "1" filename))
(define-public (write-graphs-to-file graphs filename)
(output-to-file (map draw-abstract-graph graphs) filename))
;; Local Variables:
;; geiser-scheme-implementation: guile
;; End: