mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-12-01 15:44:19 +01:00
ed2ac8f085
NOTE: The images used right now for the theme loader are made out of our old images and if someone can make some new ones go ahead. The themes are downloaded to the path you can set up. The downloaded preview images are cached at "<set up theme downloadpath>/tmp/". The widescreenfix isn't implemented there yet because images will probably be changed. *Started 3rd SettingsPage *Added JPEG Loading GuiImageData function and 4x4RGBA converter by r-win from WiiXplorer *Added ZipFile Class from WiiXplorer *Added StringToMD5 and MD5ToString to MD5 functions and made it undependable of platform
447 lines
9.4 KiB
C++
447 lines
9.4 KiB
C++
/****************************************************************************
|
|
* libwiigui
|
|
*
|
|
* Tantric 2009
|
|
*
|
|
* gui_imagedata.cpp
|
|
*
|
|
* LoadJpeg copyright by r-win for WiiXplorer
|
|
* check WiiXplorer source for license conditions
|
|
*
|
|
* GUI class definitions
|
|
***************************************************************************/
|
|
|
|
#include "gui.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#include <jpeglib.h>
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#define new_width 640
|
|
#define new_height 480
|
|
|
|
/**
|
|
* Constructor for the GuiImageData class.
|
|
*/
|
|
|
|
extern int idiotFlag;
|
|
extern char idiotChar[50];
|
|
GuiImageData::GuiImageData(const u8 * img)
|
|
{
|
|
data = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
|
|
if(img)
|
|
{
|
|
PNGUPROP imgProp;
|
|
IMGCTX ctx = PNGU_SelectImageFromBuffer(img);
|
|
|
|
if(!ctx)
|
|
return;
|
|
|
|
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
|
//if (((4%imgProp.imgWidth)!=0)||((4%imgProp.imgHeight)!=0))idiotFlag=1;
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
|
|
if(len%32) len += (32-len%32);
|
|
data = (u8 *)memalign (32, len);
|
|
|
|
if(data)
|
|
{
|
|
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
width = imgProp.imgWidth;
|
|
height = imgProp.imgHeight;
|
|
DCFlushRange(data, len);
|
|
}
|
|
else
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
idiotFlag=1;
|
|
snprintf(idiotChar, sizeof(idiotChar), "%s", img);
|
|
|
|
}
|
|
}
|
|
}
|
|
PNGU_ReleaseImageContext (ctx);
|
|
}
|
|
}
|
|
|
|
GuiImageData::GuiImageData(const u8 * img, int imgSize)
|
|
{
|
|
data = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
|
|
if(img)
|
|
{
|
|
if (img[0] == 0xFF && img[1] == 0xD8) { // IMAGE_JPEG
|
|
LoadJpeg(img, imgSize);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Constructor for the GuiImageData class.
|
|
*/
|
|
GuiImageData::GuiImageData(const char * imgPath, const u8 * buffer)
|
|
{
|
|
data = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
|
|
if(imgPath)
|
|
{
|
|
PNGUPROP imgProp;
|
|
IMGCTX ctx = PNGU_SelectImageFromDevice(imgPath);
|
|
//if (((4%imgProp.imgWidth)!=0)||((4%imgProp.imgHeight)!=0))idiotFlag=1;
|
|
|
|
if(ctx)
|
|
{
|
|
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
|
|
if(len%32) len += (32-len%32);
|
|
data = (u8 *)memalign (32, len);
|
|
|
|
if(data)
|
|
{
|
|
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
width = imgProp.imgWidth;
|
|
height = imgProp.imgHeight;
|
|
DCFlushRange(data, len);
|
|
}
|
|
else
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
idiotFlag=1;
|
|
snprintf(idiotChar, sizeof(idiotChar), "%s", imgPath);
|
|
}
|
|
}
|
|
}
|
|
PNGU_ReleaseImageContext (ctx);
|
|
}
|
|
}
|
|
|
|
if (!data) //use buffer data instead
|
|
{
|
|
width = 0;
|
|
height = 0;
|
|
if(buffer)
|
|
{
|
|
PNGUPROP imgProp;
|
|
IMGCTX ctx = PNGU_SelectImageFromBuffer(buffer);
|
|
|
|
if(!ctx)
|
|
return;
|
|
|
|
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
|
|
if(len%32) len += (32-len%32);
|
|
data = (u8 *)memalign (32, len);
|
|
|
|
if(data)
|
|
{
|
|
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
width = imgProp.imgWidth;
|
|
height = imgProp.imgHeight;
|
|
DCFlushRange(data, len);
|
|
}
|
|
else
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
}
|
|
}
|
|
}
|
|
PNGU_ReleaseImageContext (ctx);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructor for the GuiImageData class.
|
|
*/
|
|
GuiImageData::GuiImageData(const char *path, const char *file, const u8 *buffer, bool force_widescreen/*=false*/, const u8 *wbuffer/*=NULL*/)
|
|
{
|
|
data = NULL;
|
|
width = 0;
|
|
height = 0;
|
|
char path_4_3[100];
|
|
char path_16_9[100];
|
|
char *imgPath;
|
|
|
|
snprintf(path_4_3, sizeof(path_4_3), "%s%s", path, file);
|
|
if(force_widescreen)
|
|
{
|
|
snprintf(path_16_9, sizeof(path_16_9), "%sw%s", path, file);
|
|
imgPath = path_16_9;
|
|
if(wbuffer)
|
|
buffer = wbuffer;
|
|
}
|
|
else
|
|
imgPath = path_4_3;
|
|
|
|
for(;;)
|
|
{
|
|
if(imgPath)
|
|
{
|
|
PNGUPROP imgProp;
|
|
IMGCTX ctx = PNGU_SelectImageFromDevice(imgPath);
|
|
//if (((4%imgProp.imgWidth)!=0)||((4%imgProp.imgHeight)!=0))idiotFlag=1;
|
|
|
|
if(ctx)
|
|
{
|
|
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
|
|
if(len%32) len += (32-len%32);
|
|
data = (u8 *)memalign (32, len);
|
|
|
|
if(data)
|
|
{
|
|
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
width = imgProp.imgWidth;
|
|
height = imgProp.imgHeight;
|
|
DCFlushRange(data, len);
|
|
}
|
|
else
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
idiotFlag=1;
|
|
snprintf(idiotChar, sizeof(idiotChar), "%s", imgPath);
|
|
}
|
|
}
|
|
}
|
|
PNGU_ReleaseImageContext (ctx);
|
|
}
|
|
}
|
|
if(data || imgPath == path_4_3)
|
|
break;
|
|
imgPath = path_4_3;
|
|
}
|
|
|
|
if (!data) //use buffer data instead
|
|
{
|
|
width = 0;
|
|
height = 0;
|
|
if(buffer)
|
|
{
|
|
PNGUPROP imgProp;
|
|
IMGCTX ctx = PNGU_SelectImageFromBuffer(buffer);
|
|
|
|
if(!ctx)
|
|
return;
|
|
|
|
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
|
|
if(len%32) len += (32-len%32);
|
|
data = (u8 *)memalign (32, len);
|
|
|
|
if(data)
|
|
{
|
|
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
|
|
|
if(res == PNGU_OK)
|
|
{
|
|
width = imgProp.imgWidth;
|
|
height = imgProp.imgHeight;
|
|
DCFlushRange(data, len);
|
|
}
|
|
else
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
}
|
|
}
|
|
}
|
|
PNGU_ReleaseImageContext (ctx);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Destructor for the GuiImageData class.
|
|
*/
|
|
GuiImageData::~GuiImageData()
|
|
{
|
|
if(data)
|
|
{
|
|
free(data);
|
|
data = NULL;
|
|
}
|
|
}
|
|
|
|
u8 * GuiImageData::GetImage()
|
|
{
|
|
return data;
|
|
}
|
|
|
|
int GuiImageData::GetWidth()
|
|
{
|
|
return width;
|
|
}
|
|
|
|
int GuiImageData::GetHeight()
|
|
{
|
|
return height;
|
|
}
|
|
void GuiImageData::SetGrayscale(void)
|
|
{
|
|
GXColor color;
|
|
u32 offset, gray;
|
|
|
|
for(int x = 0; x < width; x++) {
|
|
for(int y = 0; y < height; y++) {
|
|
offset = (((y >> 2)<<4)*width) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
|
|
color.r = *(data+offset+1);
|
|
color.g = *(data+offset+32);
|
|
color.b = *(data+offset+33);
|
|
|
|
gray = (77*color.r + 150*color.g + 28*color.b)/255;
|
|
|
|
*(data+offset+1) = gray;
|
|
*(data+offset+32) = gray;
|
|
*(data+offset+33) = gray;
|
|
}
|
|
}
|
|
}
|
|
|
|
// This function finds it's origin in GRRLIB, which can be found here: http://code.google.com/p/grrlib/
|
|
void GuiImageData::LoadJpeg(const u8 *img, int imgSize)
|
|
{
|
|
struct jpeg_decompress_struct cinfo;
|
|
struct jpeg_error_mgr jerr;
|
|
|
|
int n = imgSize;
|
|
|
|
while (n > 1) {
|
|
if (img[n - 1] == 0xff && img[n] == 0xd9) {
|
|
break;
|
|
}
|
|
n--;
|
|
}
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
cinfo.err = jpeg_std_error(&jerr);
|
|
cinfo.progress = NULL;
|
|
jpeg_memory_src(&cinfo, img, n);
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
jpeg_calc_output_dimensions(&cinfo);
|
|
|
|
if (cinfo.output_width > new_width || cinfo.output_height > new_height)
|
|
{
|
|
float factor = (cinfo.output_width > cinfo.output_height) ? (1.0 * cinfo.output_width) / new_width : (1.0 * cinfo.output_height) / new_height;
|
|
cinfo.scale_num = 1;
|
|
cinfo.scale_denom = factor;
|
|
cinfo.do_fancy_upsampling = true;
|
|
cinfo.do_block_smoothing = false;
|
|
cinfo.dct_method = JDCT_IFAST;
|
|
}
|
|
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
int rowsize = cinfo.output_width * cinfo.num_components;
|
|
unsigned char *tempBuffer = (unsigned char *) malloc(rowsize * cinfo.output_height);
|
|
|
|
JSAMPROW row_pointer[1];
|
|
|
|
row_pointer[0] = (unsigned char*) malloc(rowsize);
|
|
size_t location = 0;
|
|
while (cinfo.output_scanline < cinfo.output_height) {
|
|
jpeg_read_scanlines(&cinfo, row_pointer, 1);
|
|
memcpy(tempBuffer + location, row_pointer[0], rowsize);
|
|
location += rowsize;
|
|
}
|
|
|
|
int len = ((cinfo.output_width+3)>>2)*((cinfo.output_height+3)>>2)*32*2;
|
|
|
|
data = (u8 *) memalign(32, len);
|
|
|
|
RawTo4x4RGBA(tempBuffer, data, cinfo.output_width, cinfo.output_height);
|
|
DCFlushRange(data, len);
|
|
|
|
width = cinfo.output_width;
|
|
height = cinfo.output_height;
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
free(row_pointer[0]);
|
|
free(tempBuffer);
|
|
}
|
|
|
|
/**
|
|
* Convert a raw bmp (RGB, no alpha) to 4x4RGBA.
|
|
* @author DragonMinded
|
|
* @param src
|
|
* @param dst
|
|
* @param width
|
|
* @param height
|
|
*/
|
|
void GuiImageData::RawTo4x4RGBA(const unsigned char *src, void *dst, const unsigned int width, const unsigned int height)
|
|
{
|
|
unsigned int block;
|
|
unsigned int i;
|
|
unsigned int c;
|
|
unsigned int ar;
|
|
unsigned int gb;
|
|
unsigned char *p = (unsigned char*)dst;
|
|
|
|
for (block = 0; block < height; block += 4) {
|
|
for (i = 0; i < width; i += 4) {
|
|
/* Alpha and Red */
|
|
for (c = 0; c < 4; ++c) {
|
|
for (ar = 0; ar < 4; ++ar) {
|
|
/* Alpha pixels */
|
|
*p++ = 255;
|
|
/* Red pixels */
|
|
*p++ = src[((i + ar) + ((block + c) * width)) * 3];
|
|
}
|
|
}
|
|
|
|
/* Green and Blue */
|
|
for (c = 0; c < 4; ++c) {
|
|
for (gb = 0; gb < 4; ++gb) {
|
|
/* Green pixels */
|
|
*p++ = src[(((i + gb) + ((block + c) * width)) * 3) + 1];
|
|
/* Blue pixels */
|
|
*p++ = src[(((i + gb) + ((block + c) * width)) * 3) + 2];
|
|
}
|
|
}
|
|
} /* i */
|
|
} /* block */
|
|
}
|