-added jpg file support for game covers and themes, if no .png

is found, it will just replace the filename extension with .jpg
and try it again, the jpg file width and height need to be
divisable with 4, otherwise wiiflow will just ignore the cover
This commit is contained in:
fix94.1 2012-07-22 22:10:17 +00:00
parent f9a38eff01
commit e8c66b7278
9 changed files with 190 additions and 100 deletions

View File

@ -1848,18 +1848,18 @@ bool CCoverFlow::start(const char *id)
if(m_box)
{
if (m_pngLoadCover.empty() || STexture::TE_OK != m_loadingTexture.fromPNGFile(m_pngLoadCover.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (m_pngLoadCover.empty() || STexture::TE_OK != m_loadingTexture.fromImageFile(m_pngLoadCover.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (STexture::TE_OK != m_loadingTexture.fromPNG(loading_png, GX_TF_CMPR, ALLOC_MEM2, 32, 512)) return false;
if (m_pngNoCover.empty() || STexture::TE_OK != m_noCoverTexture.fromPNGFile(m_pngNoCover.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (m_pngNoCover.empty() || STexture::TE_OK != m_noCoverTexture.fromImageFile(m_pngNoCover.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (STexture::TE_OK != m_noCoverTexture.fromPNG(nopic_png, GX_TF_CMPR, ALLOC_MEM2, 32, 512)) return false;
}
else
{
if (m_pngLoadCoverFlat.empty() || STexture::TE_OK != m_loadingTexture.fromPNGFile(m_pngLoadCoverFlat.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (m_pngLoadCoverFlat.empty() || STexture::TE_OK != m_loadingTexture.fromImageFile(m_pngLoadCoverFlat.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (STexture::TE_OK != m_loadingTexture.fromPNG(flatloading_png, GX_TF_CMPR, ALLOC_MEM2, 32, 512)) return false;
if (m_pngNoCoverFlat.empty() || STexture::TE_OK != m_noCoverTexture.fromPNGFile(m_pngNoCoverFlat.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (m_pngNoCoverFlat.empty() || STexture::TE_OK != m_noCoverTexture.fromImageFile(m_pngNoCoverFlat.c_str(), GX_TF_CMPR, ALLOC_MEM2, 32, 512))
if (STexture::TE_OK != m_noCoverTexture.fromPNG(flatnopic_png, GX_TF_CMPR, ALLOC_MEM2, 32, 512)) return false;
}
@ -2577,7 +2577,7 @@ bool CCoverFlow::_loadCoverTexPNG(u32 i, bool box, bool hq)
STexture tex;
const char *path = box ? m_items[i].boxPicPath.c_str() : m_items[i].picPath.c_str();
if (STexture::TE_OK != tex.fromPNGFile(path, textureFmt, ALLOC_MEM2, 32)) return false;
if (STexture::TE_OK != tex.fromImageFile(path, textureFmt, ALLOC_MEM2, 32)) return false;
if (!m_loadingCovers) return false;

View File

@ -29,7 +29,7 @@ bool CCursor::init(const char *png, bool wideFix, CColor shadowColor, float shad
m_wideFix = wideFix;
m_x = -1;
m_y = -1;
if (STexture::TE_OK != m_texture.fromPNGFile(png, GX_TF_RGBA8))
if (STexture::TE_OK != m_texture.fromImageFile(png))
{
if (chan == 0)
ok = STexture::TE_OK == m_texture.fromPNG(player1_point_png, GX_TF_RGBA8);

View File

@ -38,11 +38,11 @@ bool CFanart::load(Config &m_globalConfig, const char *path, const char *id)
const char *dir = fmt("%s/%s", path, id);
STexture fanBg, fanBgLq;
STexture::TexErr texErr = fanBg.fromPNGFile(fmt("%s/background.png", dir), GX_TF_RGBA8);
STexture::TexErr texErr = fanBg.fromImageFile(fmt("%s/background.png", dir));
if (texErr == STexture::TE_ERROR)
{
dir = fmt("%s/%.3s", path, id);
texErr = fanBg.fromPNGFile(fmt("%s/background.png", dir), GX_TF_RGBA8);
texErr = fanBg.fromImageFile(fmt("%s/background.png", dir));
}
if (texErr == STexture::TE_OK)
@ -50,7 +50,7 @@ bool CFanart::load(Config &m_globalConfig, const char *path, const char *id)
m_cfg.load(fmt("%s/%s.ini", dir, id));
if (!m_cfg.loaded()) m_cfg.load(fmt("%s/%.3s.ini", dir, id));
fanBgLq.fromPNGFile(fmt("%s/background_lq.png", dir), GX_TF_RGBA8);
fanBgLq.fromImageFile(fmt("%s/background_lq.png", dir));
for (int i = 1; i <= 6; i++)
{
@ -176,7 +176,7 @@ void CFanart::draw(bool front)
CFanartElement::CFanartElement(Config &cfg, const char *dir, int artwork)
: m_artwork(artwork), m_isValid(false)
{
m_isValid = m_art.fromPNGFile(fmt("%s/artwork%d.png", dir, artwork), GX_TF_RGBA8) == STexture::TE_OK;
m_isValid = m_art.fromImageFile(fmt("%s/artwork%d.png", dir, artwork)) == STexture::TE_OK;
if (!m_isValid) return;
const char *section = fmt("artwork%d", artwork);

View File

@ -33,48 +33,31 @@ static inline u32 coordsRGB565(u32 x, u32 y, u32 w)
return (((y >> 2) * (w >> 2) + (x >> 2)) << 4) + ((y & 3) << 2) + (x & 3);
}
void STexture::_convertToFlippedRGBA8(u8 *dst, const u8 * src, u32 width, u32 height)
static inline void _convertToFlippedRGBA(u8 *dst, const u8 *src, u32 width, u32 height)
{
u32 block, i, c, ar, gb;
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)
{
u32 y = height - 1 - (c + block);
u32 x = ar + i;
u32 offset = ((((y >> 2) * (width >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
/* Alpha pixels */
dst[offset] = 255;
/* Red pixels */
dst[offset+1] = src[((i + ar) + ((block + c) * width)) * 3];
}
}
/* Green and Blue */
for (c = 0; c < 4; ++c)
{
for (gb = 0; gb < 4; ++gb)
{
u32 y = height - 1 - (c + block);
u32 x = gb + i;
u32 offset = ((((y >> 2) * (width >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
/* Green pixels */
dst[offset+32] = src[(((i + gb) + ((block + c) * width)) * 3) + 1];
/* Blue pixels */
dst[offset+33] = src[(((i + gb) + ((block + c) * width)) * 3) + 2];
}
}
}
}
for(u32 block = 0; block < height; block += 4)
{
for(u32 i = 0; i < width; i += 4)
{
for(u32 c = 0; c < 4; ++c)
{
for(u32 rgb = 0; rgb < 4; ++rgb)
{
u32 y = height - 1 - (c + block);
u32 x = rgb + i;
u32 dst_offset = (x + y * width) * 4;
u32 src_offset = (x + ((block + c) * width)) * 3;
/* RGB */
memcpy(&dst[dst_offset], &src[src_offset], 3);
/* Alpha */
dst[dst_offset + 3] = 0xFF;
}
}
}
}
}
void STexture::_convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height)
static inline void _convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height)
{
for (u32 y = 0; y < height; ++y)
for (u32 x = 0; x < width; ++x)
@ -87,7 +70,7 @@ void STexture::_convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height)
}
}
void STexture::_convertToRGB565(u8 *dst, const u8 *src, u32 width, u32 height)
static inline void _convertToRGB565(u8 *dst, const u8 *src, u32 width, u32 height)
{
u16 *dst16 = (u16 *)dst;
@ -172,7 +155,7 @@ static u32 colorIndices(const u8 *color0, const u8 *color1, const u8 *srcBlock)
return res;
}
void STexture::_convertToCMPR(u8 *dst, const u8 *src, u32 width, u32 height)
static inline void _convertToCMPR(u8 *dst, const u8 *src, u32 width, u32 height)
{
u8 srcBlock[16 * 4];
u8 color0[4];
@ -198,60 +181,170 @@ void STexture::_convertToCMPR(u8 *dst, const u8 *src, u32 width, u32 height)
}
}
STexture::TexErr STexture::fromPNGFile(const char *filename, u8 f, Alloc alloc, u32 minMipSize, u32 maxMipSize)
STexture::TexErr STexture::fromImageFile(const char *filename, u8 f, Alloc alloc, u32 minMipSize, u32 maxMipSize)
{
SmartBuf ptrPng;
FILE *file = fopen(filename, "rb");
if (file == 0) return STexture::TE_ERROR;
if(file == NULL)
{
strncpy((char*)filename+(strlen(filename)-3), "jp", 2);
file = fopen(filename, "rb");
}
if(file == NULL)
return TE_ERROR;
fseek(file, 0, SEEK_END);
u32 fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
if (fileSize > 0)
u8 *Image = NULL;
if(fileSize)
{
ptrPng = smartMem2Alloc(fileSize);
if (!!ptrPng)
if (fread(ptrPng.get(), 1, fileSize, file) != fileSize)
ptrPng.release();
Image = (u8*)MEM2_alloc(fileSize);
if(Image != NULL)
fread(Image, 1, fileSize, file);
}
fclose(file);
return !!ptrPng ? fromPNG(ptrPng.get(), f, alloc, minMipSize, maxMipSize) : STexture::TE_NOMEM;
TexErr result = TE_NOMEM;
if(Image != NULL)
{
if(strstr(filename, ".png") != NULL)
result = fromPNG(Image, f, alloc, minMipSize, maxMipSize);
else
result = fromJPG(Image, fileSize, f, alloc, minMipSize, maxMipSize);
MEM2_free(Image);
}
return result;
}
STexture::TexErr STexture::fromRAW(const u8 *buffer, u32 w, u32 h, Alloc alloc)
STexture::TexErr STexture::fromRAW(const u8 *buffer, u32 w, u32 h, u8 f, Alloc alloc, u32 minMipSize, u32 maxMipSize)
{
SmartBuf rawData;
format = GX_TF_RGBA8;
switch(alloc)
{
case ALLOC_MEM2:
rawData = smartMem2Alloc(GX_GetTexBufferSize(w, h, format, GX_FALSE, 0));
break;
case ALLOC_MALLOC:
rawData = smartMemAlign32(GX_GetTexBufferSize(w, h, format, GX_FALSE, 0));
break;
}
// Convert our raw stuff to a usable format
SmartBuf rawData = smartMem2Alloc(w * h * 4);
if(rawData.get() == NULL)
return STexture::TE_NOMEM;
return TE_NOMEM;
_convertToFlippedRGBA(rawData.get(), buffer, w, h);
//Let the real work begin
SmartBuf tmpData;
u8 maxLODTmp = 0;
u8 minLODTmp = 0;
u32 baseWidth;
u32 baseHeight;
width = w;
height = h;
maxLOD = 0;
STexture::_convertToFlippedRGBA8(rawData.get(), buffer, width, height);
data = rawData;
DCFlushRange(data.get(), GX_GetTexBufferSize(width, height, format, GX_FALSE, 0));
return STexture::TE_OK;
switch(f)
{
case GX_TF_RGBA8:
case GX_TF_RGB565:
case GX_TF_CMPR:
break;
default:
f = GX_TF_RGBA8;
}
format = f;
if (minMipSize > 0 || maxMipSize > 0)
_calcMipMaps(maxLODTmp, minLODTmp, baseWidth, baseHeight, w, h, minMipSize, maxMipSize);
if (maxLODTmp > 0)
{
DCFlushRange(rawData.get(), width * height * 4);
rawData = _genMipMaps(rawData.get(), width, height, maxLODTmp, baseWidth, baseHeight);
if(!rawData)
return TE_NOMEM;
u32 newWidth = baseWidth;
u32 newHeight = baseHeight;
for(int i = 0; i < minLODTmp; ++i)
{
newWidth >>= 1;
newHeight >>= 1;
}
switch(alloc)
{
case ALLOC_MEM2:
tmpData = smartMem2Alloc(fixGX_GetTexBufferSize(newWidth, newHeight, f, GX_TRUE, maxLODTmp - minLODTmp));
break;
case ALLOC_MALLOC:
tmpData = smartMemAlign32(fixGX_GetTexBufferSize(newWidth, newHeight, f, GX_TRUE, maxLODTmp - minLODTmp));
break;
}
u32 nWidth = newWidth;
u32 nHeight = newHeight;
u8 *pSrc = rawData.get();
if (minLODTmp > 0)
pSrc += fixGX_GetTexBufferSize(baseWidth, baseHeight, GX_TF_RGBA8, minLODTmp > 1 ? GX_TRUE : GX_FALSE, minLODTmp - 1);
u8 *pDst = tmpData.get();
for (u8 i = minLODTmp; i <= maxLODTmp; ++i)
{
switch(f)
{
case GX_TF_RGBA8:
_convertToRGBA8(pDst, pSrc, nWidth, nHeight);
break;
case GX_TF_RGB565:
_convertToRGB565(pDst, pSrc, nWidth, nHeight);
break;
case GX_TF_CMPR:
_convertToCMPR(pDst, pSrc, nWidth, nHeight);
break;
}
pSrc += nWidth * nHeight * 4;
pDst += GX_GetTexBufferSize(nWidth, nHeight, f, GX_FALSE, 0);
nWidth >>= 1;
nHeight >>= 1;
}
maxLOD = maxLODTmp - minLODTmp;
width = newWidth;
height = newHeight;
data = tmpData;
DCFlushRange(data.get(), fixGX_GetTexBufferSize(width, height, format, maxLOD > 0 ? GX_TRUE : GX_FALSE, maxLOD));
}
else
{
switch(alloc)
{
case ALLOC_MEM2:
tmpData = smartMem2Alloc(GX_GetTexBufferSize(w, h, format, GX_FALSE, 0));
break;
case ALLOC_MALLOC:
tmpData = smartMemAlign32(GX_GetTexBufferSize(w, h, format, GX_FALSE, 0));
break;
}
if(tmpData.get() == NULL)
{
rawData.release();
return TE_NOMEM;
}
switch(f)
{
case GX_TF_RGBA8:
_convertToRGBA8(tmpData.get(), rawData.get(), width, height);
break;
case GX_TF_RGB565:
_convertToRGB565(tmpData.get(), rawData.get(), width, height);
break;
case GX_TF_CMPR:
_convertToCMPR(tmpData.get(), rawData.get(), width, height);
break;
}
data = tmpData;
DCFlushRange(data.get(), GX_GetTexBufferSize(width, height, format, GX_FALSE, 0));
}
rawData.release();
return TE_OK;
}
STexture::TexErr STexture::fromJPG(const u8 *buffer, const u32 buffer_size)
STexture::TexErr STexture::fromJPG(const u8 *buffer, const u32 buffer_size, u8 f, Alloc alloc, u32 minMipSize, u32 maxMipSize)
{
VideoFrame VideoF;
decodeRealJpeg(buffer, buffer_size, VideoF);
if(!VideoF.getData())
return STexture::TE_ERROR;
return fromRAW(VideoF.getData(), VideoF.getWidth(), VideoF.getHeight());
if(!VideoF.getData() || (VideoF.getWidth() % 4) != 0 || (VideoF.getHeight() % 4) != 0)
return TE_ERROR;
return fromRAW(VideoF.getData(), VideoF.getWidth(), VideoF.getHeight(), f, alloc, minMipSize, maxMipSize);
}
STexture::TexErr STexture::fromPNG(const u8 *buffer, u8 f, Alloc alloc, u32 minMipSize, u32 maxMipSize)
@ -332,13 +425,13 @@ STexture::TexErr STexture::fromPNG(const u8 *buffer, u8 f, Alloc alloc, u32 minM
switch (f)
{
case GX_TF_RGBA8:
STexture::_convertToRGBA8(pDst, pSrc, nWidth, nHeight);
_convertToRGBA8(pDst, pSrc, nWidth, nHeight);
break;
case GX_TF_RGB565:
STexture::_convertToRGB565(pDst, pSrc, nWidth, nHeight);
_convertToRGB565(pDst, pSrc, nWidth, nHeight);
break;
case GX_TF_CMPR:
STexture::_convertToCMPR(pDst, pSrc, nWidth, nHeight);
_convertToCMPR(pDst, pSrc, nWidth, nHeight);
break;
}
pSrc += nWidth * nHeight * 4;

View File

@ -16,20 +16,17 @@ struct STexture
STexture(void) : data(), width(0), height(0), format(-1), maxLOD(0) { }
// Utility funcs
enum TexErr { TE_OK, TE_ERROR, TE_NOMEM };
// Get from PNG, if not found from JPG
TexErr fromImageFile(const char *filename, u8 f = -1, Alloc alloc = ALLOC_MEM2, u32 minMipSize = 0, u32 maxMipSize = 0);
// This function doesn't use MEM2 if the PNG is loaded from memory and there's no mip mapping
TexErr fromPNG(const u8 *buffer, u8 f = -1, Alloc alloc = ALLOC_MEM2, u32 minMipSize = 0, u32 maxMipSize = 0);
TexErr fromPNGFile(const char *filename, u8 f = -1, Alloc alloc = ALLOC_MEM2, u32 minMipSize = 0, u32 maxMipSize = 0);
TexErr fromRAW(const u8 *buffer, u32 w, u32 h, Alloc alloc = ALLOC_MEM2);
TexErr fromJPG(const u8 *buffer, const u32 buffer_size);
TexErr fromRAW(const u8 *buffer, u32 w, u32 h, u8 f = -1, Alloc alloc = ALLOC_MEM2, u32 minMipSize = 0, u32 maxMipSize = 0);
TexErr fromJPG(const u8 *buffer, const u32 buffer_size, u8 f = -1, Alloc alloc = ALLOC_MEM2, u32 minMipSize = 0, u32 maxMipSize = 0);
private:
static void _resize(u8 *dst, u32 dstWidth, u32 dstHeight, const u8 *src, u32 srcWidth, u32 srcHeight);
static void _resizeD2x2(u8 *dst, const u8 *src, u32 srcWidth, u32 srcHeight);
static SmartBuf _genMipMaps(const u8 *src, u32 width, u32 height, u8 maxLOD, u32 lod0Width, u32 lod0Height);
static void _calcMipMaps(u8 &maxLOD, u8 &minLOD, u32 &lod0Width, u32 &lod0Height, u32 width, u32 height, u32 minSize, u32 maxSize);
static void _convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height);
static void _convertToFlippedRGBA8(u8 *dst, const u8 *src, u32 width, u32 height);
static void _convertToRGB565(u8 *dst, const u8 *src, u32 width, u32 height);
static void _convertToCMPR(u8 *dst, const u8 *src, u32 width, u32 height);
};
u32 fixGX_GetTexBufferSize(u16 wd, u16 ht, u32 fmt, u8 mipmap, u8 maxlod);

View File

@ -1187,7 +1187,7 @@ vector<STexture> CMenu::_textures(TexSet &texSet, const char *domain, const char
textures.push_back(i->second);
}
STexture tex;
if (STexture::TE_OK == tex.fromPNGFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str()), GX_TF_RGBA8, ALLOC_MEM2))
if (STexture::TE_OK == tex.fromImageFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str())))
{
texSet[filename] = tex;
textures.push_back(tex);
@ -1212,7 +1212,7 @@ STexture CMenu::_texture(CMenu::TexSet &texSet, const char *domain, const char *
return i->second;
STexture tex;
if (STexture::TE_OK == tex.fromPNGFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str()), GX_TF_RGBA8, ALLOC_MEM2))
if (STexture::TE_OK == tex.fromImageFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str())))
{
def.data.release();
texSet[filename] = tex;

View File

@ -1469,7 +1469,7 @@ void CMenu::_initGameMenu(CMenu::SThemeData &theme)
_addUserLabels(theme, m_gameLblUser, ARRAY_SIZE(m_gameLblUser), "GAME");
m_gameBg = _texture(theme.texSet, "GAME/BG", "texture", theme.bg);
if (m_theme.loaded() && STexture::TE_OK == bgLQ.fromPNGFile(fmt("%s/%s", m_themeDataDir.c_str(), m_theme.getString("GAME/BG", "texture").c_str()), GX_TF_CMPR, ALLOC_MEM2, 64, 64))
if (m_theme.loaded() && STexture::TE_OK == bgLQ.fromImageFile(fmt("%s/%s", m_themeDataDir.c_str(), m_theme.getString("GAME/BG", "texture").c_str()), GX_TF_CMPR, ALLOC_MEM2, 64, 64))
m_gameBgLQ = bgLQ;
m_gameBtnPlay = _addButton(theme, "GAME/PLAY_BTN", theme.btnFont, L"", 420, 344, 200, 56, theme.btnFontColor);

View File

@ -875,7 +875,7 @@ void CMenu::_initMainMenu(CMenu::SThemeData &theme)
STexture emptyTex;
m_mainBg = _texture(theme.texSet, "MAIN/BG", "texture", theme.bg);
if (m_theme.loaded() && STexture::TE_OK == bgLQ.fromPNGFile(fmt("%s/%s", m_themeDataDir.c_str(), m_theme.getString("MAIN/BG", "texture").c_str()), GX_TF_CMPR, ALLOC_MEM2, 64, 64))
if (m_theme.loaded() && STexture::TE_OK == bgLQ.fromImageFile(fmt("%s/%s", m_themeDataDir.c_str(), m_theme.getString("MAIN/BG", "texture").c_str()), GX_TF_CMPR, ALLOC_MEM2, 64, 64))
m_mainBgLQ = bgLQ;
texQuit.fromPNG(btnquit_png);

View File

@ -411,9 +411,9 @@ void CMenu::_initSourceMenu(CMenu::SThemeData &theme)
STexture texConsoleImgs;
ImgName = m_source.getString(fmt("BUTTON_%i", i),"image", "default.png");
texConsoleImg.fromPNGFile(fmt("%s/%s", m_sourceDir.c_str(), ImgName.c_str()), GX_TF_RGBA8, ALLOC_MEM2);
texConsoleImg.fromImageFile(fmt("%s/%s", m_sourceDir.c_str(), ImgName.c_str()));
ImgName = m_source.getString(fmt("BUTTON_%i", i),"image_s", "default.png");
texConsoleImgs.fromPNGFile(fmt("%s/%s", m_sourceDir.c_str(), ImgName.c_str()), GX_TF_RGBA8, ALLOC_MEM2);
texConsoleImgs.fromImageFile(fmt("%s/%s", m_sourceDir.c_str(), ImgName.c_str()));
page = i / 12;
row = (i / 4 ) - (page * 3);