aboutsummaryrefslogtreecommitdiff
path: root/data/render.c
diff options
context:
space:
mode:
Diffstat (limited to 'data/render.c')
-rw-r--r--data/render.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/data/render.c b/data/render.c
new file mode 100644
index 0000000..f9da65d
--- /dev/null
+++ b/data/render.c
@@ -0,0 +1,86 @@
+#include <sqlite3ext.h>
+SQLITE_EXTENSION_INIT1
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <zlib.h>
+
+#include "compress.c"
+
+#define EVA_SIZE (sizeof(uint64_t) * MVEC_SIZE)
+
+void eva_render(sqlite3_context *context, int argc, sqlite3_value **argv) {
+ assert(context);
+ assert(argc == 4);
+ assert(argv);
+
+ (void)argc;
+
+ size_t left = (size_t)sqlite3_value_int(argv[0]);
+#if defined(MVEC_LOOP)
+ left %= MVEC_SIZE;
+#endif
+
+ size_t px_count = (size_t)sqlite3_value_int(argv[1]);
+ size_t px_pow = (size_t)sqlite3_value_int(argv[2]);
+ size_t px_res = 1 << px_pow;
+#if !defined(MVEC_LOOP)
+#if !defined(NDEBUG)
+ size_t right = left + px_res * px_count;
+#endif
+ assert(left < MVEC_SIZE);
+ assert(right <= MVEC_SIZE);
+#endif
+
+ const void *blob = sqlite3_value_blob(argv[3]);
+ size_t blob_size = (size_t)sqlite3_value_bytes(argv[3]);
+
+ // Inflate blob
+ size_t out_size = sizeof(uint64_t) * px_count;
+ uint64_t *eva = sqlite3_malloc(EVA_SIZE);
+ uint64_t *out = sqlite3_malloc(out_size);
+ z_stream strm = { 0 };
+ salis_inflate(&strm, blob_size, EVA_SIZE, (Bytef *)blob, (Bytef *)eva);
+ salis_inflate_end(&strm);
+
+ // Render image
+ for (size_t i = 0; i < px_count; i++) {
+ out[i] = 0;
+
+ for (size_t j = 0; j < px_res; j++) {
+ size_t in_coord = left + i * px_res + j;
+#if defined(MVEC_LOOP)
+ in_coord %= MVEC_SIZE;
+#endif
+ out[i] += eva[in_coord];
+ }
+ }
+
+ sqlite3_free(eva);
+
+ // Transform rendered image into textual representation
+ // A comma-separated list of hexadecimal integers
+ char *csv = sqlite3_malloc(px_count * 17 + 1);
+ char *ptr = csv;
+
+ for (size_t i = 0; i < px_count; i++) {
+ ptr += sprintf(ptr, "%lx ", out[i]);
+ }
+
+ *(--ptr) = '\0';
+ sqlite3_free(out);
+
+ sqlite3_result_text(context, csv, -1, sqlite3_free);
+}
+
+int sqlite3_render_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) {
+ assert(db);
+ assert(pzErrMsg);
+ assert(pApi);
+
+ (void)pzErrMsg;
+
+ SQLITE_EXTENSION_INIT2(pApi);
+ return sqlite3_create_function(db, "eva_render", 4, SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS | SQLITE_UTF8, NULL, eva_render, NULL, NULL);
+}