mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
drastic image loading optimization
This commit is contained in:
parent
6d7f9870f3
commit
1b181772a1
3 changed files with 125 additions and 82 deletions
BIN
boredos.iso
BIN
boredos.iso
Binary file not shown.
|
|
@ -340,22 +340,37 @@ static void decode_image(unsigned char *data, int len, RenderElement *el) {
|
|||
el->img_current_frame = 0;
|
||||
el->next_frame_tick = sys_system(16, 0, 0, 0, 0) + (delays[0] * 60 / 1000);
|
||||
|
||||
uint32_t step_x = (img_w_orig << 16) / fit_w;
|
||||
uint32_t step_y = (img_h_orig << 16) / fit_h;
|
||||
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
el->img_frames[i] = malloc(fit_w * fit_h * sizeof(uint32_t));
|
||||
if (el->img_frames[i]) {
|
||||
unsigned char *src_frame = rgba + (i * img_w_orig * img_h_orig * 4);
|
||||
for (int y = 0; y < fit_h; y++) {
|
||||
int sy = y * img_h_orig / fit_h;
|
||||
for (int x = 0; x < fit_w; x++) {
|
||||
int sx = x * img_w_orig / fit_w;
|
||||
int idx = (sy * img_w_orig + sx) * 4;
|
||||
uint32_t r = src_frame[idx];
|
||||
uint32_t g = src_frame[idx+1];
|
||||
uint32_t b = src_frame[idx+2];
|
||||
uint32_t a = src_frame[idx+3];
|
||||
el->img_frames[i][y * fit_w + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
uint16_t *src_h_table = malloc(fit_h * sizeof(uint16_t));
|
||||
uint16_t *src_w_table = malloc(fit_w * sizeof(uint16_t));
|
||||
|
||||
if (src_h_table && src_w_table) {
|
||||
for (int y = 0; y < fit_h; y++) src_h_table[y] = (y * step_y) >> 16;
|
||||
for (int x = 0; x < fit_w; x++) src_w_table[x] = (x * step_x) >> 16;
|
||||
|
||||
for (int y = 0; y < fit_h; y++) {
|
||||
int sy = src_h_table[y];
|
||||
uint32_t src_row_off = sy * img_w_orig;
|
||||
uint32_t dst_row_off = y * fit_w;
|
||||
for (int x = 0; x < fit_w; x++) {
|
||||
int sx = src_w_table[x];
|
||||
int idx = (src_row_off + sx) * 4;
|
||||
uint32_t r = src_frame[idx];
|
||||
uint32_t g = src_frame[idx+1];
|
||||
uint32_t b = src_frame[idx+2];
|
||||
uint32_t a = src_frame[idx+3];
|
||||
el->img_frames[i][dst_row_off + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (src_h_table) free(src_h_table);
|
||||
if (src_w_table) free(src_w_table);
|
||||
}
|
||||
el->img_delays[i] = delays[i];
|
||||
}
|
||||
|
|
@ -364,16 +379,20 @@ static void decode_image(unsigned char *data, int len, RenderElement *el) {
|
|||
} else {
|
||||
el->img_pixels = malloc(fit_w * fit_h * sizeof(uint32_t));
|
||||
if (el->img_pixels) {
|
||||
uint32_t step_x = (img_w_orig << 16) / fit_w;
|
||||
uint32_t step_y = (img_h_orig << 16) / fit_h;
|
||||
for (int y = 0; y < fit_h; y++) {
|
||||
int sy = y * img_h_orig / fit_h;
|
||||
int sy = (y * step_y) >> 16;
|
||||
uint32_t src_row_off = sy * img_w_orig;
|
||||
uint32_t dst_row_off = y * fit_w;
|
||||
for (int x = 0; x < fit_w; x++) {
|
||||
int sx = x * img_w_orig / fit_w;
|
||||
int idx = (sy * img_w_orig + sx) * 4;
|
||||
int sx = (x * step_x) >> 16;
|
||||
int idx = (src_row_off + sx) * 4;
|
||||
uint32_t r = rgba[idx];
|
||||
uint32_t g = rgba[idx+1];
|
||||
uint32_t b = rgba[idx+2];
|
||||
uint32_t a = rgba[idx+3];
|
||||
el->img_pixels[y * fit_w + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
el->img_pixels[dst_row_off + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
el->img_w = fit_w; el->img_h = fit_h;
|
||||
|
|
|
|||
|
|
@ -6669,35 +6669,44 @@ static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code)
|
|||
{
|
||||
stbi_uc *p, *c;
|
||||
int idx;
|
||||
stbi__uint16 stack[4096];
|
||||
int top = 0;
|
||||
stbi__uint16 current = code;
|
||||
|
||||
// recurse to decode the prefixes, since the linked-list is backwards,
|
||||
// and working backwards through an interleaved image would be nasty
|
||||
if (g->codes[code].prefix >= 0)
|
||||
stbi__out_gif_code(g, g->codes[code].prefix);
|
||||
|
||||
if (g->cur_y >= g->max_y) return;
|
||||
|
||||
idx = g->cur_x + g->cur_y;
|
||||
p = &g->out[idx];
|
||||
g->history[idx / 4] = 1;
|
||||
|
||||
c = &g->color_table[g->codes[code].suffix * 4];
|
||||
if (c[3] > 128) { // don't render transparent pixels;
|
||||
p[0] = c[2];
|
||||
p[1] = c[1];
|
||||
p[2] = c[0];
|
||||
p[3] = c[3];
|
||||
// Follow the chain of prefixes to the root, pushing suffixes onto the stack
|
||||
while (current != (stbi__uint16)-1) {
|
||||
if (top >= 4096) break;
|
||||
stack[top++] = current;
|
||||
current = (stbi__uint16)g->codes[current].prefix;
|
||||
}
|
||||
g->cur_x += 4;
|
||||
|
||||
if (g->cur_x >= g->max_x) {
|
||||
g->cur_x = g->start_x;
|
||||
g->cur_y += g->step;
|
||||
// Pop and process suffixes in order
|
||||
while (top > 0) {
|
||||
stbi__uint16 c_code = stack[--top];
|
||||
if (g->cur_y >= g->max_y) continue;
|
||||
|
||||
while (g->cur_y >= g->max_y && g->parse > 0) {
|
||||
g->step = (1 << g->parse) * g->line_size;
|
||||
g->cur_y = g->start_y + (g->step >> 1);
|
||||
--g->parse;
|
||||
idx = g->cur_x + g->cur_y;
|
||||
p = &g->out[idx];
|
||||
g->history[idx / 4] = 1;
|
||||
|
||||
c = &g->color_table[g->codes[c_code].suffix * 4];
|
||||
if (c[3] > 128) { // don't render transparent pixels;
|
||||
p[0] = c[2];
|
||||
p[1] = c[1];
|
||||
p[2] = c[0];
|
||||
p[3] = c[3];
|
||||
}
|
||||
g->cur_x += 4;
|
||||
|
||||
if (g->cur_x >= g->max_x) {
|
||||
g->cur_x = g->start_x;
|
||||
g->cur_y += g->step;
|
||||
|
||||
while (g->cur_y >= g->max_y && g->parse > 0) {
|
||||
g->step = (1 << g->parse) * g->line_size;
|
||||
g->cur_y = g->start_y + (g->step >> 1);
|
||||
--g->parse;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6963,15 +6972,46 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|||
}
|
||||
}
|
||||
|
||||
static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays)
|
||||
static int stbi__gif_count_frames(stbi__context *s)
|
||||
{
|
||||
STBI_FREE(g->out);
|
||||
STBI_FREE(g->history);
|
||||
STBI_FREE(g->background);
|
||||
int layers = 0;
|
||||
stbi_uc flags;
|
||||
int tag;
|
||||
int off = s->read_from_callbacks ? 0 : (int)(s->img_buffer - s->img_buffer_original);
|
||||
|
||||
if (out) STBI_FREE(out);
|
||||
if (delays && *delays) STBI_FREE(*delays);
|
||||
return stbi__errpuc("outofmem", "Out of memory");
|
||||
stbi__skip(s, 6); // GIF87a/GIF89a
|
||||
stbi__skip(s, 4); // w, h
|
||||
flags = stbi__get8(s);
|
||||
stbi__skip(s, 2);
|
||||
if (flags & 0x80) stbi__skip(s, 3 * (2 << (flags & 7)));
|
||||
|
||||
while (!stbi__at_eof(s)) {
|
||||
tag = stbi__get8(s);
|
||||
if (tag == 0x2C) {
|
||||
layers++;
|
||||
stbi__skip(s, 8);
|
||||
flags = stbi__get8(s);
|
||||
if (flags & 0x80) stbi__skip(s, 3 * (2 << (flags & 7)));
|
||||
stbi__get8(s); // LZW size
|
||||
while (1) {
|
||||
int len = stbi__get8(s);
|
||||
if (len == 0) break;
|
||||
stbi__skip(s, len);
|
||||
}
|
||||
} else if (tag == 0x21) {
|
||||
stbi__get8(s);
|
||||
while (1) {
|
||||
int len = stbi__get8(s);
|
||||
if (len == 0) break;
|
||||
stbi__skip(s, len);
|
||||
}
|
||||
} else if (tag == 0x3B) break;
|
||||
else break;
|
||||
}
|
||||
|
||||
stbi__rewind(s);
|
||||
if (off) stbi__skip(s, off);
|
||||
return layers;
|
||||
}
|
||||
|
||||
static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp)
|
||||
|
|
@ -6983,17 +7023,28 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stbi_uc *two_back = 0;
|
||||
stbi__gif g;
|
||||
int stride;
|
||||
int out_size = 0;
|
||||
int delays_size = 0;
|
||||
|
||||
STBI_NOTUSED(out_size);
|
||||
STBI_NOTUSED(delays_size);
|
||||
int total_layers = 0;
|
||||
|
||||
memset(&g, 0, sizeof(g));
|
||||
|
||||
total_layers = stbi__gif_count_frames(s);
|
||||
if (total_layers <= 0) return stbi__errpuc("no frames", "Corrupt GIF");
|
||||
|
||||
// Initial header parse to get dimensions
|
||||
if (!stbi__gif_header(s, &g, comp, 0)) return 0;
|
||||
stride = g.w * g.h * 4;
|
||||
stbi__rewind(s); // Rewind again for the main loop
|
||||
|
||||
out = (stbi_uc*)stbi__malloc(total_layers * stride);
|
||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||
|
||||
if (delays) {
|
||||
*delays = 0;
|
||||
*delays = (int*)stbi__malloc(total_layers * sizeof(int));
|
||||
if (!*delays) { STBI_FREE(out); return stbi__errpuc("outofmem", "Out of memory"); }
|
||||
}
|
||||
|
||||
memset(&g, 0, sizeof(g)); // Reset for real load
|
||||
|
||||
do {
|
||||
u = stbi__gif_load_next(s, &g, comp, req_comp, two_back);
|
||||
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
|
||||
|
|
@ -7002,39 +7053,12 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
*x = g.w;
|
||||
*y = g.h;
|
||||
++layers;
|
||||
stride = g.w * g.h * 4;
|
||||
|
||||
if (layers > total_layers) break; // Defensive
|
||||
|
||||
if (out) {
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
|
||||
if (!tmp)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
else {
|
||||
out = (stbi_uc*) tmp;
|
||||
out_size = layers * stride;
|
||||
}
|
||||
|
||||
if (delays) {
|
||||
int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers );
|
||||
if (!new_delays)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
*delays = new_delays;
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
} else {
|
||||
out = (stbi_uc*)stbi__malloc( layers * stride );
|
||||
if (!out)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
out_size = layers * stride;
|
||||
if (delays) {
|
||||
*delays = (int*) stbi__malloc( layers * sizeof(int) );
|
||||
if (!*delays)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
}
|
||||
memcpy( out + ((layers - 1) * stride), u, stride );
|
||||
if (layers >= 2) {
|
||||
two_back = out - 2 * stride;
|
||||
two_back = out + (layers - 2) * stride;
|
||||
}
|
||||
|
||||
if (delays) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue