-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
171 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#include "proto.h" | ||
|
||
void load_QOI_data (struct context * context, unsigned flags, size_t limit) { | ||
if (context -> size < 22) throw(context, PLUM_ERR_INVALID_FILE_FORMAT); | ||
context -> image -> type = PLUM_IMAGE_QOI; | ||
context -> image -> frames = 1; | ||
context -> image -> width = read_be32_unaligned(context -> data + 4); | ||
context -> image -> height = read_be32_unaligned(context -> data + 8); | ||
validate_image_size(context, limit); | ||
allocate_framebuffers(context, flags, false); | ||
add_color_depth_metadata(context, 8, 8, 8, 8, 0); | ||
uint64_t * frame = ctxmalloc(context, sizeof *frame * context -> source -> width * context -> source -> height); | ||
const unsigned char * data = context -> data + 14; | ||
const unsigned char * dataend = context -> data + context -> size - 22; | ||
struct QOI_pixel lookup[64] = {0}; | ||
struct QOI_pixel px = {.r = 0, .g = 0, .b = 0, .a = 0xff}; | ||
unsigned char run = 0; | ||
for (uint_fast64_t cell = 0; cell < context -> source -> width * context -> source -> height; cell ++) { | ||
if (run > 0) | ||
run --; | ||
else if (data + 1 < dataend) { | ||
unsigned char v = *(data ++); | ||
if (v == 0xfe && data + 3 < dataend) { | ||
px.r = *(data ++); | ||
px.g = *(data ++); | ||
px.b = *(data ++); | ||
} else if (v == 0xff && data + 4 < dataend) { | ||
px.r = *(data ++); | ||
px.g = *(data ++); | ||
px.b = *(data ++); | ||
px.a = *(data ++); | ||
} else if (!(v & 0xc0) && v < sizeof lookup) | ||
px = lookup[v]; | ||
else if ((v & 0xc0) == 0x40) { | ||
px.r += ((v >> 4) & 3) - 2; | ||
px.g += ((v >> 2) & 3) - 2; | ||
px.b += (v & 3) - 2; | ||
} else if ((v & 0xc0) == 0x80 && data + 1 < dataend) { | ||
unsigned char v2 = *(data ++); | ||
int_fast16_t dg = (v & 0x3f) - 32; | ||
px.r += dg + ((v2 >> 4) & 0xf) - 8; | ||
px.g += dg; | ||
px.b += dg + (v2 & 0xf) - 8; | ||
} else if ((v & 0xc0) == 0xc0) | ||
run = v & 0x3f; | ||
else | ||
throw(context, PLUM_ERR_INVALID_FILE_FORMAT); | ||
lookup[(px.r * 3 + px.g * 5 + px.b * 7 + px.a * 11) % sizeof lookup] = px; | ||
} | ||
frame[cell] = (((uint64_t) (px.a ^ 0xff) << 48) | ((uint64_t) px.b << 32) | ((uint64_t) px.g << 16) | (uint64_t) px.r) * 0x101; | ||
} | ||
write_framebuffer_to_image(context -> image, frame, 0, flags); | ||
ctxfree(context, frame); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#include "proto.h" | ||
|
||
#define equalpixels(p1, p2) ((p1).r == (p2).r && (p1).g == (p2).g && (p1).b == (p2).b && (p1).a == (p2).a) | ||
|
||
void generate_QOI_data (struct context * context) { | ||
if (context -> source -> frames > 1) throw(context, PLUM_ERR_NO_MULTI_FRAME); | ||
if (!(context -> source -> width && context -> source -> height)) throw(context, PLUM_ERR_IMAGE_TOO_LARGE); | ||
unsigned char * header = append_output_node(context, 14); | ||
bytewrite(header, 0x71, 0x6f, 0x69, 0x66); | ||
write_be32_unaligned(header + 4, context -> source -> width); | ||
write_be32_unaligned(header + 8, context -> source -> height); | ||
uint8_t channels = 3 + image_has_transparency(context -> source); | ||
header[12] = channels; | ||
header[13] = 0; | ||
uint32_t * data; | ||
if ((context -> source -> color_format & PLUM_COLOR_MASK) == PLUM_COLOR_32) | ||
data = context -> source -> data; | ||
else { | ||
data = ctxmalloc(context, sizeof *data * context -> source -> width * context -> source -> height); | ||
plum_convert_colors(data, context -> source -> data, (size_t) context -> source -> width * context -> source -> height, | ||
PLUM_COLOR_32, context -> source -> color_format); | ||
} | ||
size_t max_size = context -> source -> width * context -> source -> height * (channels + 1) + 22; | ||
unsigned char * node = append_output_node(context, max_size); | ||
unsigned char * output = node; | ||
struct QOI_pixel lookup[64] = {0}; | ||
struct QOI_pixel px = {.r = 0, .g = 0, .b = 0, .a = 0xff}; | ||
struct QOI_pixel prev = px; | ||
unsigned char run = 0; | ||
for (uint_fast64_t cell = 0; cell < context -> source -> width * context -> source -> height; cell ++) { | ||
px.r = data[cell]; | ||
px.g = data[cell] >> 8; | ||
px.b = data[cell] >> 16; | ||
px.a = (data[cell] >> 24) ^ 0xff; | ||
if (equalpixels(px, prev)) { | ||
run ++; | ||
if (run == 62 || cell == context -> source -> width * context -> source -> height - 1) { | ||
*(output ++) = 0xc0 | (run - 1); | ||
run = 0; | ||
} | ||
} else { | ||
if (run > 0) { | ||
*(output ++) = 0xc0 | (run - 1); | ||
run = 0; | ||
} | ||
uint8_t index = (px.r * 3 + px.g * 5 + px.b * 7 + px.a * 11) % sizeof lookup; | ||
if (equalpixels(px, lookup[index])) | ||
*(output ++) = index; | ||
else { | ||
lookup[index] = px; | ||
if (px.a == prev.a) { | ||
int8_t dr = px.r - prev.r, dg = px.g - prev.g, db = px.b - prev.b; | ||
int8_t drg = dr - dg, dbg = db - dg; | ||
if (dr >= -2 && dr < 2 && dg >= -2 && dg < 2 && db >= -2 && db < 2) | ||
*(output ++) = 0x40 | ((dr + 2) << 4) | ((dg + 2) << 2) | (db + 2); | ||
else if (drg >= -8 && drg < 8 && dg >= -32 && dg < 32 && dbg >= -8 && dbg < 8) | ||
output += byteappend(output, 0x80 | (dg + 32), ((drg + 8) << 4) | (dbg + 8)); | ||
else | ||
output += byteappend(output, 0xfe, px.r, px.g, px.b); | ||
} else | ||
output += byteappend(output, 0xff, px.r, px.g, px.b, px.a); | ||
} | ||
} | ||
prev = px; | ||
} | ||
output += byteappend(output, 0, 0, 0, 0, 0, 0, 0, 1); | ||
resize_output_node(context, node, output - node); | ||
if (data != context -> source -> data) ctxfree(context, data); | ||
} | ||
|
||
#undef equalpixels |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters