+
+ dpsnprintf(lmppath, sizeof(lmppath), "%s.lmp", filename);
+ data = FS_LoadFile(lmppath, tempmempool, true, &filesize);
+ if (data)
+ {
+ if (filesize > 8)
+ {
+ int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
+ int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
+ if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
+ {
+ *returnwidth = w;
+ *returnheight = h;
+ Mem_Free(data);
+ return true;
+ }
+ }
+ Mem_Free(data);
+ }
+ if (!strncasecmp(filename, "gfx/", 4))
+ {
+ data = W_GetLumpName(filename + 4, &filesize);
+ if (data && filesize > 8)
+ {
+ int w = data[0] + data[1] * 0x100 + data[2] * 0x10000 + data[3] * 0x1000000;
+ int h = data[4] + data[5] * 0x100 + data[6] * 0x10000 + data[7] * 0x1000000;
+ if (w >= 1 && w <= 32768 && h >= 1 && h <= 32768)
+ {
+ *returnwidth = w;
+ *returnheight = h;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+extern cvar_t gl_picmip;
+rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, qbool complain, int flags, qbool allowFixtrans, qbool sRGB)
+{
+ unsigned char *data;
+ rtexture_t *rt;
+ int miplevel = R_PicmipForFlags(flags);
+ if (!(data = loadimagepixelsbgra (filename, complain, allowFixtrans, false, &miplevel)))
+ return 0;
+ rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, flags, miplevel, NULL);
+ Mem_Free(data);
+ return rt;
+}
+
+int 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 = (unsigned char *) 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 0; // sorry, can't do anything about this
+ while(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 + 2];
+ g = data[FIXTRANS_PIXEL_U * 4 + 1];
+ b = data[FIXTRANS_PIXEL_U * 4 + 0];
+ 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 + 2];
+ g = data[FIXTRANS_PIXEL_D * 4 + 1];
+ b = data[FIXTRANS_PIXEL_D * 4 + 0];
+ 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 + 2];
+ g = data[FIXTRANS_PIXEL_L * 4 + 1];
+ b = data[FIXTRANS_PIXEL_L * 4 + 0];
+ 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 + 2];
+ g = data[FIXTRANS_PIXEL_R * 4 + 1];
+ b = data[FIXTRANS_PIXEL_R * 4 + 0];
+ 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 + 2];
+ g0 = data[FIXTRANS_PIXEL * 4 + 1];
+ b0 = data[FIXTRANS_PIXEL * 4 + 0];
+ 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 + 2] = r;
+ data[FIXTRANS_PIXEL * 4 + 1] = g;
+ data[FIXTRANS_PIXEL * 4 + 0] = 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;
+ }
+ }
+ return changedPixels;
+}
+
+void Image_FixTransparentPixels_f(cmd_state_t *cmd)
+{
+ const char *filename, *filename_pattern;
+ fssearch_t *search;
+ int i, n;
+ char outfilename[MAX_QPATH], buf[MAX_QPATH];
+ unsigned char *data;
+ if(Cmd_Argc(cmd) != 2)
+ {
+ Con_Printf("Usage: %s imagefile\n", Cmd_Argv(cmd, 0));
+ return;
+ }
+ filename_pattern = Cmd_Argv(cmd, 1);
+ search = FS_Search(filename_pattern, true, true, NULL);
+ if(!search)
+ return;
+ for(i = 0; i < search->numfilenames; ++i)
+ {
+ filename = search->filenames[i];
+ Con_Printf("Processing %s... ", filename);
+ Image_StripImageExtension(filename, buf, sizeof(buf));
+ dpsnprintf(outfilename, sizeof(outfilename), "fixtrans/%s.tga", buf);
+ if(!(data = loadimagepixelsbgra(filename, true, false, false, NULL)))
+ return;
+ if((n = fixtransparentpixels(data, image_width, image_height)))
+ {
+ Image_WriteTGABGRA(outfilename, image_width, image_height, data);
+ Con_Printf("%s written (%d pixels changed).\n", outfilename, n);
+ }
+ else
+ Con_Printf("unchanged.\n");
+ Mem_Free(data);
+ }
+ FS_FreeSearch(search);
+}
+
+qbool Image_WriteTGABGR_preflipped (const char *filename, int width, int height, const unsigned char *data)
+{
+ qbool ret;
+ unsigned char buffer[18];
+ const void *buffers[2];
+ fs_offset_t sizes[2];
+
+ memset (buffer, 0, 18);
+ buffer[2] = 2; // uncompressed type
+ buffer[12] = (width >> 0) & 0xFF;
+ buffer[13] = (width >> 8) & 0xFF;
+ buffer[14] = (height >> 0) & 0xFF;
+ buffer[15] = (height >> 8) & 0xFF;
+ buffer[16] = 24; // pixel size
+
+ buffers[0] = buffer;
+ sizes[0] = 18;
+ buffers[1] = data;
+ sizes[1] = width*height*3;
+ ret = FS_WriteFileInBlocks(filename, buffers, sizes, 2);