-
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
12 changed files
with
167 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#include "proto.h" | ||
|
||
#define pixelcolor(px) (((uint32_t) (px).a << 24) | ((uint32_t) (px).b << 16) | ((uint32_t) (px).g << 8) | (uint32_t) (px).r) | ||
|
||
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); | ||
size_t framesize = (size_t) context -> image -> width * context -> image -> height; | ||
uint32_t * frame = ctxmalloc(context, sizeof *frame * framesize); | ||
const unsigned char * data = context -> data + 14; | ||
const unsigned char * dataend = context -> data + context -> size; | ||
struct QOI_pixel lookup[64] = {0}; | ||
struct QOI_pixel px = {.r = 0, .g = 0, .b = 0, .a = 0xff}; | ||
for (size_t cell = 0; cell < framesize; cell ++) { | ||
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 / 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 ++); | ||
int8_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) { | ||
uint8_t run = v & 0x3f; | ||
if (cell + run >= framesize) throw(context, PLUM_ERR_INVALID_FILE_FORMAT); | ||
uint32_t color = pixelcolor(px); | ||
while (run --) frame[cell ++] = color; | ||
} else | ||
throw(context, PLUM_ERR_INVALID_FILE_FORMAT); | ||
lookup[(px.r * 3 + px.g * 5 + px.b * 7 + px.a * 11) % (sizeof lookup / sizeof *lookup)] = px; | ||
} | ||
frame[cell] = pixelcolor(px); | ||
} | ||
plum_convert_colors(context -> image -> data8, frame, framesize, flags, PLUM_COLOR_32 | PLUM_ALPHA_INVERT); | ||
ctxfree(context, frame); | ||
} | ||
|
||
#undef pixelcolor |
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,65 @@ | ||
#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); | ||
bytewrite(header + 12, channels, 0); | ||
size_t framesize = (size_t) context -> source -> width * context -> source -> height; | ||
uint32_t * data; | ||
if ((context -> source -> color_format & (PLUM_COLOR_MASK | PLUM_ALPHA_INVERT)) == (PLUM_COLOR_32 | PLUM_ALPHA_INVERT)) | ||
data = context -> source -> data; | ||
else { | ||
data = ctxmalloc(context, sizeof *data * framesize); | ||
plum_convert_colors(data, context -> source -> data, framesize, PLUM_COLOR_32 | PLUM_ALPHA_INVERT, context -> source -> color_format); | ||
} | ||
unsigned char * node = append_output_node(context, framesize * (channels + 1) + 8); | ||
unsigned char * output = node; | ||
struct QOI_pixel lookup[64] = {0}; | ||
struct QOI_pixel prev = {.r = 0, .g = 0, .b = 0, .a = 0xff}; | ||
uint8_t run = 0; | ||
for (size_t cell = 0; cell < framesize; cell ++) { | ||
struct QOI_pixel px = {.r = data[cell], .g = data[cell] >> 8, .b = data[cell] >> 16, .a = data[cell] >> 24}; | ||
if (equalpixels(px, prev)) { | ||
run ++; | ||
if (run == 62 || cell == framesize - 1) { | ||
*(output ++) = 0xc0 | (run - 1); | ||
run = 0; | ||
} | ||
} else { | ||
if (run) { | ||
*(output ++) = 0xc0 | (run - 1); | ||
run = 0; | ||
} | ||
uint8_t index = (px.r * 3 + px.g * 5 + px.b * 7 + px.a * 11) % (sizeof lookup / 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