mirror of
https://github.com/GRRLIB/GRRLIB.git
synced 2024-12-23 02:39:19 +00:00
[CHG] Updated PNGU with code from Tantric for the PNGU_DecodeTo4x4RGBA8 function
This commit is contained in:
parent
7771f167c9
commit
54be46f4e4
5 changed files with 120 additions and 131 deletions
|
@ -158,11 +158,12 @@ void GRRLIB_BMFX_Blur (const GRRLIB_texImg *texsrc,
|
|||
|
||||
for (k = x - factor; k <= x + factor; k++) {
|
||||
for (l = y - factor; l <= y + factor; l++) {
|
||||
if (k < 0) { colours[tmp] = thiscol; }
|
||||
else if (k >= texsrc->w) { colours[tmp] = thiscol; }
|
||||
else if (l < 0) { colours[tmp] = thiscol; }
|
||||
else if (l >= texsrc->h) { colours[tmp] = thiscol; }
|
||||
else { colours[tmp] = GRRLIB_GetPixelFromtexImg(k, l, texsrc); }
|
||||
if (k < 0 || k >= texsrc->w || l < 0 || l >= texsrc->h) {
|
||||
colours[tmp] = thiscol;
|
||||
}
|
||||
else {
|
||||
colours[tmp] = GRRLIB_GetPixelFromtexImg(k, l, texsrc);
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,10 +26,15 @@ THE SOFTWARE.
|
|||
/**
|
||||
* Load a file to memory.
|
||||
* @param filename Name of the file to be loaded.
|
||||
* @param data Pointer-to-your-pointer. Ie. { u8 *data; load("file", &data); }.
|
||||
* @param data Pointer-to-your-pointer.
|
||||
* Ie. { u8 *data; GRRLIB_LoadFile("file", &data); }.
|
||||
* It is your responsibility to free the memory allocated by this function.
|
||||
* @return int 0:EmptyFile, -1:FileNotFound, -2:OutOfMemory, -3:FileReadError,
|
||||
* >0 -> FileLength.
|
||||
* @return A integer representating a code:
|
||||
* - 0 : EmptyFile.
|
||||
* - -1 : FileNotFound.
|
||||
* - -2 : OutOfMemory.
|
||||
* - -3 : FileReadError.
|
||||
* - >0 : FileLength.
|
||||
*/
|
||||
int GRRLIB_LoadFile(const char* filename, unsigned char* *data) {
|
||||
int len;
|
||||
|
|
|
@ -127,8 +127,10 @@ GRRLIB_texImg* GRRLIB_LoadTexture (const u8 *my_img) {
|
|||
* Load a texture from a buffer.
|
||||
* @param my_png the PNG buffer to load.
|
||||
* @return A GRRLIB_texImg structure filled with image information.
|
||||
* If image size is not correct, the texture will be completely transparent.
|
||||
*/
|
||||
GRRLIB_texImg* GRRLIB_LoadTexturePNG (const u8 *my_png) {
|
||||
int width = 0, height = 0;
|
||||
PNGUPROP imgProp;
|
||||
IMGCTX ctx;
|
||||
GRRLIB_texImg *my_texture = calloc(1, sizeof(GRRLIB_texImg));
|
||||
|
@ -136,19 +138,16 @@ GRRLIB_texImg* GRRLIB_LoadTexturePNG (const u8 *my_png) {
|
|||
if(my_texture != NULL) {
|
||||
ctx = PNGU_SelectImageFromBuffer(my_png);
|
||||
PNGU_GetImageProperties(ctx, &imgProp);
|
||||
my_texture->data = memalign(32, imgProp.imgWidth * imgProp.imgHeight * 4);
|
||||
my_texture->data = PNGU_DecodeTo4x4RGBA8(ctx, imgProp.imgWidth, imgProp.imgHeight, &width, &height, NULL);
|
||||
if(my_texture->data != NULL) {
|
||||
if(PNGU_DecodeTo4x4RGBA8(ctx, imgProp.imgWidth, imgProp.imgHeight, my_texture->data, 255) == PNGU_OK) {
|
||||
my_texture->w = imgProp.imgWidth;
|
||||
my_texture->h = imgProp.imgHeight;
|
||||
GRRLIB_SetHandle( my_texture, 0, 0 );
|
||||
GRRLIB_FlushTex( my_texture );
|
||||
}
|
||||
else
|
||||
{
|
||||
free(my_texture->data);
|
||||
my_texture->data = NULL;
|
||||
my_texture->w = width;
|
||||
my_texture->h = height;
|
||||
GRRLIB_SetHandle( my_texture, 0, 0 );
|
||||
if(imgProp.imgWidth != width || imgProp.imgHeight != height) {
|
||||
// PGNU has resized the texture
|
||||
memset(my_texture->data, 0, (my_texture->h * my_texture->w) << 2);
|
||||
}
|
||||
GRRLIB_FlushTex( my_texture );
|
||||
}
|
||||
PNGU_ReleaseImageContext(ctx);
|
||||
}
|
||||
|
|
|
@ -556,134 +556,118 @@ int PNGU_DecodeTo4x4RGB5A3 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *b
|
|||
return PNGU_OK;
|
||||
}
|
||||
|
||||
|
||||
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
|
||||
// Coded by Tantric for WiiMC (http://www.wiimc.org)
|
||||
static inline PNGU_u32 coordsRGBA8(PNGU_u32 x, PNGU_u32 y, PNGU_u32 w)
|
||||
{
|
||||
int result;
|
||||
PNGU_u32 x, y, qwidth, qheight;
|
||||
PNGU_u64 alphaMask;
|
||||
return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
|
||||
}
|
||||
|
||||
// width and height need to be divisible by four
|
||||
if ((width % 4) || (height % 4))
|
||||
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
||||
// Coded by Tantric for WiiMC (http://www.wiimc.org)
|
||||
PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, int * dstWidth, int * dstHeight, PNGU_u8 *dstPtr)
|
||||
{
|
||||
PNGU_u8 default_alpha = 255; // default alpha value, which is used if the source image doesn't have an alpha channel.
|
||||
PNGU_u8 *dst;
|
||||
int x, y, x2=0, y2=0, offset;
|
||||
int xRatio = 0, yRatio = 0;
|
||||
png_byte *pixel;
|
||||
|
||||
result = pngu_decode (ctx, width, height, 0);
|
||||
if (result != PNGU_OK)
|
||||
return result;
|
||||
if (pngu_decode (ctx, width, height, 0) != PNGU_OK)
|
||||
return NULL;
|
||||
|
||||
// Init some variables
|
||||
qwidth = width / 4;
|
||||
qheight = height / 4;
|
||||
int newWidth = width;
|
||||
int newHeight = height;
|
||||
|
||||
// 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) )
|
||||
if(width > 1024 || height > 1024)
|
||||
{
|
||||
// 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) * 8;
|
||||
float ratio = (float)width/(float)height;
|
||||
|
||||
PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16));
|
||||
PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+4] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+5] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+6] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+7] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
}
|
||||
if(ratio > 1)
|
||||
{
|
||||
newWidth = 1024;
|
||||
newHeight = 1024/ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
newWidth = 1024*ratio;
|
||||
newHeight = 1024;
|
||||
}
|
||||
xRatio = (int)((width<<16)/newWidth)+1;
|
||||
yRatio = (int)((height<<16)/newHeight)+1;
|
||||
}
|
||||
|
||||
int padWidth = newWidth;
|
||||
int padHeight = newHeight;
|
||||
if(padWidth%4) padWidth += (4-padWidth%4);
|
||||
if(padHeight%4) padHeight += (4-padHeight%4);
|
||||
|
||||
int len = (padWidth * padHeight) << 2;
|
||||
if(len%32) len += (32-len%32);
|
||||
|
||||
if(dstPtr)
|
||||
dst = dstPtr; // use existing allocation
|
||||
else
|
||||
dst = memalign (32, len);
|
||||
|
||||
if(!dst)
|
||||
return NULL;
|
||||
|
||||
for (y = 0; y < padHeight; y++)
|
||||
{
|
||||
// No alpha channel present, copy image to the output buffer
|
||||
alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
|
||||
(((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
|
||||
for (x = 0; x < padWidth; x++)
|
||||
{
|
||||
offset = coordsRGBA8(x, y, padWidth);
|
||||
|
||||
for (y = 0; y < qheight; y++)
|
||||
for (x = 0; x < qwidth; x++)
|
||||
if(y >= newHeight || x >= newWidth)
|
||||
{
|
||||
int blockbase = (y * qwidth + x) * 8;
|
||||
|
||||
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4]+x*12));
|
||||
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4]+x*12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+4] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+1]+x*12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+1]+x*12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+5] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+2]+x*12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+2]+x*12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+6] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y*4+3]+x*12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y*4+3]+x*12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+7] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
dst[offset] = 0;
|
||||
dst[offset+1] = 255;
|
||||
dst[offset+32] = 255;
|
||||
dst[offset+33] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(xRatio > 0)
|
||||
{
|
||||
x2 = ((x*xRatio)>>16);
|
||||
y2 = ((y*yRatio)>>16);
|
||||
}
|
||||
|
||||
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA ||
|
||||
ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
if(xRatio > 0)
|
||||
pixel = &(ctx->row_pointers[y2][x2*4]);
|
||||
else
|
||||
pixel = &(ctx->row_pointers[y][x*4]);
|
||||
|
||||
dst[offset] = pixel[3]; // Alpha
|
||||
dst[offset+1] = pixel[0]; // Red
|
||||
dst[offset+32] = pixel[1]; // Green
|
||||
dst[offset+33] = pixel[2]; // Blue
|
||||
}
|
||||
else
|
||||
{
|
||||
if(xRatio > 0)
|
||||
pixel = &(ctx->row_pointers[y2][x2*3]);
|
||||
else
|
||||
pixel = &(ctx->row_pointers[y][x*3]);
|
||||
|
||||
dst[offset] = default_alpha; // Alpha
|
||||
dst[offset+1] = pixel[0]; // Red
|
||||
dst[offset+32] = pixel[1]; // Green
|
||||
dst[offset+33] = pixel[2]; // Blue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Free resources
|
||||
free (ctx->img_data);
|
||||
free (ctx->row_pointers);
|
||||
|
||||
// Success
|
||||
return PNGU_OK;
|
||||
*dstWidth = padWidth;
|
||||
*dstHeight = padHeight;
|
||||
return dst;
|
||||
}
|
||||
|
||||
// Coded by Tantric for libwiigui (http://code.google.com/p/libwiigui)
|
||||
|
|
|
@ -150,8 +150,8 @@ int PNGU_DecodeTo4x4RGB565 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *b
|
|||
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,
|
||||
// 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);
|
||||
// destination address.
|
||||
PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, int * dstWidth, int * dstHeight, PNGU_u8 *dstPtr);
|
||||
|
||||
// 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).
|
||||
|
|
Loading…
Reference in a new issue