]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - image.c
added r_glsl_restart command, and modified shaderstring loading back to the old way...
[xonotic/darkplaces.git] / image.c
diff --git a/image.c b/image.c
index 623ed5891d5837676a446c74f95714a21b3bb32a..21e809ed8360ddd11a0c24f05261e578ef09c106 100644 (file)
--- a/image.c
+++ b/image.c
@@ -2,6 +2,7 @@
 #include "quakedef.h"
 #include "image.h"
 #include "jpeg.h"
+#include "image_png.h"
 #include "r_shadow.h"
 
 int            image_width;
@@ -180,14 +181,14 @@ typedef struct pcx_s
 LoadPCX
 ============
 */
-unsigned char* LoadPCX (const unsigned char *f, int matchwidth, int matchheight)
+unsigned char* LoadPCX (const unsigned char *f, int filesize, int matchwidth, int matchheight)
 {
        pcx_t pcx;
        unsigned char *a, *b, *image_rgba, *pbuf;
        const unsigned char *palette, *fin, *enddata;
        int x, y, x2, dataByte;
 
-       if (fs_filesize < (int)sizeof(pcx) + 768)
+       if (filesize < (int)sizeof(pcx) + 768)
        {
                Con_Print("Bad pcx file\n");
                return NULL;
@@ -218,7 +219,7 @@ unsigned char* LoadPCX (const unsigned char *f, int matchwidth, int matchheight)
        if ((matchwidth && image_width != matchwidth) || (matchheight && image_height != matchheight))
                return NULL;
 
-       palette = f + fs_filesize - 768;
+       palette = f + filesize - 768;
 
        image_rgba = (unsigned char *)Mem_Alloc(tempmempool, image_width*image_height*4);
        if (!image_rgba)
@@ -297,7 +298,7 @@ void PrintTargaHeader(TargaHeader *t)
 LoadTGA
 =============
 */
-unsigned char *LoadTGA (const unsigned char *f, int matchwidth, int matchheight)
+unsigned char *LoadTGA (const unsigned char *f, int filesize, int matchwidth, int matchheight)
 {
        int x, y, row_inc, compressed, readpixelcount, red, green, blue, alpha, runlen, pindex, alphabits;
        unsigned char *pixbuf, *image_rgba;
@@ -306,10 +307,10 @@ unsigned char *LoadTGA (const unsigned char *f, int matchwidth, int matchheight)
        TargaHeader targa_header;
        unsigned char palette[256*4];
 
-       if (fs_filesize < 19)
+       if (filesize < 19)
                return NULL;
 
-       enddata = f + fs_filesize;
+       enddata = f + filesize;
 
        targa_header.id_length = f[0];
        targa_header.colormap_type = f[1];
@@ -536,11 +537,11 @@ unsigned char *LoadTGA (const unsigned char *f, int matchwidth, int matchheight)
 LoadLMP
 ============
 */
-unsigned char *LoadLMP (const unsigned char *f, int matchwidth, int matchheight, qboolean loadAs8Bit)
+unsigned char *LoadLMP (const unsigned char *f, int filesize, int matchwidth, int matchheight, qboolean loadAs8Bit)
 {
        unsigned char *image_buffer;
 
-       if (fs_filesize < 9)
+       if (filesize < 9)
        {
                Con_Print("LoadLMP: invalid LMP file\n");
                return NULL;
@@ -557,7 +558,7 @@ unsigned char *LoadLMP (const unsigned char *f, int matchwidth, int matchheight,
        if ((matchwidth && image_width != matchwidth) || (matchheight && image_height != matchheight))
                return NULL;
 
-       if (fs_filesize < (fs_offset_t)(8 + image_width * image_height))
+       if (filesize < (8 + image_width * image_height))
        {
                Con_Print("LoadLMP: invalid LMP file\n");
                return NULL;
@@ -571,14 +572,14 @@ unsigned char *LoadLMP (const unsigned char *f, int matchwidth, int matchheight,
        else
        {
                image_buffer = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
-               Image_Copy8bitRGBA(f + 8, image_buffer, image_width * image_height, palette_complete);
+               Image_Copy8bitRGBA(f + 8, image_buffer, image_width * image_height, palette_transparent);
        }
        return image_buffer;
 }
 
-static unsigned char *LoadLMPRGBA (const unsigned char *f, int matchwidth, int matchheight)
+static unsigned char *LoadLMPRGBA (const unsigned char *f, int filesize, int matchwidth, int matchheight)
 {
-       return LoadLMP(f, matchwidth, matchheight, false);
+       return LoadLMP(f, filesize, matchwidth, matchheight, false);
 }
 
 
@@ -593,12 +594,12 @@ typedef struct q2wal_s
        int                     value;
 } q2wal_t;
 
-unsigned char *LoadWAL (const unsigned char *f, int matchwidth, int matchheight)
+unsigned char *LoadWAL (const unsigned char *f, int filesize, int matchwidth, int matchheight)
 {
        unsigned char *image_rgba;
        const q2wal_t *inwal = (const q2wal_t *)f;
 
-       if (fs_filesize < (int) sizeof(q2wal_t))
+       if (filesize < (int) sizeof(q2wal_t))
        {
                Con_Print("LoadWAL: invalid WAL file\n");
                return NULL;
@@ -614,7 +615,7 @@ unsigned char *LoadWAL (const unsigned char *f, int matchwidth, int matchheight)
        if ((matchwidth && image_width != matchwidth) || (matchheight && image_height != matchheight))
                return NULL;
 
-       if ((int) fs_filesize < (int) sizeof(q2wal_t) + (int) LittleLong(inwal->offsets[0]) + image_width * image_height)
+       if (filesize < (int) sizeof(q2wal_t) + (int) LittleLong(inwal->offsets[0]) + image_width * image_height)
        {
                Con_Print("LoadWAL: invalid WAL file\n");
                return NULL;
@@ -652,29 +653,66 @@ void Image_StripImageExtension (const char *in, char *out)
                strcpy(out, in);
 }
 
-struct imageformat_s
+typedef struct imageformat_s
 {
        const char *formatstring;
-       unsigned char *(*loadfunc)(const unsigned char *f, int matchwidth, int matchheight);
+       unsigned char *(*loadfunc)(const unsigned char *f, int filesize, int matchwidth, int matchheight);
 }
-imageformats[] =
+imageformat_t;
+
+// GAME_TENEBRAE only
+imageformat_t imageformats_tenebrae[] =
 {
        {"override/%s.tga", LoadTGA},
+       {"override/%s.png", PNG_LoadImage},
        {"override/%s.jpg", JPEG_LoadImage},
+       {NULL, NULL}
+};
+
+imageformat_t imageformats_nopath[] =
+{
        {"textures/%s.tga", LoadTGA},
+       {"textures/%s.png", PNG_LoadImage},
        {"textures/%s.jpg", JPEG_LoadImage},
-       {"textures/%s.pcx", LoadPCX},
-       {"textures/%s.wal", LoadWAL},
        {"%s.tga", LoadTGA},
+       {"%s.png", PNG_LoadImage},
+       {"%s.jpg", JPEG_LoadImage},
+       {NULL, NULL}
+};
+
+imageformat_t imageformats_textures[] =
+{
+       {"%s.tga", LoadTGA},
+       {"%s.png", PNG_LoadImage},
+       {"%s.jpg", JPEG_LoadImage},
+       {"%s.pcx", LoadPCX},
+       {"%s.wal", LoadWAL},
+       {NULL, NULL}
+};
+
+imageformat_t imageformats_gfx[] =
+{
+       {"%s.tga", LoadTGA},
+       {"%s.png", PNG_LoadImage},
        {"%s.jpg", JPEG_LoadImage},
        {"%s.pcx", LoadPCX},
        {"%s.lmp", LoadLMPRGBA},
        {NULL, NULL}
 };
 
+imageformat_t imageformats_other[] =
+{
+       {"%s.tga", LoadTGA},
+       {"%s.png", PNG_LoadImage},
+       {"%s.jpg", JPEG_LoadImage},
+       {"%s.pcx", LoadPCX},
+       {NULL, NULL}
+};
+
 unsigned char *loadimagepixels (const char *filename, qboolean complain, int matchwidth, int matchheight)
 {
-       int i;
+       fs_offset_t filesize;
+       imageformat_t *firstformat, *format;
        unsigned char *f, *data = NULL;
        char basename[MAX_QPATH], name[MAX_QPATH], *c;
        if (developer_memorydebug.integer)
@@ -687,13 +725,32 @@ unsigned char *loadimagepixels (const char *filename, qboolean complain, int mat
        for (c = basename;*c;c++)
                if (*c == '*')
                        *c = '#';
-       for (i = 0;imageformats[i].formatstring;i++)
+       name[0] = 0;
+       if (strchr(basename, '/'))
+       {
+               int i;
+               for (i = 0;i < (int)sizeof(name)-1 && basename[i] != '/';i++)
+                       name[i] = basename[i];
+               name[i] = 0;
+       }
+       if (gamemode == GAME_TENEBRAE)
+               firstformat = imageformats_tenebrae;
+       else if (!strcasecmp(name, "textures"))
+               firstformat = imageformats_textures;
+       else if (!strcasecmp(name, "gfx"))
+               firstformat = imageformats_gfx;
+       else if (!strchr(name, '/'))
+               firstformat = imageformats_nopath;
+       else
+               firstformat = imageformats_other;
+       // now try all the formats in the selected list
+       for (format = firstformat;format->formatstring;format++)
        {
-               sprintf (name, imageformats[i].formatstring, basename);
-               f = FS_LoadFile(name, tempmempool, true);
+               sprintf (name, format->formatstring, basename);
+               f = FS_LoadFile(name, tempmempool, true, &filesize);
                if (f)
                {
-                       data = imageformats[i].loadfunc(f, matchwidth, matchheight);
+                       data = format->loadfunc(f, filesize, matchwidth, matchheight);
                        Mem_Free(f);
                        if (data)
                        {
@@ -707,10 +764,10 @@ unsigned char *loadimagepixels (const char *filename, qboolean complain, int mat
        if (complain)
        {
                Con_Printf("Couldn't load %s using ", filename);
-               for (i = 0;imageformats[i].formatstring;i++)
+               for (format = firstformat;format->formatstring;format++)
                {
-                       sprintf (name, imageformats[i].formatstring, basename);
-                       Con_Printf(i == 0 ? "\"%s\"" : (imageformats[i+1].formatstring ? ", \"%s\"" : " or \"%s\".\n"), imageformats[i].formatstring);
+                       sprintf (name, format->formatstring, basename);
+                       Con_Printf(format == firstformat ? "\"%s\"" : (format[1].formatstring ? ", \"%s\"" : " or \"%s\".\n"), format->formatstring);
                }
        }
        if (developer_memorydebug.integer)
@@ -718,37 +775,6 @@ unsigned char *loadimagepixels (const char *filename, qboolean complain, int mat
        return NULL;
 }
 
-int image_makemask (const unsigned char *in, unsigned char *out, int size)
-{
-       int i, count;
-       count = 0;
-       for (i = 0;i < size;i++)
-       {
-               out[0] = out[1] = out[2] = 255;
-               out[3] = in[3];
-               if (in[3] != 255)
-                       count++;
-               in += 4;
-               out += 4;
-       }
-       return count;
-}
-
-unsigned char* loadimagepixelsmask (const char *filename, qboolean complain, int matchwidth, int matchheight)
-{
-       unsigned char *in, *data;
-       in = data = loadimagepixels(filename, complain, matchwidth, matchheight);
-       if (!data)
-               return NULL;
-       if (image_makemask(data, data, image_width * image_height))
-               return data; // some transparency
-       else
-       {
-               Mem_Free(data);
-               return NULL; // all opaque
-       }
-}
-
 rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
 {
        unsigned char *data;
@@ -760,78 +786,6 @@ rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, int ma
        return rt;
 }
 
-rtexture_t *loadtextureimagemask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
-{
-       unsigned char *data;
-       rtexture_t *rt;
-       if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight)))
-               return 0;
-       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
-       Mem_Free(data);
-       return rt;
-}
-
-rtexture_t *image_masktex;
-rtexture_t *image_nmaptex;
-rtexture_t *loadtextureimagewithmask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
-{
-       unsigned char *data;
-       rtexture_t *rt;
-       image_masktex = NULL;
-       image_nmaptex = NULL;
-       if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
-               return 0;
-
-       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
-
-       if (flags & TEXF_ALPHA && image_makemask(data, data, image_width * image_height))
-               image_masktex = R_LoadTexture2D(pool, va("%s_mask", filename), image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
-
-       Mem_Free(data);
-       return rt;
-}
-
-rtexture_t *loadtextureimagewithmaskandnmap (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags, float bumpscale)
-{
-       unsigned char *data, *data2;
-       rtexture_t *rt;
-       image_masktex = NULL;
-       image_nmaptex = NULL;
-       if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
-               return 0;
-
-       data2 = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
-
-       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
-
-       Image_HeightmapToNormalmap(data, data2, image_width, image_height, (flags & TEXF_CLAMP) != 0, bumpscale);
-       image_nmaptex = R_LoadTexture2D(pool, va("%s_nmap", filename), image_width, image_height, data2, TEXTYPE_RGBA, flags, NULL);
-
-       if (flags & TEXF_ALPHA && image_makemask(data, data2, image_width * image_height))
-               image_masktex = R_LoadTexture2D(pool, va("%s_mask", filename), image_width, image_height, data2, TEXTYPE_RGBA, flags, NULL);
-
-       Mem_Free(data2);
-
-       Mem_Free(data);
-       return rt;
-}
-
-rtexture_t *loadtextureimagebumpasnmap (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags, float bumpscale)
-{
-       unsigned char *data, *data2;
-       rtexture_t *rt;
-       if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
-               return 0;
-       data2 = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
-
-       Image_HeightmapToNormalmap(data, data2, image_width, image_height, (flags & TEXF_CLAMP) != 0, bumpscale);
-       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data2, TEXTYPE_RGBA, flags, NULL);
-
-       Mem_Free(data2);
-       Mem_Free(data);
-       return rt;
-}
-
 qboolean Image_WriteTGARGB_preflipped (const char *filename, int width, int height, const unsigned char *data, unsigned char *buffer)
 {
        qboolean ret;
@@ -861,40 +815,6 @@ qboolean Image_WriteTGARGB_preflipped (const char *filename, int width, int heig
        return ret;
 }
 
-void Image_WriteTGARGB (const char *filename, int width, int height, const unsigned char *data)
-{
-       int y;
-       unsigned char *buffer, *out;
-       const unsigned char *in, *end;
-
-       buffer = (unsigned char *)Mem_Alloc(tempmempool, width*height*3 + 18);
-
-       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
-
-       // swap rgb to bgr and flip upside down
-       out = buffer + 18;
-       for (y = height - 1;y >= 0;y--)
-       {
-               in = data + y * width * 3;
-               end = in + width * 3;
-               for (;in < end;in += 3)
-               {
-                       *out++ = in[2];
-                       *out++ = in[1];
-                       *out++ = in[0];
-               }
-       }
-       FS_WriteFile (filename, buffer, width*height*3 + 18 );
-
-       Mem_Free(buffer);
-}
-
 void Image_WriteTGARGBA (const char *filename, int width, int height, const unsigned char *data)
 {
        int y;
@@ -910,7 +830,7 @@ void Image_WriteTGARGBA (const char *filename, int width, int height, const unsi
        buffer[14] = (height >> 0) & 0xFF;
        buffer[15] = (height >> 8) & 0xFF;
        buffer[16] = 32;        // pixel size
-       buffer[17] = 8; // transparent flag? (seems to be needed by gimp)
+       buffer[17] = 8; // 8 bits of alpha
 
        // swap rgba to bgra and flip upside down
        out = buffer + 18;
@@ -931,26 +851,6 @@ void Image_WriteTGARGBA (const char *filename, int width, int height, const unsi
        Mem_Free(buffer);
 }
 
-qboolean Image_CheckAlpha(const unsigned char *data, int size, qboolean rgba)
-{
-       const unsigned char *end;
-       if (rgba)
-       {
-               // check alpha bytes
-               for (end = data + size * 4, data += 3;data < end;data += 4)
-                       if (*data < 255)
-                               return 1;
-       }
-       else
-       {
-               // color 255 is transparent
-               for (end = data + size;data < end;data++)
-                       if (*data == 255)
-                               return 1;
-       }
-       return 0;
-}
-
 static void Image_Resample32LerpLine (const unsigned char *in, unsigned char *out, int inwidth, int outwidth)
 {
        int             j, xi, oldx = 0, f, fstep, endx, lerp;
@@ -1511,7 +1411,7 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou
        }
 }
 
-int image_loadskin(imageskin_t *s, char *shadername)
+int image_loadskin(imageskin_t *s, const char *shadername)
 {
        int j;
        unsigned char *bumppixels;
@@ -1527,8 +1427,12 @@ int image_loadskin(imageskin_t *s, char *shadername)
        s->basepixels_height = image_height;
 
        bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0;
-       if (Image_CheckAlpha(s->basepixels, s->basepixels_width * s->basepixels_height, true))
+       for (j = 3;j < s->basepixels_width * s->basepixels_height * 4;j += 4)
+               if (s->basepixels[j] < 255)
+                       break;
+       if (j < s->basepixels_width * s->basepixels_height * 4)
        {
+               // has transparent pixels
                s->maskpixels = (unsigned char *)Mem_Alloc(loadmodel->mempool, s->basepixels_width * s->basepixels_height * 4);
                s->maskpixels_width = s->basepixels_width;
                s->maskpixels_height = s->basepixels_height;