Skip to content
Permalink
Browse files

If non-alex area of skin arms are completely black, treat as alex skin

This fixes skins saved by services that lose transparency
  • Loading branch information...
UnknownShadow200 committed May 10, 2019
1 parent 0999a1b commit cea7f095bb921ac963e5a01a9c20bece84468ace
Showing with 26 additions and 9 deletions.
  1. +4 −4 src/Entity.c
  2. +1 −1 src/Game.c
  3. +20 −3 src/Utils.c
  4. +1 −1 src/Utils.h
@@ -660,13 +660,13 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
}

/* only perform filtering when the entire hat is opaque */
uint32_t fullWhite = PackedCol_ARGB(255, 255, 255, 255);
uint32_t fullBlack = PackedCol_ARGB(0, 0, 0, 255);
uint32_t white = PackedCol_ARGB(255, 255, 255, 255);
uint32_t black = PackedCol_ARGB(0, 0, 0, 255);
for (y = 0; y < sizeY; y++) {
uint32_t* row = Bitmap_RawRow(bmp, y) + sizeX;
for (x = 0; x < sizeX; x++) {
uint32_t pixel = row[x];
if (pixel == fullWhite || pixel == fullBlack) row[x] = 0;
if (pixel == white || pixel == black) row[x] = 0;
}
}
}
@@ -730,7 +730,7 @@ static void Player_CheckSkin(struct Player* p) {
Gfx_DeleteTexture(&e->TextureId);
Player_SetSkinAll(p, true);
Player_EnsurePow2(p, &bmp);
e->SkinType = Utils_GetSkinType(&bmp);
e->SkinType = Utils_CalcSkinType(&bmp);

if (bmp.Width > Gfx.MaxTexWidth || bmp.Height > Gfx.MaxTexHeight) {
Chat_Add1("&cSkin %s is too large", &skin);
@@ -237,7 +237,7 @@ bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, const String*
success = !res && Game_ValidateBitmap(file, &bmp);
if (success) {
Gfx_DeleteTexture(texId);
if (skinType) { *skinType = Utils_GetSkinType(&bmp); }
if (skinType) { *skinType = Utils_CalcSkinType(&bmp); }
*texId = Gfx_CreateTexture(&bmp, true, false);
}

@@ -140,14 +140,31 @@ int Utils_AccumulateWheelDelta(float* accumulator, float delta) {
return steps;
}

uint8_t Utils_GetSkinType(const Bitmap* bmp) {
/* Checks if an area is completely black, so Alex skins edited with Microsoft Paint are still treated as Alex */
static bool Utils_IsAllBlack(const Bitmap* bmp, int x1, int y1, int width, int height) {
uint32_t black = PackedCol_ARGB(0, 0, 0, 255);
int x, y;
for (y = y1; y < y1 + height; y++) {
uint32_t* row = Bitmap_RawRow(bmp, y);

for (x = x1; x < x1 + width; x++) {
if (row[x] != black) return false;
}
}
return true;
}

uint8_t Utils_CalcSkinType(const Bitmap* bmp) {
int scale;
if (bmp->Width == bmp->Height * 2) return SKIN_64x32;
if (bmp->Width != bmp->Height) return SKIN_INVALID;

/* Minecraft alex skins have this particular pixel with alpha of 0 */
scale = bmp->Width / 64;
return Bitmap_GetPixel(bmp, 54 * scale, 20 * scale).A >= 127 ? SKIN_64x64 : SKIN_64x64_SLIM;
/* Minecraft alex skins have this particular pixel with alpha of 0 */
if (Bitmap_GetPixel(bmp, 54 * scale, 20 * scale).A < 128) return SKIN_64x64_SLIM;

return Utils_IsAllBlack(bmp, 54 * scale, 20 * scale, 2 * scale, 12 * scale)
&& Utils_IsAllBlack(bmp, 50 * scale, 16 * scale, 2 * scale, 4 * scale) ? SKIN_64x64_SLIM : SKIN_64x64;
}

uint32_t Utils_CRC32(const uint8_t* data, uint32_t length) {
@@ -40,7 +40,7 @@ void Utils_UNSAFE_GetFilename(STRING_REF String* path);
int Utils_AccumulateWheelDelta(float* accumulator, float delta);
#define Utils_AdjViewDist(value) ((int)(1.4142135f * (value)))

uint8_t Utils_GetSkinType(const Bitmap* bmp);
uint8_t Utils_CalcSkinType(const Bitmap* bmp);
uint32_t Utils_CRC32(const uint8_t* data, uint32_t length);
/* CRC32 lookup table, for faster CRC32 calculations. */
/* NOTE: This cannot be just indexed by byte value - see Utils_CRC32 implementation. */

0 comments on commit cea7f09

Please sign in to comment.
You can’t perform that action at this time.