#include <base/system.h>
#include <engine/external/pnglite/pnglite.h>
#define IDX(x, y, w) ((x) + (y)*(w))
typedef struct
{
unsigned char r, g, b, a;
} CPixel;
// simple, ugly bilinear sampling..
CPixel sampleBilinear(int x_, int y_, float ratio, CPixel *pData, int w)
{
CPixel sample;
int x = x_ * ratio;
int y = y_ * ratio;
float offsetx = (x_ * ratio) - x;
float offsety = (y_ * ratio) - y;
int index = IDX(x, y, w);
sample.r = pData[index].r * (1-offsetx) * (1-offsety) +
pData[index+1].r * offsetx * (1-offsety) +
pData[index+w].r * (1-offsetx) * offsety +
pData[index+w+1].r * offsetx * offsety;
sample.g = pData[index].g * (1-offsetx) * (1-offsety) +
pData[index+1].g * offsetx * (1-offsety) +
pData[index+w].g * (1-offsetx) * offsety +
pData[index+w+1].g * offsetx * offsety;
sample.b = pData[index].b * (1-offsetx) * (1-offsety) +
pData[index+1].b * offsetx * (1-offsety) +
pData[index+w].b * (1-offsetx) * offsety +
pData[index+w+1].b * offsetx * offsety;
sample.a = pData[index].a * (1-offsetx) * (1-offsety) +
pData[index+1].a * offsetx * (1-offsety) +
pData[index+w].a * (1-offsetx) * offsety +
pData[index+w+1].a * offsetx * offsety;
return sample;
}
int SplitSkin(CPixel *pImg, CPixel *pBody, CPixel *pFeet, CPixel *pEyes, CPixel *pHands)
{
if(!pImg)
return 1;
// Part: body
float ratio = 96.0f/128.0f;
// alpha mask
for(int x = 0; x < 128; x++)
for(int y = 0; y < 128; y++)
pBody[IDX(x,y,256)] = sampleBilinear(x+128, y, ratio, pImg, 256);
// main
for(int x = 128; x < 256; x++)
for(int y = 0; y < 128; y++)
pBody[IDX(x,y,256)] = sampleBilinear(x-128, y, ratio, pImg, 256);
// Part: hands
ratio = 32.0f/64.0f;
for(int x = 0; x < 128; x++)
for(int y = 0; y < 64; y++)
pHands[IDX(x, y, 128)] = sampleBilinear(x+384, y, ratio, pImg, 256);
// TODO: eyes, feet
return 0;
}
int FixSkin(const char *pFileName)
{
png_t Png;
png_init(0, 0);
CPixel *pOrgImg = 0x0;
png_open_file(&Png, pFileName);
if(Png.color_type != PNG_TRUECOLOR_ALPHA)
{
dbg_msg("skin_fix", "%s: not an RGBA image", pFileName);
return 1;
}
int w = Png.width;
int h = Png.height;
pOrgImg = (CPixel *)mem_alloc(w*h*sizeof(CPixel), 1);
png_get_data(&Png, (unsigned char *)pOrgImg);
png_close_file(&Png);
dbg_msg("skin_fix", "processing file: %s", pFileName);
CPixel *pBody = (CPixel *)mem_alloc(256*256*sizeof(CPixel), 1);
mem_zero(pBody, 256*256*sizeof(CPixel));
CPixel *pFeet = (CPixel *)mem_alloc(128*64*sizeof(CPixel), 1);
mem_zero(pFeet, 128*64*sizeof(CPixel));
CPixel *pEyes = (CPixel *)mem_alloc(128*128*sizeof(CPixel), 1);
mem_zero(pEyes, 128*128*sizeof(CPixel));
CPixel *pHands = (CPixel *)mem_alloc(128*64*sizeof(CPixel), 1);
mem_zero(pHands, 128*64*sizeof(CPixel));
SplitSkin(pOrgImg, pBody, pFeet, pEyes, pHands);
// save here
// body
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "body_%s", pFileName);
png_open_file_write(&Png, aBuf);
png_set_data(&Png, 256, 256, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pBody);
png_close_file(&Png);
// hands
str_format(aBuf, sizeof(aBuf), "hands_%s", pFileName);
png_open_file_write(&Png, aBuf);
png_set_data(&Png, 128, 64, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pHands);
png_close_file(&Png);
// feet
str_format(aBuf, sizeof(aBuf), "feet_%s", pFileName);
png_open_file_write(&Png, aBuf);
png_set_data(&Png, 128, 64, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pFeet);
png_close_file(&Png);
// eyes
str_format(aBuf, sizeof(aBuf), "eyes_%s", pFileName);
png_open_file_write(&Png, aBuf);
png_set_data(&Png, 128, 64, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pEyes);
png_close_file(&Png);
// create json file
// split off .png
str_format(aBuf, sizeof(aBuf), "%s", pFileName);
int len = str_length(aBuf);
aBuf[len-4] = 0;
char pJsonFile[2048];
str_format(pJsonFile, 2048,
"{\"skin\": { \n"
"\t\"body\": { \n"
"\t\t\"filename\": \"body_%s\", \n"
"\t\t\"custom_colors\": \"false\" \n"
"\t},\n"
"\t\"hands\": { \n"
"\t\t\"filename\": \"hands_%s\", \n"
"\t\t\"custom_colors\": \"false\" \n"
"\t},\n"
"\t\"feet\": { \n"
"\t\t\"filename\": \"feet_%s\", \n"
"\t\t\"custom_colors\": \"false\" \n"
"\t},\n"
"\t\"eyes\": { \n"
"\t\t\"filename\": \"eyes_%s\", \n"
"\t\t\"custom_colors\": \"false\" \n"
"\t}}\n"
"}"
, aBuf, aBuf, aBuf, aBuf);
char aBufJson[256];
str_format(aBufJson, sizeof(aBufJson), "%s.json", aBuf);
IOHANDLE JsonFile = io_open(aBufJson, IOFLAG_WRITE);
io_write(JsonFile, pJsonFile, str_length(pJsonFile));
io_close(JsonFile);
mem_free(pOrgImg);
mem_free(pBody);
mem_free(pEyes);
mem_free(pHands);
mem_free(pFeet);
return 0;
}
int main(int argc, const char **argv)
{
dbg_logger_stdout();
if(argc == 1)
{
dbg_msg("Usage", "%s FILE1 [ FILE2... ]", argv[0]);
return -1;
}
for(int i = 1; i < argc; i++)
FixSkin(argv[i]);
return 0;
}
As ppl are also complainin about "all skins are lost, crap new skinsystem, blabla" I wrote some small/ugly script to convert 0.6 skins to 0.7 skinsystem. Atm it generates the json file, the hand and the body (missing feet and eyes as I got boring and running out of time (: ).