mirror of
https://github.com/libretro/RetroArch
synced 2025-03-28 19:20:35 +00:00
rpng.c - some cleanups
This commit is contained in:
parent
8adb16bf0a
commit
a9e4f17b07
160
gfx/rpng/rpng.c
160
gfx/rpng/rpng.c
@ -85,6 +85,7 @@ static uint32_t dword_be(const uint8_t *buf)
|
||||
static bool read_chunk_header(FILE *file, struct png_chunk *chunk)
|
||||
{
|
||||
uint8_t dword[4] = {0};
|
||||
|
||||
if (fread(dword, 1, 4, file) != 4)
|
||||
return false;
|
||||
|
||||
@ -116,6 +117,7 @@ struct idat_buffer
|
||||
static enum png_chunk_type png_chunk_type(const struct png_chunk *chunk)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(chunk_map); i++)
|
||||
{
|
||||
if (memcmp(chunk->type, chunk_map[i].id, 4) == 0)
|
||||
@ -157,6 +159,7 @@ static bool png_parse_ihdr(FILE *file,
|
||||
{
|
||||
unsigned i;
|
||||
bool ret = true;
|
||||
|
||||
if (!png_read_chunk(file, chunk))
|
||||
return false;
|
||||
|
||||
@ -184,6 +187,7 @@ static bool png_parse_ihdr(FILE *file,
|
||||
{
|
||||
static const unsigned valid_bpp[] = { 1, 2, 4, 8, 16 };
|
||||
bool correct_bpp = false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_bpp); i++)
|
||||
{
|
||||
if (valid_bpp[i] == ihdr->depth)
|
||||
@ -200,6 +204,7 @@ static bool png_parse_ihdr(FILE *file,
|
||||
{
|
||||
static const unsigned valid_bpp[] = { 1, 2, 4, 8 };
|
||||
bool correct_bpp = false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(valid_bpp); i++)
|
||||
{
|
||||
if (valid_bpp[i] == ihdr->depth)
|
||||
@ -227,8 +232,10 @@ static bool png_parse_ihdr(FILE *file,
|
||||
if (ihdr->compression != 0)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
//if (ihdr->interlace != 0) // No Adam7 supported.
|
||||
// GOTO_END_ERROR();
|
||||
#if 0
|
||||
if (ihdr->interlace != 0) /* No Adam7 supported. */
|
||||
GOTO_END_ERROR();
|
||||
#endif
|
||||
|
||||
end:
|
||||
png_free_chunk(chunk);
|
||||
@ -238,7 +245,7 @@ end:
|
||||
// Paeth prediction filter.
|
||||
static inline int paeth(int a, int b, int c)
|
||||
{
|
||||
int p = a + b - c;
|
||||
int p = a + b - c;
|
||||
int pa = abs(p - a);
|
||||
int pb = abs(p - b);
|
||||
int pc = abs(p - c);
|
||||
@ -254,14 +261,18 @@ static inline void copy_line_rgb(uint32_t *data,
|
||||
const uint8_t *decoded, unsigned width, unsigned bpp)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bpp /= 8;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
uint32_t r = *decoded;
|
||||
uint32_t r, g, b;
|
||||
|
||||
r = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t g = *decoded;
|
||||
g = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t b = *decoded;
|
||||
b = *decoded;
|
||||
decoded += bpp;
|
||||
data[i] = (0xffu << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
@ -271,16 +282,19 @@ static inline void copy_line_rgba(uint32_t *data,
|
||||
const uint8_t *decoded, unsigned width, unsigned bpp)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bpp /= 8;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
uint32_t r = *decoded;
|
||||
uint32_t r, g, b, a;
|
||||
r = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t g = *decoded;
|
||||
g = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t b = *decoded;
|
||||
b = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t a = *decoded;
|
||||
a = *decoded;
|
||||
decoded += bpp;
|
||||
data[i] = (a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
@ -289,7 +303,11 @@ static inline void copy_line_rgba(uint32_t *data,
|
||||
static inline void copy_line_bw(uint32_t *data,
|
||||
const uint8_t *decoded, unsigned width, unsigned depth)
|
||||
{
|
||||
unsigned i, bit;
|
||||
unsigned i, bit = 0;
|
||||
static const unsigned mul_table[] = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 };
|
||||
unsigned mul = mul_table[depth];
|
||||
unsigned mask = (1 << depth) - 1;
|
||||
|
||||
if (depth == 16)
|
||||
{
|
||||
for (i = 0; i < width; i++)
|
||||
@ -297,22 +315,17 @@ static inline void copy_line_bw(uint32_t *data,
|
||||
uint32_t val = decoded[i << 1];
|
||||
data[i] = (val * 0x010101) | (0xffu << 24);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const unsigned mul_table[] = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 };
|
||||
unsigned mul = mul_table[depth];
|
||||
unsigned mask = (1 << depth) - 1;
|
||||
bit = 0;
|
||||
for (i = 0; i < width; i++, bit += depth)
|
||||
{
|
||||
unsigned byte = bit >> 3;
|
||||
unsigned val = decoded[byte] >> (8 - depth - (bit & 7));
|
||||
|
||||
val &= mask;
|
||||
val *= mul;
|
||||
data[i] = (val * 0x010101) | (0xffu << 24);
|
||||
}
|
||||
for (i = 0; i < width; i++, bit += depth)
|
||||
{
|
||||
unsigned byte = bit >> 3;
|
||||
unsigned val = decoded[byte] >> (8 - depth - (bit & 7));
|
||||
|
||||
val &= mask;
|
||||
val *= mul;
|
||||
data[i] = (val * 0x010101) | (0xffu << 24);
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,15 +334,19 @@ static inline void copy_line_gray_alpha(uint32_t *data,
|
||||
unsigned bpp)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bpp /= 8;
|
||||
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
uint32_t gray = *decoded;
|
||||
uint32_t gray, alpha;
|
||||
|
||||
gray = *decoded;
|
||||
decoded += bpp;
|
||||
uint32_t alpha = *decoded;
|
||||
alpha = *decoded;
|
||||
decoded += bpp;
|
||||
|
||||
data[i] = (gray * 0x010101) | (alpha << 24);
|
||||
data[i] = (gray * 0x010101) | (alpha << 24);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,11 +356,14 @@ static inline void copy_line_plt(uint32_t *data,
|
||||
{
|
||||
unsigned i, bit;
|
||||
unsigned mask = (1 << depth) - 1;
|
||||
|
||||
bit = 0;
|
||||
|
||||
for (i = 0; i < width; i++, bit += depth)
|
||||
{
|
||||
unsigned byte = bit >> 3;
|
||||
unsigned val = decoded[byte] >> (8 - depth - (bit & 7));
|
||||
|
||||
val &= mask;
|
||||
data[i] = palette[val];
|
||||
}
|
||||
@ -355,6 +375,7 @@ static void png_pass_geom(const struct png_ihdr *ihdr,
|
||||
{
|
||||
unsigned bpp;
|
||||
unsigned pitch;
|
||||
|
||||
switch (ihdr->color_type)
|
||||
{
|
||||
case 0:
|
||||
@ -402,18 +423,20 @@ static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr,
|
||||
const uint32_t *palette)
|
||||
{
|
||||
unsigned i, h;
|
||||
bool ret = true;
|
||||
|
||||
unsigned bpp;
|
||||
unsigned pitch;
|
||||
size_t pass_size;
|
||||
uint8_t *prev_scanline = NULL;
|
||||
uint8_t *decoded_scanline = NULL;
|
||||
bool ret = true;
|
||||
|
||||
png_pass_geom(ihdr, ihdr->width, ihdr->height, &bpp, &pitch, &pass_size);
|
||||
|
||||
if (inflate_buf_size < pass_size)
|
||||
return false;
|
||||
|
||||
uint8_t *prev_scanline = (uint8_t*)calloc(1, pitch);
|
||||
uint8_t *decoded_scanline = (uint8_t*)calloc(1, pitch);
|
||||
prev_scanline = (uint8_t*)calloc(1, pitch);
|
||||
decoded_scanline = (uint8_t*)calloc(1, pitch);
|
||||
|
||||
if (!prev_scanline || !decoded_scanline)
|
||||
GOTO_END_ERROR();
|
||||
@ -422,6 +445,7 @@ static bool png_reverse_filter(uint32_t *data, const struct png_ihdr *ihdr,
|
||||
h++, inflate_buf += pitch, data += ihdr->width)
|
||||
{
|
||||
unsigned filter = *inflate_buf++;
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case 0: /* None */
|
||||
@ -500,11 +524,14 @@ static void deinterlace_pass(uint32_t *data, const struct png_ihdr *ihdr,
|
||||
const struct adam7_pass *pass)
|
||||
{
|
||||
unsigned x, y;
|
||||
|
||||
data += pass->y * ihdr->width + pass->x;
|
||||
|
||||
for (y = 0; y < pass_height;
|
||||
y++, data += ihdr->width * pass->stride_y, input += pass_width)
|
||||
{
|
||||
uint32_t *out = data;
|
||||
|
||||
for (x = 0; x < pass_width; x++, out += pass->stride_x)
|
||||
*out = input[x];
|
||||
}
|
||||
@ -528,26 +555,30 @@ static bool png_reverse_filter_adam7(uint32_t *data,
|
||||
|
||||
for (pass = 0; pass < ARRAY_SIZE(passes); pass++)
|
||||
{
|
||||
unsigned pass_width, pass_height;
|
||||
size_t pass_size;
|
||||
struct png_ihdr tmp_ihdr;
|
||||
uint32_t *tmp_data = NULL;
|
||||
|
||||
if (ihdr->width <= passes[pass].x ||
|
||||
ihdr->height <= passes[pass].y) /* Empty pass */
|
||||
continue;
|
||||
|
||||
unsigned pass_width = (ihdr->width -
|
||||
pass_width = (ihdr->width -
|
||||
passes[pass].x + passes[pass].stride_x - 1) / passes[pass].stride_x;
|
||||
unsigned pass_height = (ihdr->height - passes[pass].y +
|
||||
pass_height = (ihdr->height - passes[pass].y +
|
||||
passes[pass].stride_y - 1) / passes[pass].stride_y;
|
||||
|
||||
uint32_t *tmp_data = (uint32_t*)
|
||||
malloc(pass_width * pass_height * sizeof(uint32_t));
|
||||
tmp_data = (uint32_t*)malloc(
|
||||
pass_width * pass_height * sizeof(uint32_t));
|
||||
|
||||
if (!tmp_data)
|
||||
return false;
|
||||
|
||||
struct png_ihdr tmp_ihdr = *ihdr;
|
||||
tmp_ihdr = *ihdr;
|
||||
tmp_ihdr.width = pass_width;
|
||||
tmp_ihdr.height = pass_height;
|
||||
|
||||
size_t pass_size;
|
||||
png_pass_geom(&tmp_ihdr, pass_width,
|
||||
pass_height, NULL, NULL, &pass_size);
|
||||
|
||||
@ -579,6 +610,7 @@ static bool png_append_idat(FILE *file,
|
||||
const struct png_chunk *chunk, struct idat_buffer *buf)
|
||||
{
|
||||
uint8_t *new_buffer = (uint8_t*)realloc(buf->data, buf->size + chunk->size);
|
||||
|
||||
if (!new_buffer)
|
||||
return false;
|
||||
|
||||
@ -594,10 +626,11 @@ static bool png_append_idat(FILE *file,
|
||||
static bool png_read_plte(FILE *file, uint32_t *buffer, unsigned entries)
|
||||
{
|
||||
unsigned i;
|
||||
uint8_t buf[256 * 3];
|
||||
|
||||
if (entries > 256)
|
||||
return false;
|
||||
|
||||
uint8_t buf[256 * 3];
|
||||
if (fread(buf, 3, entries, file) != entries)
|
||||
return false;
|
||||
|
||||
@ -618,33 +651,33 @@ static bool png_read_plte(FILE *file, uint32_t *buffer, unsigned entries)
|
||||
bool rpng_load_image_argb(const char *path, uint32_t **data,
|
||||
unsigned *width, unsigned *height)
|
||||
{
|
||||
long pos;
|
||||
*data = NULL;
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
|
||||
bool ret = true;
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long file_len = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
long pos, file_len;
|
||||
FILE *file;
|
||||
char header[8];
|
||||
uint8_t *inflate_buf = NULL;
|
||||
size_t inflate_buf_size = 0;
|
||||
z_stream stream = {0};
|
||||
struct idat_buffer idat_buf = {0};
|
||||
struct png_ihdr ihdr = {0};
|
||||
uint32_t palette[256] = {0};
|
||||
bool has_ihdr = false;
|
||||
bool has_idat = false;
|
||||
bool has_iend = false;
|
||||
bool has_plte = false;
|
||||
uint8_t *inflate_buf = NULL;
|
||||
size_t inflate_buf_size = 0;
|
||||
z_stream stream = {0};
|
||||
bool ret = true;
|
||||
|
||||
struct idat_buffer idat_buf = {0};
|
||||
struct png_ihdr ihdr = {0};
|
||||
uint32_t palette[256] = {0};
|
||||
*data = NULL;
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
|
||||
file = fopen(path, "rb");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
file_len = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
char header[8];
|
||||
if (fread(header, 1, sizeof(header), file) != sizeof(header))
|
||||
GOTO_END_ERROR();
|
||||
|
||||
@ -656,6 +689,7 @@ bool rpng_load_image_argb(const char *path, uint32_t **data,
|
||||
pos < file_len && pos >= 0; pos = ftell(file))
|
||||
{
|
||||
struct png_chunk chunk = {0};
|
||||
|
||||
if (!read_chunk_header(file, &chunk))
|
||||
GOTO_END_ERROR();
|
||||
|
||||
@ -793,11 +827,11 @@ static bool png_write_crc(FILE *file, const uint8_t *data, size_t size)
|
||||
static bool png_write_ihdr(FILE *file, const struct png_ihdr *ihdr)
|
||||
{
|
||||
uint8_t ihdr_raw[] = {
|
||||
'0', '0', '0', '0', // Size
|
||||
'0', '0', '0', '0', /* Size */
|
||||
'I', 'H', 'D', 'R',
|
||||
|
||||
0, 0, 0, 0, // Width
|
||||
0, 0, 0, 0, // Height
|
||||
0, 0, 0, 0, /* Width */
|
||||
0, 0, 0, 0, /* Height */
|
||||
ihdr->depth,
|
||||
ihdr->color_type,
|
||||
ihdr->compression,
|
||||
|
Loading…
x
Reference in New Issue
Block a user