Initial badges work
Additional cleanup probably necessary, some more feature work still in progress (zip files)
This commit is contained in:
@@ -3,6 +3,135 @@
|
||||
|
||||
#include <png.h>
|
||||
|
||||
int pngToRGB565(char *png_buf, u64 fileSize, u16 *rgb_buf_64x64, u8 *alpha_buf_64x64, u16 *rgb_buf_32x32, u8 *alpha_buf_32x32, bool set_icon)
|
||||
{
|
||||
if (png_buf == NULL) return 0;
|
||||
if (fileSize < 8 || png_sig_cmp((png_bytep) png_buf, 0, 8))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 *buf = (u32 *) png_buf;
|
||||
FILE *fp = fmemopen(buf, fileSize, "rb");
|
||||
png_bytep *row_pointers = NULL;
|
||||
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png_infop info = png_create_info_struct(png);
|
||||
|
||||
png_init_io(png, fp);
|
||||
png_read_info(png, info);
|
||||
|
||||
u32 width = png_get_image_width(png, info);
|
||||
u32 height = png_get_image_height(png, info);
|
||||
png_byte color_type = png_get_color_type(png, info);
|
||||
png_byte bit_depth = png_get_bit_depth(png, info);
|
||||
|
||||
if (set_icon && (width != 48 || height != 48))
|
||||
{
|
||||
DEBUG("Invalid set icon?\n");
|
||||
return 0;
|
||||
}
|
||||
if (!set_icon && (width < 64 || height < 64 || width % 64 != 0 || height % 64 != 0 || width > 12 * 64 || height > 6 * 64))
|
||||
{
|
||||
DEBUG("Invalid png found...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
u32 x, y, r, g, b, a;
|
||||
|
||||
memset(alpha_buf_64x64, 0, 12*6*64*64/2);
|
||||
memset(alpha_buf_32x32, 0, 12*6*32*32/2);
|
||||
|
||||
row_pointers = malloc(sizeof(png_bytep) * height);
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
row_pointers[y] = (png_byte *) malloc(png_get_rowbytes(png, info));
|
||||
}
|
||||
|
||||
png_read_image(png, row_pointers);
|
||||
|
||||
png_destroy_read_struct(&png, &info, NULL);
|
||||
|
||||
if (fp) fclose(fp);
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
png_bytep row = row_pointers[y];
|
||||
for (x = 0; x < width; ++x)
|
||||
{
|
||||
png_bytep px = &(row[x * 4]);
|
||||
r = px[0] >> 3;
|
||||
g = px[1] >> 2;
|
||||
b = px[2] >> 3;
|
||||
a = px[3] >> 4;
|
||||
|
||||
// rgb565 conversion code adapted from GYTB
|
||||
int rgb565_index = 8*64*((y/8)%8) | 64*((x/8)%8) | 32*((y/4)%2) | 16*((x/4)%2) | 8*((y/2)%2) | 4*((x/2)%2) | 2*(y%2) | (x%2);
|
||||
rgb565_index |= 64*64*(height/64)*(x/64) + 64*64*(y/64); // account for multiple badges from 1 image
|
||||
rgb_buf_64x64[rgb565_index] = (r << 11) | (g << 5) | b;
|
||||
alpha_buf_64x64[rgb565_index / 2] |= a << (4 * (x % 2));
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < height; y += 2)
|
||||
{
|
||||
png_bytep row = row_pointers[y];
|
||||
png_bytep nextrow = row_pointers[y+1];
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
png_bytep px1 = &(row[x * 4]);
|
||||
png_bytep px2 = &(nextrow[x * 4]);
|
||||
png_bytep px3 = &(row[(x + 1) * 4]);
|
||||
png_bytep px4 = &(nextrow[(x + 1) * 4]);
|
||||
r = (px1[0] + px2[0] + px3[0] + px4[0]) >> 5;
|
||||
g = (px1[1] + px2[1] + px3[1] + px4[1]) >> 4;
|
||||
b = (px1[2] + px2[2] + px3[2] + px4[2]) >> 5;
|
||||
a = (px1[3] + px2[3] + px3[3] + px4[3]) >> 6;
|
||||
int x2 = x/2;
|
||||
int y2 = y/2;
|
||||
|
||||
int rgb565_index = 4*64*((y2/8)%4) | 64*((x2/8)%4) | 32*((y2/4)%2) | 16*((x2/4)%2) | 8*((y2/2)%2) | 4*((x2/2)%2) | 2*(y2%2) | (x2%2);
|
||||
rgb565_index |= 32*32*(height/64)*(x/64) + 32*32*(y/64);
|
||||
|
||||
rgb_buf_32x32[rgb565_index] = (r << 11) | (g << 5) | b;
|
||||
alpha_buf_32x32[rgb565_index / 2] |= a << (4 * (x2%2));
|
||||
}
|
||||
}
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
free(row_pointers[y]);
|
||||
}
|
||||
|
||||
free(row_pointers);
|
||||
if (!set_icon)
|
||||
return (height/64)*(width/64);
|
||||
else
|
||||
return (height/48)*(width/48);
|
||||
}
|
||||
|
||||
static void rotate_agbr_counterclockwise(char ** bufp, size_t size, size_t width)
|
||||
{
|
||||
uint32_t * buf = (uint32_t*)*bufp;
|
||||
|
||||
Reference in New Issue
Block a user