Skip to content

Commit c42b684

Browse files
committed
Logo (Image): try improving performace of base64 encoding
1 parent 1837446 commit c42b684

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

src/logo/image/image.c

+36-18
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,45 @@
1111
#include <windows.h>
1212
#endif
1313

14-
static FFstrbuf base64Encode(const FFstrbuf* in)
14+
// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145
15+
static void base64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output)
1516
{
16-
const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17-
18-
FFstrbuf out = ffStrbufCreateA(8 * (1 + in->length / 6));
17+
static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18+
char *out = output;
19+
const char *ends = str + (size - size % 3);
20+
while (str != ends) {
21+
uint32_t n = __builtin_bswap32(*(uint32_t*) str);
22+
*out++ = chars[(n >> 26) & 63];
23+
*out++ = chars[(n >> 20) & 63];
24+
*out++ = chars[(n >> 14) & 63];
25+
*out++ = chars[(n >> 8) & 63];
26+
str += 3;
27+
}
1928

20-
unsigned val = 0;
21-
int valb = -6;
22-
for (uint32_t i = 0; i < in->length; ++i)
23-
{
24-
unsigned char c = (unsigned char) in->chars[i];
25-
val = (val << 8) + c;
26-
valb += 8;
27-
while (valb >= 0)
28-
{
29-
ffStrbufAppendC(&out, base64Chars[(val>>valb)&0x3F]);
30-
valb -= 6;
31-
}
29+
if (size % 3 == 1) {
30+
uint64_t n = (uint64_t)*str << 16;
31+
*out++ = chars[(n >> 18) & 63];
32+
*out++ = chars[(n >> 12) & 63];
33+
*out++ = '=';
34+
*out++ = '=';
35+
} else if (size % 3 == 2) {
36+
uint64_t n = (uint64_t)*str++ << 16;
37+
n |= (uint64_t)*str << 8;
38+
*out++ = chars[(n >> 18) & 63];
39+
*out++ = chars[(n >> 12) & 63];
40+
*out++ = chars[(n >> 6) & 63];
41+
*out++ = '=';
3242
}
33-
if (valb > -6) ffStrbufAppendC(&out, base64Chars[((val<<8)>>(valb+8))&0x3F]);
34-
while (out.length % 4) ffStrbufAppendC(&out, '=');
43+
*out = '\0';
44+
*out_size = (uint32_t) (out - output);
45+
}
46+
47+
static FFstrbuf base64Encode(const FFstrbuf* in)
48+
{
49+
FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3);
50+
base64EncodeRaw(in->length, in->chars, &out.length, out.chars);
51+
assert(out.length < out.allocated);
52+
3553
return out;
3654
}
3755

0 commit comments

Comments
 (0)