retrieve user icons

This commit is contained in:
BernardoGiordano 2018-06-09 22:16:29 +02:00
parent c358c577f2
commit 9d98dec931
4 changed files with 145 additions and 27 deletions

View file

@ -31,12 +31,26 @@
#include <string.h>
#include <switch.h>
#include <unordered_map>
#include "draw.hpp"
#include "types.hpp"
extern "C" {
#include "nanojpeg.h"
}
#define USER_ICON_SIZE 96
struct User {
std::string name;
u8* icon;
};
namespace Account
{
Result init(void);
void exit(void);
u8* icon(u128 id);
std::string username(u128 id);
}

View file

@ -82,5 +82,6 @@ void DrawText(u32 font, u32 x, u32 y, color_t clr, const char* text);
void DrawTextTruncate(u32 font, u32 x, u32 y, color_t clr, const char* text, u32 max_width, const char* end_text);
void GetTextDimensions(u32 font, const char* text, u32* width_out, u32* height_out);
void DrawImage(int x, int y, int width, int height, const u8 *image, ImageMode mode);
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight);
#endif

View file

@ -26,7 +26,7 @@
#include "account.hpp"
static std::unordered_map<u128, std::string> mUsernames;
static std::unordered_map<u128, User> mUsers;
Result Account::init(void)
{
@ -35,38 +35,77 @@ Result Account::init(void)
void Account::exit(void)
{
for (auto& value : mUsers)
{
free(value.second.icon);
}
accountExit();
}
static User getUser(u128 id)
{
User user{ "", NULL };
AccountProfile profile;
AccountProfileBase profilebase;
memset(&profilebase, 0, sizeof(profilebase));
if (R_SUCCEEDED(accountGetProfile(&profile, id)) &&
R_SUCCEEDED(accountProfileGet(&profile, NULL, &profilebase)))
{
user.name = std::string(profilebase.username, 0x20);
//load icon
u8* buffer;
size_t image_size, real_size;
if (R_SUCCEEDED(accountProfileGetImageSize(&profile, &image_size)) &&
(buffer = (u8*)malloc(image_size)) != NULL &&
R_SUCCEEDED(accountProfileLoadImage(&profile, buffer, image_size, &real_size)))
{
njInit();
size_t fullsize = 256*256*3;
if (njDecode(buffer, real_size) == NJ_OK &&
njGetWidth() == 256 &&
njGetHeight() == 256 &&
(size_t)njGetImageSize() == fullsize &&
njIsColor() == 1)
{
u8* decoded_buffer = njGetImage();
user.icon = (u8*)malloc(USER_ICON_SIZE*USER_ICON_SIZE*3);
downscaleRGBImg(decoded_buffer, user.icon, 256, 256, USER_ICON_SIZE, USER_ICON_SIZE);
decoded_buffer = NULL;
}
free(buffer);
njDone();
}
}
accountProfileClose(&profile);
return user;
}
std::string Account::username(u128 id)
{
std::unordered_map<u128, std::string>::const_iterator got = mUsernames.find(id);
if (got == mUsernames.end())
std::unordered_map<u128, User>::const_iterator got = mUsers.find(id);
if (got == mUsers.end())
{
// look for a user and add it to the map
AccountProfile profile;
AccountProfileBase profilebase;
char username[0x21] = {0};
memset(&profilebase, 0, sizeof(profilebase));
Result res = accountGetProfile(&profile, id);
if (R_FAILED(res))
{
return "";
}
res = accountProfileGet(&profile, NULL, &profilebase);
if (R_FAILED(res))
{
return "";
}
strncpy(username, profilebase.username, sizeof(username) - 1);
std::string user = std::string(username);
mUsernames.insert({id, user});
accountProfileClose(&profile);
return user;
User user = getUser(id);
mUsers.insert({id, user});
return user.name;
}
return got->second;
return got->second.name;
}
u8* Account::icon(u128 id)
{
std::unordered_map<u128, User>::const_iterator got = mUsers.find(id);
// the null check in the icon is to handle the bad memory issue that isn't yet fixed
if (got == mUsers.end() || got->second.icon == NULL)
{
User user = getUser(id);
mUsers.insert({id, user});
return user.icon;
}
return got->second.icon;
}

View file

@ -355,4 +355,68 @@ void rectangle(u32 x, u32 y, u32 w, u32 h, color_t color)
Draw4PixelsRaw(i, j, color);
}
}
}
void downscaleRGBImg(const u8 *image, u8* out, int srcWidth, int srcHeight, int destWidth, int destHeight)
{
int tmpx, tmpy;
int pos;
float sourceX, sourceY;
float xScale = (float)srcWidth / (float)destWidth;
float yScale = (float)srcHeight / (float)destHeight;
int pixelX, pixelY;
u8 r1, r2, r3, r4;
u8 g1, g2, g3, g4;
u8 b1, b2, b3, b4;
float fx, fy, fx1, fy1;
int w1, w2, w3, w4;
for (tmpx=0; tmpx<destWidth; tmpx++)
{
for (tmpy=0; tmpy<destHeight; tmpy++)
{
sourceX = tmpx * xScale;
sourceY = tmpy * yScale;
pixelX = (int)sourceX;
pixelY = (int)sourceY;
// get colours from four surrounding pixels
pos = ((pixelY + 0) * srcWidth + pixelX + 0) * 3;
r1 = image[pos+0];
g1 = image[pos+1];
b1 = image[pos+2];
pos = ((pixelY + 0) * srcWidth + pixelX + 1) * 3;
r2 = image[pos+0];
g2 = image[pos+1];
b2 = image[pos+2];
pos = ((pixelY + 1) * srcWidth + pixelX + 0) * 3;
r3 = image[pos+0];
g3 = image[pos+1];
b3 = image[pos+2];
pos = ((pixelY + 1) * srcWidth + pixelX + 1) * 3;
r4 = image[pos+0];
g4 = image[pos+1];
b4 = image[pos+2];
// determine weights
fx = sourceX - pixelX;
fy = sourceY - pixelY;
fx1 = 1.0f - fx;
fy1 = 1.0f - fy;
w1 = (int)(fx1*fy1*256.0);
w2 = (int)(fx*fy1*256.0);
w3 = (int)(fx1*fy*256.0);
w4 = (int)(fx*fy*256.0);
// set output pixels
pos = ((tmpy*destWidth) + tmpx) * 3;
out[pos+0] = (u8)((r1 * w1 + r2 * w2 + r3 * w3 + r4 * w4) >> 8);
out[pos+1] = (u8)((g1 * w1 + g2 * w2 + g3 * w3 + g4 * w4) >> 8);
out[pos+2] = (u8)((b1 * w1 + b2 * w2 + b3 * w3 + b4 * w4) >> 8);
}
}
}