aboutsummaryrefslogtreecommitdiff
path: root/data/render.c
blob: f9da65d5c6d0f1408178add0c2f3a02c62cc6173 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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);
}