mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-25 02:31:50 +01:00
optimizations
This commit is contained in:
parent
8e5eb64a5c
commit
92cbfafede
@ -51,14 +51,13 @@ static struct
|
|||||||
static int f_read(void * punt, int bytes, int blocks, int *f)
|
static int f_read(void * punt, int bytes, int blocks, int *f)
|
||||||
{
|
{
|
||||||
int b;
|
int b;
|
||||||
int c;
|
int c = 0;
|
||||||
int d;
|
int d;
|
||||||
|
|
||||||
if (bytes * blocks <= 0)
|
if (bytes * blocks <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
blocks = bytes * blocks;
|
blocks *= bytes;
|
||||||
c = 0;
|
|
||||||
|
|
||||||
while (blocks > 0)
|
while (blocks > 0)
|
||||||
{
|
{
|
||||||
@ -66,9 +65,9 @@ static int f_read(void * punt, int bytes, int blocks, int *f)
|
|||||||
if (b > 4096)
|
if (b > 4096)
|
||||||
b = 4096;
|
b = 4096;
|
||||||
|
|
||||||
if (*f >= 0x666 && *f <= 0x669)
|
d = (*f) - 0x666;
|
||||||
|
if((unsigned)(d) <= (0x669 - 0x666))
|
||||||
{
|
{
|
||||||
d = (*f) - 0x666;
|
|
||||||
if (file[d].size == 0)
|
if (file[d].size == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if ((file[d].pos + b) > file[d].size)
|
if ((file[d].pos + b) > file[d].size)
|
||||||
@ -96,11 +95,12 @@ static int f_seek(int *f, ogg_int64_t offset, int mode)
|
|||||||
{
|
{
|
||||||
if(f==NULL) return(-1);
|
if(f==NULL) return(-1);
|
||||||
|
|
||||||
int k, d;
|
int k;
|
||||||
mode &= 3;
|
mode &= 3;
|
||||||
if (*f >= 0x666 && *f <= 0x669)
|
|
||||||
|
int d = (*f) - 0x666;
|
||||||
|
if((unsigned)(d) <= (0x669 - 0x666))
|
||||||
{
|
{
|
||||||
d = (*f) - 0x666;
|
|
||||||
k = 0;
|
k = 0;
|
||||||
|
|
||||||
if (file[d].size == 0)
|
if (file[d].size == 0)
|
||||||
@ -121,7 +121,7 @@ static int f_seek(int *f, ogg_int64_t offset, int mode)
|
|||||||
else
|
else
|
||||||
file[d].pos = offset;
|
file[d].pos = offset;
|
||||||
}
|
}
|
||||||
if (mode == 1)
|
else if (mode == 1)
|
||||||
{
|
{
|
||||||
if ((file[d].pos + offset) >= file[d].size)
|
if ((file[d].pos + offset) >= file[d].size)
|
||||||
{
|
{
|
||||||
@ -136,7 +136,7 @@ static int f_seek(int *f, ogg_int64_t offset, int mode)
|
|||||||
else
|
else
|
||||||
file[d].pos += offset;
|
file[d].pos += offset;
|
||||||
}
|
}
|
||||||
if (mode == 2)
|
else if (mode == 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((file[d].size + offset) >= file[d].size)
|
if ((file[d].size + offset) >= file[d].size)
|
||||||
@ -166,10 +166,9 @@ static int f_seek(int *f, ogg_int64_t offset, int mode)
|
|||||||
|
|
||||||
static int f_close(int *f)
|
static int f_close(int *f)
|
||||||
{
|
{
|
||||||
int d;
|
int d = (*f) - 0x666;
|
||||||
if (*f >= 0x666 && *f <= 0x669)
|
if((unsigned)(d) <= (0x669 - 0x666))
|
||||||
{
|
{
|
||||||
d = (*f) - 0x666;
|
|
||||||
file[d].size = 0;
|
file[d].size = 0;
|
||||||
file[d].pos = 0;
|
file[d].pos = 0;
|
||||||
if (file[d].mem)
|
if (file[d].mem)
|
||||||
@ -185,11 +184,11 @@ static int f_close(int *f)
|
|||||||
|
|
||||||
static long f_tell(int *f)
|
static long f_tell(int *f)
|
||||||
{
|
{
|
||||||
int k, d;
|
int k;
|
||||||
|
|
||||||
if (*f >= 0x666 && *f <= 0x669)
|
int d = (*f) - 0x666;
|
||||||
|
if((unsigned)(d) <= (0x669 - 0x666))
|
||||||
{
|
{
|
||||||
d = (*f) - 0x666;
|
|
||||||
k = file[d].pos;
|
k = file[d].pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -205,8 +204,15 @@ static int mem_open(char * ogg, int size)
|
|||||||
if (one)
|
if (one)
|
||||||
{
|
{
|
||||||
one = 0;
|
one = 0;
|
||||||
for (n = 0; n < 4; n++)
|
|
||||||
file[n].size = 0;
|
file[0].size = 0;
|
||||||
|
file[1].size = 0;
|
||||||
|
file[2].size = 0;
|
||||||
|
file[3].size = 0;
|
||||||
|
file[0].mem = ogg;
|
||||||
|
file[0].size = size;
|
||||||
|
file[0].pos = 0;
|
||||||
|
return (0x666);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < 4; n++)
|
for (n = 0; n < 4; n++)
|
||||||
@ -224,7 +230,7 @@ static int mem_open(char * ogg, int size)
|
|||||||
|
|
||||||
static int mem_close(int fd)
|
static int mem_close(int fd)
|
||||||
{
|
{
|
||||||
if (fd >= 0x666 && fd <= 0x669) // it is a memory file descriptor?
|
if((unsigned)((fd) - 0x666) <= (0x669 - 0x666)) // it is a memory file descriptor?
|
||||||
{
|
{
|
||||||
fd -= 0x666;
|
fd -= 0x666;
|
||||||
file[fd].size = 0;
|
file[fd].size = 0;
|
||||||
@ -353,8 +359,7 @@ static void * ogg_player_thread(private_data_ogg * priv)
|
|||||||
priv[0].seek_time = -1;
|
priv[0].seek_time = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret
|
ret = ov_read(
|
||||||
= ov_read(
|
|
||||||
&priv[0].vf,
|
&priv[0].vf,
|
||||||
(void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
|
(void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
|
||||||
MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section);
|
MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section);
|
||||||
@ -513,8 +518,7 @@ int StatusOgg()
|
|||||||
return 255; // EOF
|
return 255; // EOF
|
||||||
else if (private_ogg.flag & 128)
|
else if (private_ogg.flag & 128)
|
||||||
return 2; // paused
|
return 2; // paused
|
||||||
else
|
return 1; // running
|
||||||
return 1; // running
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetVolumeOgg(int volume)
|
void SetVolumeOgg(int volume)
|
||||||
|
@ -47,7 +47,7 @@ struct _IMGCTX
|
|||||||
png_bytep img_data;
|
png_bytep img_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PNGU Implementation //
|
// PNGU Implementation
|
||||||
|
|
||||||
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
||||||
{
|
{
|
||||||
@ -129,436 +129,6 @@ int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
|
|||||||
return PNGU_OK;
|
return PNGU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PNGU_u32 x, y, buffWidth;
|
|
||||||
|
|
||||||
// width needs to be divisible by two
|
|
||||||
if (width % 2)
|
|
||||||
return PNGU_ODD_WIDTH;
|
|
||||||
|
|
||||||
// stride needs to be divisible by two
|
|
||||||
if (stride % 2)
|
|
||||||
return PNGU_ODD_STRIDE;
|
|
||||||
|
|
||||||
result = pngu_decode (ctx, width, height, 1);
|
|
||||||
if (result != PNGU_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Copy image to the output buffer
|
|
||||||
buffWidth = (width + stride) >> 1;
|
|
||||||
PNGU_u32 wid2 = width >>1;
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
for (x = 0; x < wid2; x++)
|
|
||||||
{
|
|
||||||
PNGU_u32 x6 = x*6;
|
|
||||||
((PNGU_u32 *)buffer)[y*buffWidth+x] = PNGU_RGB8_TO_YCbYCr (*(ctx->row_pointers[y]+x6), *(ctx->row_pointers[y]+x6+1), *(ctx->row_pointers[y]+x6+2),
|
|
||||||
*(ctx->row_pointers[y]+x6+3), *(ctx->row_pointers[y]+x6+4), *(ctx->row_pointers[y]+x6+5));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PNGU_u32 x, y, buffWidth;
|
|
||||||
|
|
||||||
result = pngu_decode (ctx, width, height, 1);
|
|
||||||
if (result != PNGU_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
buffWidth = width + stride;
|
|
||||||
|
|
||||||
// Copy image to the output buffer
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
((PNGU_u16 *)buffer)[y*buffWidth+x] =
|
|
||||||
(((PNGU_u16) (ctx->row_pointers[y][x*3] & 0xF8)) << 8) |
|
|
||||||
(((PNGU_u16) (ctx->row_pointers[y][x*3+1] & 0xFC)) << 3) |
|
|
||||||
(((PNGU_u16) (ctx->row_pointers[y][x*3+2] & 0xF8)) >> 3);
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PNGU_u32 x, y, buffWidth;
|
|
||||||
|
|
||||||
result = pngu_decode (ctx, width, height, 0);
|
|
||||||
if (result != PNGU_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
buffWidth = width + stride;
|
|
||||||
|
|
||||||
// Check is source image has an alpha channel
|
|
||||||
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
|
|
||||||
{
|
|
||||||
// Alpha channel present, copy image to the output buffer
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
memcpy (buffer + (y * buffWidth << 2), ctx->row_pointers[y], width<<2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No alpha channel present, copy image to the output buffer
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
for (x = 0; x < width; x++)
|
|
||||||
((PNGU_u32 *)buffer)[y*buffWidth+x] =
|
|
||||||
(((PNGU_u32) ctx->row_pointers[y][x*3]) << 24) |
|
|
||||||
(((PNGU_u32) ctx->row_pointers[y][x*3+1]) << 16) |
|
|
||||||
(((PNGU_u32) ctx->row_pointers[y][x*3+2]) << 8) |
|
|
||||||
((PNGU_u32) default_alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer)
|
|
||||||
{
|
|
||||||
PNGU_u32 x, y;
|
|
||||||
|
|
||||||
// width and height need to be divisible by four
|
|
||||||
if ((width % 4) || (height % 4))
|
|
||||||
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
|
||||||
|
|
||||||
int result = pngu_decode (ctx, width, height, 1);
|
|
||||||
if (result != PNGU_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Copy image to the output buffer
|
|
||||||
PNGU_u32 qwidth = width >> 2;
|
|
||||||
PNGU_u32 qheight = height >> 2;
|
|
||||||
|
|
||||||
for (y = 0; y < qheight; y++)
|
|
||||||
for (x = 0; x < qwidth; x++)
|
|
||||||
{
|
|
||||||
PNGU_u32 y4 = y << 2;
|
|
||||||
PNGU_u32 x12 = x * 12;
|
|
||||||
int blockbase = (y * qwidth + x) << 2;
|
|
||||||
|
|
||||||
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12));
|
|
||||||
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase] =
|
|
||||||
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
|
||||||
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
|
||||||
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
|
||||||
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
|
||||||
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
|
||||||
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
|
||||||
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
|
||||||
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
|
||||||
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
|
||||||
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
|
||||||
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
|
||||||
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
|
||||||
(((field64 & 0xF800000000000000ULL) | ((field64 & 0xFC000000000000ULL) << 3) | ((field64 & 0xF80000000000ULL) << 5)) |
|
|
||||||
(((field64 & 0xF800000000ULL) << 8) | ((field64 & 0xFC000000ULL) << 11) | ((field64 & 0xF80000ULL) << 13)) |
|
|
||||||
(((field64 & 0xF800ULL) << 16) | ((field64 & 0xFCULL) << 19) | ((field32 & 0xF8000000ULL) >> 11)) |
|
|
||||||
(((field32 & 0xF80000ULL) >> 8) | ((field32 & 0xFC00ULL) >> 5) | ((field32 & 0xF8ULL) >> 3)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
PNGU_u32 x, y, qwidth, qheight;
|
|
||||||
PNGU_u64 alphaMask;
|
|
||||||
|
|
||||||
// width and height need to be divisible by four
|
|
||||||
if ((width % 4) || (height % 4))
|
|
||||||
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
|
||||||
|
|
||||||
result = pngu_decode (ctx, width, height, 0);
|
|
||||||
if (result != PNGU_OK)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
// Init some vars
|
|
||||||
qwidth = width >> 2;
|
|
||||||
qheight = height >> 2;
|
|
||||||
|
|
||||||
// Check is source image has an alpha channel
|
|
||||||
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
|
|
||||||
{
|
|
||||||
// Alpha channel present, copy image to the output buffer
|
|
||||||
for (y = 0; y < qheight; y++)
|
|
||||||
for (x = 0; x < qwidth; x++)
|
|
||||||
{
|
|
||||||
int blockbase = (y * qwidth + x) << 2;
|
|
||||||
|
|
||||||
PNGU_u32 y4 = y << 2;
|
|
||||||
PNGU_u32 x16 = x << 4;
|
|
||||||
|
|
||||||
PNGU_u64 tmp;
|
|
||||||
|
|
||||||
PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16));
|
|
||||||
PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16+8));
|
|
||||||
|
|
||||||
// If first pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
|
|
||||||
if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
|
|
||||||
else
|
|
||||||
tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
|
|
||||||
|
|
||||||
// If second pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
|
|
||||||
if ((fieldA & 0xE0ULL) == 0xE0ULL)
|
|
||||||
tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
|
|
||||||
else
|
|
||||||
tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
|
|
||||||
|
|
||||||
// If third pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
|
|
||||||
if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
|
|
||||||
else
|
|
||||||
tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
|
|
||||||
|
|
||||||
// If fourth pixel is opaque set MSB to 1 and encode colors in RGB555, else set MSB to 0 and encode colors in ARGB3444
|
|
||||||
if ((fieldB & 0xE0ULL) == 0xE0ULL)
|
|
||||||
tmp = tmp | 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
|
|
||||||
else
|
|
||||||
tmp = tmp | ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
|
|
||||||
((PNGU_u64 *) buffer)[blockbase] = tmp;
|
|
||||||
|
|
||||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16));
|
|
||||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16+8));
|
|
||||||
if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
|
|
||||||
|
|
||||||
if ((fieldA & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+1] = tmp;
|
|
||||||
|
|
||||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16));
|
|
||||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16+8));
|
|
||||||
if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
|
|
||||||
|
|
||||||
if ((fieldA & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+2] = tmp;
|
|
||||||
|
|
||||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16));
|
|
||||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16+8));
|
|
||||||
if ((fieldA & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp = 0x8000000000000000ULL | ((fieldA & 0xF800000000000000ULL) >> 1) | ((fieldA & 0xF8000000000000ULL) << 2) | ((fieldA & 0xF80000000000ULL) << 5);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp = ((fieldA & 0xE000000000ULL) << 23) | ((fieldA & 0xF000000000000000ULL) >> 4) | (fieldA & 0xF0000000000000ULL) | ((fieldA & 0xF00000000000ULL) << 4);
|
|
||||||
|
|
||||||
if ((fieldA & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x800000000000ULL | ((fieldA & 0xF8000000ULL) << 15) | ((fieldA & 0xF80000ULL) << 18) | ((fieldA & 0xF800ULL) << 21);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldA & 0xE0ULL) << 39) | ((fieldA & 0xF0000000ULL) << 12) | ((fieldA & 0xF00000ULL) << 16) | ((fieldA & 0xF000ULL) << 20);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE000000000ULL) == 0xE000000000ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x80000000ULL | ((fieldB & 0xF800000000000000ULL) >> 33) | ((fieldB & 0xF8000000000000ULL) >> 30) | ((fieldB & 0xF80000000000ULL) >> 27);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE000000000ULL) >> 9) | ((fieldB & 0xF000000000000000ULL) >> 36) | ((fieldB & 0xF0000000000000ULL) >> 32) | ((fieldB & 0xF00000000000ULL) >> 28);
|
|
||||||
|
|
||||||
if ((fieldB & 0xE0ULL) == 0xE0ULL)
|
|
||||||
// Opaque pixel, so set MSB to 1 and encode colors in RGB555
|
|
||||||
tmp |= 0x8000ULL | ((fieldB & 0xF8000000ULL) >> 17) | ((fieldB & 0xF80000ULL) >> 14) | ((fieldB & 0xF800ULL) >> 11);
|
|
||||||
else
|
|
||||||
// Tranlucid pixel, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
tmp |= ((fieldB & 0xE0ULL) << 7) | ((fieldB & 0xF0000000ULL) >> 20) | ((fieldB & 0xF00000ULL) >> 16) | ((fieldB & 0xF000ULL) >> 12);
|
|
||||||
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+3] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No alpha channel present, copy image to the output buffer
|
|
||||||
default_alpha = (default_alpha >> 5);
|
|
||||||
if (default_alpha == 7)
|
|
||||||
{
|
|
||||||
// The user wants an opaque texture, so set MSB to 1 and encode colors in RGB555
|
|
||||||
alphaMask = 0x8000800080008000ULL;
|
|
||||||
|
|
||||||
for (y = 0; y < qheight; y++)
|
|
||||||
for (x = 0; x < qwidth; x++)
|
|
||||||
{
|
|
||||||
int blockbase = (y * qwidth + x) << 2;
|
|
||||||
|
|
||||||
PNGU_u32 y4 = y << 2;
|
|
||||||
PNGU_u32 x12 = x * 12;
|
|
||||||
|
|
||||||
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12));
|
|
||||||
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase] =
|
|
||||||
alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
|
|
||||||
((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
|
|
||||||
((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
|
|
||||||
((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
|
||||||
alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
|
|
||||||
((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
|
|
||||||
((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
|
|
||||||
((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
|
||||||
alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
|
|
||||||
((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
|
|
||||||
((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
|
|
||||||
((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
|
||||||
alphaMask | ((field64 & 0xF800000000000000ULL) >> 1) | ((field64 & 0xF8000000000000ULL) << 2) |
|
|
||||||
((field64 & 0xF80000000000ULL) << 5) | ((field64 & 0xF800000000ULL) << 7) | ((field64 & 0xF8000000ULL) << 10) |
|
|
||||||
((field64 & 0xF80000ULL) << 13) | ((field64 & 0xF800ULL) << 15) | ((field64 & 0xF8ULL) << 18) |
|
|
||||||
((field32 & 0xF8000000ULL) >> 11) | ((field32 & 0xF80000ULL) >> 9) | ((field32 & 0xF800ULL) >> 6) | ((field32 & 0xF8ULL) >> 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The user wants a translucid texture, so set MSB to 0 and encode colors in ARGB3444
|
|
||||||
default_alpha = (default_alpha << 4);
|
|
||||||
alphaMask = (((PNGU_u64) default_alpha) << 56) | (((PNGU_u64) default_alpha) << 40) |
|
|
||||||
(((PNGU_u64) default_alpha) << 24) | (((PNGU_u64) default_alpha) << 8);
|
|
||||||
|
|
||||||
for (y = 0; y < qheight; y++)
|
|
||||||
for (x = 0; x < qwidth; x++)
|
|
||||||
{
|
|
||||||
int blockbase = (y * qwidth + x) << 2;
|
|
||||||
|
|
||||||
PNGU_u32 y4 = y << 2;
|
|
||||||
PNGU_u32 x12 = x * 12;
|
|
||||||
|
|
||||||
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12));
|
|
||||||
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase] =
|
|
||||||
alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
|
|
||||||
((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
|
|
||||||
((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
|
|
||||||
((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
|
||||||
alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
|
|
||||||
((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
|
|
||||||
((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
|
|
||||||
((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
|
||||||
alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
|
|
||||||
((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
|
|
||||||
((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
|
|
||||||
((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
|
|
||||||
|
|
||||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12));
|
|
||||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8));
|
|
||||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
|
||||||
alphaMask | ((field64 & 0xF000000000000000ULL) >> 4) | (field64 & 0xF0000000000000ULL) | ((field64 & 0xF00000000000ULL) << 4) |
|
|
||||||
((field64 & 0xF000000000ULL) << 4) | ((field64 & 0xF0000000ULL) << 8) | ((field64 & 0xF00000ULL) << 12) |
|
|
||||||
((field64 & 0xF000ULL) << 12) | ((field64 & 0xF0ULL) << 16) | ((field32 & 0xF0000000ULL) >> 12) |
|
|
||||||
((field32 & 0xF00000ULL) >> 12) | ((field32 & 0xF000ULL) >> 8) | ((field32 & 0xF0ULL) >> 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
|
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
@ -694,122 +264,6 @@ int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *bu
|
|||||||
return PNGU_OK;
|
return PNGU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
|
||||||
{
|
|
||||||
png_uint_32 rowbytes;
|
|
||||||
PNGU_u32 x, y, buffWidth;
|
|
||||||
|
|
||||||
// Erase from the context any readed info
|
|
||||||
pngu_free_info (ctx);
|
|
||||||
ctx->propRead = 0;
|
|
||||||
|
|
||||||
// Check if the user has selected a file to write the image
|
|
||||||
if (ctx->source == PNGU_SOURCE_BUFFER);
|
|
||||||
|
|
||||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
{
|
|
||||||
// Open file
|
|
||||||
if (!(ctx->fd = fopen (ctx->filename, "wb")))
|
|
||||||
return PNGU_CANT_OPEN_FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
return PNGU_NO_FILE_SELECTED;
|
|
||||||
|
|
||||||
// Allocation of libpng structs
|
|
||||||
ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
if (!(ctx->png_ptr))
|
|
||||||
{
|
|
||||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
fclose (ctx->fd);
|
|
||||||
return PNGU_LIB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
|
|
||||||
if (!(ctx->info_ptr))
|
|
||||||
{
|
|
||||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
|
||||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
fclose (ctx->fd);
|
|
||||||
return PNGU_LIB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->source == PNGU_SOURCE_BUFFER)
|
|
||||||
{
|
|
||||||
// Installation of our custom data writer function
|
|
||||||
ctx->cursor = 0;
|
|
||||||
png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
|
|
||||||
}
|
|
||||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
{
|
|
||||||
// Default data writer uses function fwrite, so it needs to use our FILE*
|
|
||||||
png_init_io (ctx->png_ptr, ctx->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup output file properties
|
|
||||||
png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
|
||||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
|
||||||
|
|
||||||
// Allocate memory to store the image in RGB format
|
|
||||||
rowbytes = width * 3;
|
|
||||||
if (rowbytes % 4)
|
|
||||||
rowbytes = ((rowbytes >> 2) + 1) << 2;
|
|
||||||
|
|
||||||
ctx->img_data = malloc (rowbytes * height);
|
|
||||||
if (!ctx->img_data)
|
|
||||||
{
|
|
||||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
|
||||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
fclose (ctx->fd);
|
|
||||||
return PNGU_LIB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->row_pointers = malloc (sizeof (png_bytep) * height);
|
|
||||||
if (!ctx->row_pointers)
|
|
||||||
{
|
|
||||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
|
||||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
fclose (ctx->fd);
|
|
||||||
return PNGU_LIB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode YCbYCr image into RGB8 format
|
|
||||||
buffWidth = (width + stride) >> 1;
|
|
||||||
PNGU_u32 wid2 = width >> 1;
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
ctx->row_pointers[y] = ctx->img_data + (y * rowbytes);
|
|
||||||
|
|
||||||
for (x = 0; x < wid2; ++x)
|
|
||||||
{
|
|
||||||
PNGU_u32 x6 = x*6;
|
|
||||||
PNGU_YCbYCr_TO_RGB8 ( ((PNGU_u32 *)buffer)[y*buffWidth+x],
|
|
||||||
((PNGU_u8 *) ctx->row_pointers[y]+x6), ((PNGU_u8 *) ctx->row_pointers[y]+x6+1),
|
|
||||||
((PNGU_u8 *) ctx->row_pointers[y]+x6+2), ((PNGU_u8 *) ctx->row_pointers[y]+x6+3),
|
|
||||||
((PNGU_u8 *) ctx->row_pointers[y]+x6+4), ((PNGU_u8 *) ctx->row_pointers[y]+x6+5) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tell libpng where is our image data
|
|
||||||
png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
|
|
||||||
|
|
||||||
// Write file header and image data
|
|
||||||
png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
|
||||||
|
|
||||||
// Tell libpng we have no more data to write
|
|
||||||
png_write_end (ctx->png_ptr, (png_infop) NULL);
|
|
||||||
|
|
||||||
// Free resources
|
|
||||||
free (ctx->img_data);
|
|
||||||
free (ctx->row_pointers);
|
|
||||||
png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
|
|
||||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
|
||||||
fclose (ctx->fd);
|
|
||||||
|
|
||||||
// Success
|
|
||||||
return PNGU_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
||||||
{
|
{
|
||||||
png_uint_32 rowbytes;
|
png_uint_32 rowbytes;
|
||||||
@ -950,46 +404,6 @@ int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is taken from a libogc example
|
|
||||||
PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2)
|
|
||||||
{
|
|
||||||
PNGU_u32 y1, cb1, cr1, y2, cb2, cr2, cb, cr;
|
|
||||||
|
|
||||||
y1 = (299 * r1 + 587 * g1 + 114 * b1) / 1000;
|
|
||||||
cb1 = (-16874 * r1 - 33126 * g1 + 50000 * b1 + 12800000) / 100000;
|
|
||||||
cr1 = (50000 * r1 - 41869 * g1 - 8131 * b1 + 12800000) / 100000;
|
|
||||||
|
|
||||||
y2 = (299 * r2 + 587 * g2 + 114 * b2) / 1000;
|
|
||||||
cb2 = (-16874 * r2 - 33126 * g2 + 50000 * b2 + 12800000) / 100000;
|
|
||||||
cr2 = (50000 * r2 - 41869 * g2 - 8131 * b2 + 12800000) / 100000;
|
|
||||||
|
|
||||||
cb = (cb1 + cb2) >> 1;
|
|
||||||
cr = (cr1 + cr2) >> 1;
|
|
||||||
|
|
||||||
return (PNGU_u32) ((y1 << 24) | (cb << 16) | (y2 << 8) | cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2)
|
|
||||||
{
|
|
||||||
PNGU_u8 *val = (PNGU_u8 *) &ycbycr;
|
|
||||||
|
|
||||||
float val1 = (float)((int)(val[1]) - 128);
|
|
||||||
float val3 = (float)((int)(val[3]) - 128);
|
|
||||||
|
|
||||||
int r = (int)(1.371f * val3);
|
|
||||||
int g = (int)(- 0.698f * val3 - 0.336f * val1);
|
|
||||||
int b = (int)(1.732f * val1);
|
|
||||||
|
|
||||||
*r1 = pngu_clamp (val[0] + r, 0, 255);
|
|
||||||
*g1 = pngu_clamp (val[0] + g, 0, 255);
|
|
||||||
*b1 = pngu_clamp (val[0] + b, 0, 255);
|
|
||||||
|
|
||||||
*r2 = pngu_clamp (val[2] + r, 0, 255);
|
|
||||||
*g2 = pngu_clamp (val[2] + g, 0, 255);
|
|
||||||
*b2 = pngu_clamp (val[2] + b, 0, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int pngu_info (IMGCTX ctx)
|
int pngu_info (IMGCTX ctx)
|
||||||
{
|
{
|
||||||
png_byte magic[8];
|
png_byte magic[8];
|
||||||
@ -1265,7 +679,6 @@ int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlph
|
|||||||
return PNGU_OK;
|
return PNGU_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pngu_free_info (IMGCTX ctx)
|
void pngu_free_info (IMGCTX ctx)
|
||||||
{
|
{
|
||||||
if (ctx->infoRead)
|
if (ctx->infoRead)
|
||||||
@ -1279,7 +692,6 @@ void pngu_free_info (IMGCTX ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Custom data provider function used for reading from memory buffers.
|
// Custom data provider function used for reading from memory buffers.
|
||||||
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
@ -1288,7 +700,6 @@ void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t
|
|||||||
ctx->cursor += length;
|
ctx->cursor += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Custom data writer function used for writing to memory buffers.
|
// Custom data writer function used for writing to memory buffers.
|
||||||
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||||
{
|
{
|
||||||
@ -1297,14 +708,12 @@ void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t
|
|||||||
ctx->cursor += length;
|
ctx->cursor += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Custom data flusher function used for writing to memory buffers.
|
// Custom data flusher function used for writing to memory buffers.
|
||||||
void pngu_flush_data_to_buffer (png_structp png_ptr)
|
void pngu_flush_data_to_buffer (png_structp png_ptr)
|
||||||
{
|
{
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function used in YCbYCr to RGB decoding
|
// Function used in YCbYCr to RGB decoding
|
||||||
int pngu_clamp (int value, int min, int max)
|
int pngu_clamp (int value, int min, int max)
|
||||||
{
|
{
|
||||||
|
@ -66,26 +66,6 @@ typedef struct
|
|||||||
struct _IMGCTX;
|
struct _IMGCTX;
|
||||||
typedef struct _IMGCTX *IMGCTX;
|
typedef struct _IMGCTX *IMGCTX;
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Pixel conversion *
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
// Macro to convert RGB8 values to RGB565
|
|
||||||
#define PNGU_RGB8_TO_RGB565(r,g,b) ( ((((PNGU_u16) r) & 0xF8U) << 8) | ((((PNGU_u16) g) & 0xFCU) << 3) | (((PNGU_u16) b) >> 3) )
|
|
||||||
|
|
||||||
// Macro to convert RGBA8 values to RGB5A3
|
|
||||||
#define PNGU_RGB8_TO_RGB5A3(r,g,b,a) (PNGU_u16) (((a & 0xE0U) == 0xE0U) ? \
|
|
||||||
(0x8000U | ((((PNGU_u16) r) & 0xF8U) << 7) | ((((PNGU_u16) g) & 0xF8U) << 2) | (((PNGU_u16) b) >> 3)) : \
|
|
||||||
(((((PNGU_u16) a) & 0xE0U) << 7) | ((((PNGU_u16) r) & 0xF0U) << 4) | (((PNGU_u16) g) & 0xF0U) | ((((PNGU_u16) b) & 0xF0U) >> 4)))
|
|
||||||
|
|
||||||
// Function to convert two RGB8 values to YCbYCr
|
|
||||||
PNGU_u32 PNGU_RGB8_TO_YCbYCr (PNGU_u8 r1, PNGU_u8 g1, PNGU_u8 b1, PNGU_u8 r2, PNGU_u8 g2, PNGU_u8 b2);
|
|
||||||
|
|
||||||
// Function to convert an YCbYCr to two RGB8 values.
|
|
||||||
void PNGU_YCbYCr_TO_RGB8 (PNGU_u32 ycbycr, PNGU_u8 *r1, PNGU_u8 *g1, PNGU_u8 *b1, PNGU_u8 *r2, PNGU_u8 *g2, PNGU_u8 *b2);
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Image context handling *
|
* Image context handling *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -107,67 +87,17 @@ void PNGU_ReleaseImageContext (IMGCTX ctx);
|
|||||||
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
|
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
|
||||||
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
|
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Image conversion *
|
* Image conversion *
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
// Expands selected image into an YCbYCr buffer. You need to specify context, image dimensions,
|
|
||||||
// destination address and stride in pixels (stride = buffer width - image width).
|
|
||||||
int PNGU_DecodeToYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
|
||||||
|
|
||||||
// Macro for decoding an image inside a buffer at given coordinates.
|
|
||||||
#define PNGU_DECODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
|
||||||
\
|
|
||||||
PNGU_DecodeToYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
|
||||||
(coordX) * 2, (bufferWidth) - (imgWidth))
|
|
||||||
|
|
||||||
// Expands selected image into a linear RGB565 buffer. You need to specify context, image dimensions,
|
|
||||||
// destination address and stride in pixels (stride = buffer width - image width).
|
|
||||||
int PNGU_DecodeToRGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
|
||||||
|
|
||||||
// Macro for decoding an image inside a buffer at given coordinates.
|
|
||||||
#define PNGU_DECODE_TO_COORDS_RGB565(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
|
||||||
\
|
|
||||||
PNGU_DecodeToRGB565 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
|
||||||
(coordX) * 2, (bufferWidth) - (imgWidth))
|
|
||||||
|
|
||||||
// Expands selected image into a linear RGBA8 buffer. You need to specify context, image dimensions,
|
|
||||||
// destination address, stride in pixels and default alpha value, which is used if the source image
|
|
||||||
// doesn't have an alpha channel.
|
|
||||||
int PNGU_DecodeToRGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride, PNGU_u8 default_alpha);
|
|
||||||
|
|
||||||
// Macro for decoding an image inside a buffer at given coordinates.
|
|
||||||
#define PNGU_DECODE_TO_COORDS_RGBA8(ctx,coordX,coordY,imgWidth,imgHeight,default_alpha,bufferWidth,bufferHeight,buffer) \
|
|
||||||
\
|
|
||||||
PNGU_DecodeToRGBA8 (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
|
||||||
(coordX) * 2, (bufferWidth) - (imgWidth), default_alpha)
|
|
||||||
|
|
||||||
// Expands selected image into a 4x4 tiled RGB565 buffer. You need to specify context, image dimensions
|
|
||||||
// and destination address.
|
|
||||||
int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer);
|
|
||||||
|
|
||||||
// Expands selected image into a 4x4 tiled RGB5A3 buffer. You need to specify context, image dimensions,
|
|
||||||
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
|
||||||
int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
|
||||||
|
|
||||||
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
|
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
|
||||||
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
||||||
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
||||||
|
|
||||||
// Encodes an YCbYCr image in PNG format and stores it in the selected device or memory buffer. You need to
|
|
||||||
// specify context, image dimensions, destination address and stride in pixels (stride = buffer width - image width).
|
|
||||||
int PNGU_EncodeFromYCbYCr (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
|
||||||
|
|
||||||
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||||
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||||
|
|
||||||
// Macro for encoding an image stored into an YCbYCr buffer at given coordinates.
|
|
||||||
#define PNGU_ENCODE_TO_COORDS_YCbYCr(ctx,coordX,coordY,imgWidth,imgHeight,bufferWidth,bufferHeight,buffer) \
|
|
||||||
\
|
|
||||||
PNGU_EncodeFromYCbYCr (ctx, imgWidth, imgHeight, ((void *) buffer) + (coordY) * (bufferWidth) * 2 + \
|
|
||||||
(coordX) * 2, (bufferWidth) - (imgWidth))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user