From 51f09e1526ab6144043e8213ffd66939dfe47c81 Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 9 Nov 2007 15:03:13 +0000 Subject: [PATCH] add new console command "fixtrans", usage: fixtrans gfx/foo.tga - writes a new fixtrans/gfx/foo.tga with alpha-zero pixels changed to values around them. Helps with weird seams on badly made transparent images. git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7672 d7cf8633-e32d-0410-b094-e92efae38249 --- host_cmd.c | 3 ++ image.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++ image.h | 3 ++ 3 files changed, 147 insertions(+) diff --git a/host_cmd.c b/host_cmd.c index 8bb5e69a..578a2b87 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "sv_demo.h" +#include "image.h" int current_skill; cvar_t sv_cheats = {0, "sv_cheats", "0", "enables cheat commands in any game, and cheat impulses in dpmod"}; @@ -2496,6 +2497,8 @@ void Host_InitCommands (void) Cmd_AddCommand_WithClientCommand ("pings", NULL, Host_Pings_f, "command sent by clients to request updated ping and packetloss of players on scoreboard (originally from QW, but also used on NQ servers)"); Cmd_AddCommand ("pingplreport", Host_PingPLReport_f, "command sent by server containing client ping and packet loss values for scoreboard, triggered by pings command from client (not used by QW servers)"); + Cmd_AddCommand ("fixtrans", Image_FixTransparentPixels_f, "change alpha-zero pixels in an image file to sensible values, and write out a new TGA (warning: SLOW)"); + Cvar_RegisterVariable (&team); Cvar_RegisterVariable (&skin); Cvar_RegisterVariable (&noaim); diff --git a/image.c b/image.c index bc58a724..9d60244b 100644 --- a/image.c +++ b/image.c @@ -918,6 +918,147 @@ rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, int ma return rt; } +void fixtransparentpixels(unsigned char *data, int w, int h) +{ + int const FIXTRANS_NEEDED = 1; + int const FIXTRANS_HAS_L = 2; + int const FIXTRANS_HAS_R = 4; + int const FIXTRANS_HAS_U = 8; + int const FIXTRANS_HAS_D = 16; + int const FIXTRANS_FIXED = 32; + unsigned char *fixMask = Mem_Alloc(tempmempool, w * h); + int fixPixels = 0; + int changedPixels = 0; + int x, y; + +#define FIXTRANS_PIXEL (y*w+x) +#define FIXTRANS_PIXEL_U (((y+h-1)%h)*w+x) +#define FIXTRANS_PIXEL_D (((y+1)%h)*w+x) +#define FIXTRANS_PIXEL_L (y*w+((x+w-1)%w)) +#define FIXTRANS_PIXEL_R (y*w+((x+1)%w)) + + memset(fixMask, 0, w * h); + for(y = 0; y < h; ++y) + for(x = 0; x < w; ++x) + { + if(data[FIXTRANS_PIXEL * 4 + 3] == 0) + { + fixMask[FIXTRANS_PIXEL] |= FIXTRANS_NEEDED; + ++fixPixels; + } + else + { + fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U; + fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D; + fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L; + fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R; + } + } + if(fixPixels == w * h) + return; // sorry, can't do anything about this + while(fixPixels) + { + Con_Printf(" %d pixels left to fix...\n", fixPixels); + for(y = 0; y < h; ++y) + for(x = 0; x < w; ++x) + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_NEEDED) + { + unsigned int sumR = 0, sumG = 0, sumB = 0, sumA = 0, sumRA = 0, sumGA = 0, sumBA = 0, cnt = 0; + unsigned char r, g, b, a, r0, g0, b0; + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_U) + { + r = data[FIXTRANS_PIXEL_U * 4 + 0]; + g = data[FIXTRANS_PIXEL_U * 4 + 1]; + b = data[FIXTRANS_PIXEL_U * 4 + 2]; + a = data[FIXTRANS_PIXEL_U * 4 + 3]; + sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt; + } + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_D) + { + r = data[FIXTRANS_PIXEL_D * 4 + 0]; + g = data[FIXTRANS_PIXEL_D * 4 + 1]; + b = data[FIXTRANS_PIXEL_D * 4 + 2]; + a = data[FIXTRANS_PIXEL_D * 4 + 3]; + sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt; + } + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_L) + { + r = data[FIXTRANS_PIXEL_L * 4 + 0]; + g = data[FIXTRANS_PIXEL_L * 4 + 1]; + b = data[FIXTRANS_PIXEL_L * 4 + 2]; + a = data[FIXTRANS_PIXEL_L * 4 + 3]; + sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt; + } + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_HAS_R) + { + r = data[FIXTRANS_PIXEL_R * 4 + 0]; + g = data[FIXTRANS_PIXEL_R * 4 + 1]; + b = data[FIXTRANS_PIXEL_R * 4 + 2]; + a = data[FIXTRANS_PIXEL_R * 4 + 3]; + sumR += r; sumG += g; sumB += b; sumA += a; sumRA += r*a; sumGA += g*a; sumBA += b*a; ++cnt; + } + if(!cnt) + continue; + r0 = data[FIXTRANS_PIXEL * 4 + 0]; + g0 = data[FIXTRANS_PIXEL * 4 + 1]; + b0 = data[FIXTRANS_PIXEL * 4 + 2]; + if(sumA) + { + // there is a surrounding non-alpha pixel + r = (sumRA + sumA / 2) / sumA; + g = (sumGA + sumA / 2) / sumA; + b = (sumBA + sumA / 2) / sumA; + } + else + { + // need to use a "regular" average + r = (sumR + cnt / 2) / cnt; + g = (sumG + cnt / 2) / cnt; + b = (sumB + cnt / 2) / cnt; + } + if(r != r0 || g != g0 || b != b0) + ++changedPixels; + data[FIXTRANS_PIXEL * 4 + 0] = r; + data[FIXTRANS_PIXEL * 4 + 1] = g; + data[FIXTRANS_PIXEL * 4 + 2] = b; + fixMask[FIXTRANS_PIXEL] |= FIXTRANS_FIXED; + } + for(y = 0; y < h; ++y) + for(x = 0; x < w; ++x) + if(fixMask[FIXTRANS_PIXEL] & FIXTRANS_FIXED) + { + fixMask[FIXTRANS_PIXEL] &= ~(FIXTRANS_NEEDED | FIXTRANS_FIXED); + fixMask[FIXTRANS_PIXEL_D] |= FIXTRANS_HAS_U; + fixMask[FIXTRANS_PIXEL_U] |= FIXTRANS_HAS_D; + fixMask[FIXTRANS_PIXEL_R] |= FIXTRANS_HAS_L; + fixMask[FIXTRANS_PIXEL_L] |= FIXTRANS_HAS_R; + --fixPixels; + } + } + Con_Printf(" %d pixels actually changed.\n", changedPixels); +} + +void Image_FixTransparentPixels_f(void) +{ + const char *filename; + char outfilename[MAX_QPATH], buf[MAX_QPATH]; + unsigned char *data; + if(Cmd_Argc() != 2) + { + Con_Printf("Usage: %s imagefile\n", Cmd_Argv(0)); + return; + } + filename = Cmd_Argv(1); + Image_StripImageExtension(filename, buf, sizeof(buf)); + dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf); + if(!(data = loadimagepixels(filename, true, 0, 0))) + return; + fixtransparentpixels(data, image_width, image_height); + Image_WriteTGARGBA(outfilename, image_width, image_height, data); + Mem_Free(data); + Con_Printf("%s written.\n", outfilename); +} + qboolean Image_WriteTGARGB_preflipped (const char *filename, int width, int height, const unsigned char *data, unsigned char *buffer) { qboolean ret; diff --git a/image.h b/image.h index 17b6149f..3a0052e8 100644 --- a/image.h +++ b/image.h @@ -45,5 +45,8 @@ unsigned char *LoadLMP (const unsigned char *f, int filesize, int matchwidth, in void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale); +// console command to fix the colors of transparent pixels (to prevent weird borders) +void Image_FixTransparentPixels_f(void); + #endif -- 2.39.2