diff --git a/GRRLIB/GRRLIB/GRRLIB_bmfx.c b/GRRLIB/GRRLIB/GRRLIB_bmfx.c index 3c9cf7b..cef02f9 100644 --- a/GRRLIB/GRRLIB/GRRLIB_bmfx.c +++ b/GRRLIB/GRRLIB/GRRLIB_bmfx.c @@ -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++; } } diff --git a/GRRLIB/GRRLIB/GRRLIB_fileIO.c b/GRRLIB/GRRLIB/GRRLIB_fileIO.c index 5bbd2b1..5d4e059 100644 --- a/GRRLIB/GRRLIB/GRRLIB_fileIO.c +++ b/GRRLIB/GRRLIB/GRRLIB_fileIO.c @@ -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; diff --git a/GRRLIB/GRRLIB/GRRLIB_texEdit.c b/GRRLIB/GRRLIB/GRRLIB_texEdit.c index 5b25b67..553197d 100644 --- a/GRRLIB/GRRLIB/GRRLIB_texEdit.c +++ b/GRRLIB/GRRLIB/GRRLIB_texEdit.c @@ -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); } diff --git a/GRRLIB/lib/pngu/pngu.c b/GRRLIB/lib/pngu/pngu.c index 16cefd9..bc897eb 100644 --- a/GRRLIB/lib/pngu/pngu.c +++ b/GRRLIB/lib/pngu/pngu.c @@ -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) diff --git a/GRRLIB/lib/pngu/pngu.h b/GRRLIB/lib/pngu/pngu.h index e1e20b6..24ab272 100644 --- a/GRRLIB/lib/pngu/pngu.h +++ b/GRRLIB/lib/pngu/pngu.h @@ -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).