home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / qdata / images.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-20  |  14.3 KB  |  742 lines

  1. #include "qdata.h"
  2.  
  3. char        mip_prefix[1024];        // directory to dump the textures in
  4.  
  5. qboolean    colormap_issued;
  6. byte        colormap_palette[768];
  7.  
  8. /*
  9. ==============
  10. RemapZero
  11.  
  12. Replaces all 0 bytes in an image with the closest palette entry.
  13. This is because NT won't let us change index 0, so any palette
  14. animation leaves those pixels untouched.
  15. ==============
  16. */
  17. void RemapZero (byte *pixels, byte *palette, int width, int height)
  18. {
  19.     int        i, c;
  20.     int        alt_zero;
  21.     int        value, best;
  22.  
  23.     alt_zero = 0;
  24.     best = 9999999;
  25.     for (i=1 ; i<255 ; i++)
  26.     {
  27.         value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
  28.         if (value < best)
  29.         {
  30.             best = value;
  31.             alt_zero = i;
  32.         }
  33.     }
  34.  
  35.     c = width*height;
  36.     for (i=0 ; i<c ; i++)
  37.         if (pixels[i] == 0)
  38.             pixels[i] = alt_zero;
  39. }
  40.  
  41. /*
  42. ==============
  43. Cmd_Grab
  44.  
  45. $grab filename x y width height
  46. ==============
  47. */
  48. void Cmd_Grab (void)
  49. {
  50.     int             xl,yl,w,h,y;
  51.     byte            *cropped;
  52.     char            savename[1024];
  53.     char            dest[1024];
  54.  
  55.     GetToken (false);
  56.  
  57.     if (token[0] == '/' || token[0] == '\\')
  58.         sprintf (savename, "%s%s.pcx", gamedir, token+1);
  59.     else
  60.         sprintf (savename, "%spics/%s.pcx", gamedir, token);
  61.  
  62.     if (g_release)
  63.     {
  64.         if (token[0] == '/' || token[0] == '\\')
  65.             sprintf (dest, "%s.pcx", token+1);
  66.         else
  67.             sprintf (dest, "pics/%s.pcx", token);
  68.  
  69.         ReleaseFile (dest);
  70.         return;
  71.     }
  72.  
  73.     GetToken (false);
  74.     xl = atoi (token);
  75.     GetToken (false);
  76.     yl = atoi (token);
  77.     GetToken (false);
  78.     w = atoi (token);
  79.     GetToken (false);
  80.     h = atoi (token);
  81.  
  82.     if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
  83.         Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
  84.  
  85.     // crop it to the proper size
  86.     cropped = malloc (w*h);
  87.     for (y=0 ; y<h ; y++)
  88.     {
  89.         memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
  90.     }
  91.  
  92.     // save off the new image
  93.     printf ("saving %s\n", savename);
  94.     CreatePath (savename);
  95.     WritePCXfile (savename, cropped, w,    h, lbmpalette);
  96.  
  97.     free (cropped);
  98. }
  99.  
  100. /*
  101. ==============
  102. Cmd_Raw
  103.  
  104. $grab filename x y width height
  105. ==============
  106. */
  107. void Cmd_Raw (void)
  108. {
  109.     int             xl,yl,w,h,y;
  110.     byte            *cropped;
  111.     char            savename[1024];
  112.     char            dest[1024];
  113.  
  114.     GetToken (false);
  115.  
  116.     sprintf (savename, "%s%s.lmp", gamedir, token);
  117.  
  118.     if (g_release)
  119.     {
  120.         sprintf (dest, "%s.lmp", token);
  121.         ReleaseFile (dest);
  122.         return;
  123.     }
  124.  
  125.     GetToken (false);
  126.     xl = atoi (token);
  127.     GetToken (false);
  128.     yl = atoi (token);
  129.     GetToken (false);
  130.     w = atoi (token);
  131.     GetToken (false);
  132.     h = atoi (token);
  133.  
  134.     if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
  135.         Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
  136.  
  137.     // crop it to the proper size
  138.     cropped = malloc (w*h);
  139.     for (y=0 ; y<h ; y++)
  140.     {
  141.         memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
  142.     }
  143.  
  144.     // save off the new image
  145.     printf ("saving %s\n", savename);
  146.     CreatePath (savename);
  147.  
  148.     SaveFile (savename, cropped, w*h);
  149.  
  150.     free (cropped);
  151. }
  152.  
  153. /*
  154. =============================================================================
  155.  
  156. COLORMAP GRABBING
  157.  
  158. =============================================================================
  159. */
  160.  
  161. /*
  162. ===============
  163. BestColor
  164. ===============
  165. */
  166. byte BestColor (int r, int g, int b, int start, int stop)
  167. {
  168.     int    i;
  169.     int    dr, dg, db;
  170.     int    bestdistortion, distortion;
  171.     int    bestcolor;
  172.     byte    *pal;
  173.  
  174. //
  175. // let any color go to 0 as a last resort
  176. //
  177.     bestdistortion = 256*256*4;
  178.     bestcolor = 0;
  179.  
  180.     pal = colormap_palette + start*3;
  181.     for (i=start ; i<= stop ; i++)
  182.     {
  183.         dr = r - (int)pal[0];
  184.         dg = g - (int)pal[1];
  185.         db = b - (int)pal[2];
  186.         pal += 3;
  187.         distortion = dr*dr + dg*dg + db*db;
  188.         if (distortion < bestdistortion)
  189.         {
  190.             if (!distortion)
  191.                 return i;        // perfect match
  192.  
  193.             bestdistortion = distortion;
  194.             bestcolor = i;
  195.         }
  196.     }
  197.  
  198.     return bestcolor;
  199. }
  200.  
  201.  
  202. /*
  203. ==============
  204. Cmd_Colormap
  205.  
  206. $colormap filename
  207.  
  208.   the brightes colormap is first in the table (FIXME: reverse this now?)
  209.  
  210.   64 rows of 256 : lightmaps
  211.   256 rows of 256 : translucency table
  212. ==============
  213. */
  214. void Cmd_Colormap (void)
  215. {
  216.     int        levels, brights;
  217.     int        l, c;
  218.     float    frac, red, green, blue;
  219.     float    range;
  220.     byte    *cropped, *lump_p;
  221.     char    savename[1024];
  222.     char    dest[1024];
  223.  
  224.     colormap_issued = true;
  225.     if (!g_release)
  226.         memcpy (colormap_palette, lbmpalette, 768);
  227.  
  228.     if (!TokenAvailable ())
  229.     {    // just setting colormap_issued
  230.         return;
  231.     }
  232.  
  233.     GetToken (false);
  234.     sprintf (savename, "%spics/%s.pcx", gamedir, token);
  235.  
  236.     if (g_release)
  237.     {
  238.         sprintf (dest, "pics/%s.pcx", token);
  239.         ReleaseFile (dest);
  240.         return;
  241.     }
  242.  
  243.     range = 2;
  244.     levels = 64;
  245.     brights = 1;    // ignore 255 (transparent)
  246.  
  247.     cropped = malloc((levels+256)*256);
  248.     lump_p = cropped;
  249.  
  250. // shaded levels
  251.     for (l=0;l<levels;l++)
  252.     {
  253.         frac = range - range*(float)l/(levels-1);
  254.         for (c=0 ; c<256-brights ; c++)
  255.         {
  256.             red = lbmpalette[c*3];
  257.             green = lbmpalette[c*3+1];
  258.             blue = lbmpalette[c*3+2];
  259.  
  260.             red = (int)(red*frac+0.5);
  261.             green = (int)(green*frac+0.5);
  262.             blue = (int)(blue*frac+0.5);
  263.             
  264. //
  265. // note: 254 instead of 255 because 255 is the transparent color, and we
  266. // don't want anything remapping to that
  267. // don't use color 0, because NT can't remap that (or 255)
  268. //
  269.             *lump_p++ = BestColor(red,green,blue, 1, 254);
  270.         }
  271.  
  272.         // fullbrights allways stay the same
  273.         for ( ; c<256 ; c++)
  274.             *lump_p++ = c;
  275.     }
  276.     
  277. // 66% transparancy table
  278.     for (l=0;l<255;l++)
  279.     {
  280.         for (c=0 ; c<255 ; c++)
  281.         {
  282.             red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
  283.             green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
  284.             blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
  285.  
  286.             *lump_p++ = BestColor(red,green,blue, 1, 254);
  287.         }
  288.         *lump_p++ = 255;
  289.     }
  290.     for (c=0 ; c<256 ; c++)
  291.         *lump_p++ = 255;
  292.     
  293.     // save off the new image
  294.     printf ("saving %s\n", savename);
  295.     CreatePath (savename);
  296.     WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
  297.  
  298.     free (cropped);
  299. }
  300.  
  301. /*
  302. =============================================================================
  303.  
  304. MIPTEX GRABBING
  305.  
  306. =============================================================================
  307. */
  308.  
  309. byte    pixdata[256];
  310.  
  311. int        d_red, d_green, d_blue;
  312.  
  313. byte    palmap[32][32][32];
  314. qboolean    palmap_built;
  315.  
  316. /*
  317. =============
  318. FindColor
  319. =============
  320. */
  321. int FindColor (int r, int g, int b)
  322. {
  323.     int        bestcolor;
  324.  
  325.     if (r > 255)
  326.         r = 255;
  327.     if (r < 0)
  328.         r = 0;
  329.     if (g > 255)
  330.         g = 255;
  331.     if (g < 0)
  332.         g = 0;
  333.     if (b > 255)
  334.         b = 255;
  335.     if (b < 0)
  336.         b = 0;
  337. #ifndef TABLECOLORS
  338.     bestcolor = BestColor (r, g, b, 0, 254);
  339. #else
  340.     bestcolor = palmap[r>>3][g>>3][b>>3];
  341. #endif
  342.  
  343.     return bestcolor;
  344. }
  345.  
  346.  
  347. void BuildPalmap (void)
  348. {
  349. #ifdef TABLECOLORS
  350.     int        r, g, b;
  351.     int        bestcolor;
  352.  
  353.     if (palmap_built)
  354.         return;
  355.     palmap_built = true;
  356.  
  357.     for (r=4 ; r<256 ; r+=8)
  358.     {
  359.         for (g=4 ; g<256 ; g+=8)
  360.         {
  361.             for (b=4 ; b<256 ; b+=8)
  362.             {
  363.                 bestcolor = BestColor (r, g, b, 1, 254);
  364.                 palmap[r>>3][g>>3][b>>3] = bestcolor;
  365.             }
  366.         }
  367.     }
  368. #endif
  369.  
  370.     if (!colormap_issued)
  371.         Error ("You must issue a $colormap command first");
  372.  
  373. }
  374.  
  375. /*
  376. =============
  377. AveragePixels
  378. =============
  379. */
  380. byte AveragePixels (int count)
  381. {
  382.     int        r,g,b;
  383.     int        i;
  384.     int        vis;
  385.     int        pix;
  386.     int        bestcolor;
  387.     byte    *pal;
  388.     int        fullbright;
  389.     
  390.     vis = 0;
  391.     r = g = b = 0;
  392.     fullbright = 0;
  393.     for (i=0 ; i<count ; i++)
  394.     {
  395.         pix = pixdata[i];
  396.         
  397.         r += lbmpalette[pix*3];
  398.         g += lbmpalette[pix*3+1];
  399.         b += lbmpalette[pix*3+2];
  400.         vis++;
  401.     }
  402.         
  403.     r /= vis;
  404.     g /= vis;
  405.     b /= vis;
  406.  
  407.     // error diffusion
  408.     r += d_red;
  409.     g += d_green;
  410.     b += d_blue;
  411.     
  412. //
  413. // find the best color
  414. //
  415.     bestcolor = FindColor (r, g, b);
  416.  
  417.     // error diffusion
  418.     pal = colormap_palette + bestcolor*3;
  419.     d_red = r - (int)pal[0];
  420.     d_green = g - (int)pal[1];
  421.     d_blue = b - (int)pal[2];
  422.  
  423.     return bestcolor;
  424. }
  425.  
  426.  
  427. typedef enum
  428. {
  429.     pt_contents,
  430.     pt_flags,
  431.     pt_animvalue,
  432.     pt_flagvalue
  433. } parmtype_t;
  434.  
  435. typedef struct
  436. {
  437.     char    *name;
  438.     int        flags;
  439.     parmtype_t    type;
  440. } mipparm_t;
  441.  
  442. mipparm_t    mipparms[] =
  443. {
  444.     // utility content attributes
  445.     {"water",    CONTENTS_WATER, pt_contents},
  446.     {"slime",    CONTENTS_SLIME, pt_contents},        // mildly damaging
  447.     {"lava",    CONTENTS_LAVA, pt_contents},        // very damaging
  448.     {"window",    CONTENTS_WINDOW, pt_contents},    // solid, but doesn't eat internal textures
  449.     {"mist",    CONTENTS_MIST, pt_contents},    // non-solid window
  450.     {"origin",    CONTENTS_ORIGIN, pt_contents},    // center of rotating brushes
  451.     {"playerclip",    CONTENTS_PLAYERCLIP, pt_contents},
  452.     {"monsterclip",    CONTENTS_MONSTERCLIP, pt_contents},
  453.  
  454.     // utility surface attributes
  455.     {"hint",    SURF_HINT, pt_flags},
  456.     {"skip",    SURF_SKIP, pt_flags},
  457.     {"light",    SURF_LIGHT, pt_flagvalue},        // value is the light quantity
  458.  
  459.     // texture chaining
  460.     {"anim",    0,            pt_animvalue},        // value is the next animation
  461.  
  462.     // server attributes
  463.     {"slick",    SURF_SLICK, pt_flags},
  464.  
  465.     // drawing attributes
  466.     {"sky",        SURF_SKY, pt_flags},
  467.     {"warping",    SURF_WARP, pt_flags},        // only valid with 64x64 textures
  468.     {"trans33",    SURF_TRANS33, pt_flags},    // translucent should allso set fullbright
  469.     {"trans66",    SURF_TRANS66, pt_flags},
  470.     {"flowing",    SURF_FLOWING, pt_flags},    // flow direction towards angle 0
  471.     {"nodraw",    SURF_NODRAW, pt_flags},    // for clip textures and trigger textures
  472.  
  473.     {NULL, 0, pt_contents}
  474. };
  475.  
  476.  
  477.  
  478. /*
  479. ==============
  480. Cmd_Mip
  481.  
  482. $mip filename x y width height <OPTIONS>
  483. must be multiples of sixteen
  484. SURF_WINDOW
  485. ==============
  486. */
  487. void Cmd_Mip (void)
  488. {
  489.     int             x,y,xl,yl,xh,yh,w,h;
  490.     byte            *screen_p, *source;
  491.     int             linedelta;
  492.     miptex_t        *qtex;
  493.     int                miplevel, mipstep;
  494.     int                xx, yy, pix;
  495.     int                count;
  496.     int                flags, value, contents;
  497.     mipparm_t        *mp;
  498.     char            lumpname[64];
  499.     byte            *lump_p;
  500.     char            filename[1024];
  501.     char            animname[64];
  502.  
  503.     GetToken (false);
  504.     strcpy (lumpname, token);
  505.     
  506.     GetToken (false);
  507.     xl = atoi (token);
  508.     GetToken (false);
  509.     yl = atoi (token);
  510.     GetToken (false);
  511.     w = atoi (token);
  512.     GetToken (false);
  513.     h = atoi (token);
  514.  
  515.     if ( (w & 15) || (h & 15) )
  516.         Error ("line %i: miptex sizes must be multiples of 16", scriptline);
  517.  
  518.     flags = 0;
  519.     contents = 0;
  520.     value = 0;
  521.  
  522.     animname[0] = 0;
  523.  
  524.     // get optional flags and values
  525.     while (TokenAvailable ())
  526.     {
  527.         GetToken (false);
  528.     
  529.         for (mp=mipparms ; mp->name ; mp++)
  530.         {
  531.             if (!strcmp(mp->name, token))
  532.             {
  533.                 switch (mp->type)
  534.                 {
  535.                 case pt_animvalue:
  536.                     GetToken (false);    // specify the next animation frame
  537.                     strcpy (animname, token);
  538.                     break;
  539.                 case pt_flags:
  540.                     flags |= mp->flags;
  541.                     break;
  542.                 case pt_contents:
  543.                     contents |= mp->flags;
  544.                     break;
  545.                 case pt_flagvalue:
  546.                     flags |= mp->flags;
  547.                     GetToken (false);    // specify the light value
  548.                     value = atoi(token);
  549.                     break;
  550.                 }
  551.                 break;
  552.             }
  553.         }
  554.         if (!mp->name)
  555.             Error ("line %i: unknown parm %s", scriptline, token);
  556.     }
  557.  
  558.     sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
  559.     if (g_release)
  560.         return;    // textures are only released by $maps
  561.  
  562.     xh = xl+w;
  563.     yh = yl+h;
  564.  
  565.     qtex = malloc (sizeof(miptex_t) + w*h*2);
  566.     memset (qtex, 0, sizeof(miptex_t));
  567.  
  568.     qtex->width = LittleLong(w);
  569.     qtex->height = LittleLong(h);
  570.     qtex->flags = LittleLong(flags);
  571.     qtex->contents = LittleLong(contents);
  572.     qtex->value = LittleLong(value);
  573.     sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
  574.     if (animname[0])
  575.         sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
  576.     
  577.     lump_p = (byte *)(&qtex->value+1);
  578.     
  579.     screen_p = byteimage + yl*byteimagewidth + xl;
  580.     linedelta = byteimagewidth - w;
  581.  
  582.     source = lump_p;
  583.     qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
  584.  
  585.     for (y=yl ; y<yh ; y++)
  586.     {
  587.         for (x=xl ; x<xh ; x++)
  588.         {
  589.             pix = *screen_p++;
  590.             if (pix == 255)
  591.                 pix = 1;        // should never happen
  592.             *lump_p++ = pix;
  593.         }
  594.         screen_p += linedelta;
  595.     }
  596.     
  597. //
  598. // subsample for greater mip levels
  599. //
  600.     d_red = d_green = d_blue = 0;    // no distortion yet
  601.  
  602.     for (miplevel = 1 ; miplevel<4 ; miplevel++)
  603.     {
  604.         qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
  605.         
  606.         mipstep = 1<<miplevel;
  607.         for (y=0 ; y<h ; y+=mipstep)
  608.         {
  609.  
  610.             for (x = 0 ; x<w ; x+= mipstep)
  611.             {
  612.                 count = 0;
  613.                 for (yy=0 ; yy<mipstep ; yy++)
  614.                     for (xx=0 ; xx<mipstep ; xx++)
  615.                     {
  616.                         pixdata[count] = source[ (y+yy)*w + x + xx ];
  617.                         count++;
  618.                     }
  619.                 *lump_p++ = AveragePixels (count);
  620.             }    
  621.         }
  622.     }
  623.  
  624. //
  625. // dword align the size
  626. //
  627.     while ((int)lump_p&3)
  628.         *lump_p++ = 0;
  629.  
  630. //
  631. // write it out
  632. //
  633.     printf ("writing %s\n", filename);
  634.     SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
  635.  
  636.     free (qtex);
  637. }
  638.  
  639. /*
  640. ===============
  641. Cmd_Mippal
  642. ===============
  643. */
  644. void Cmd_Mippal (void)
  645. {
  646.     colormap_issued = true;
  647.     if (g_release)
  648.         return;
  649.  
  650.     memcpy (colormap_palette, lbmpalette, 768);
  651.  
  652.     BuildPalmap();
  653. }
  654.  
  655.  
  656. /*
  657. ===============
  658. Cmd_Mipdir
  659. ===============
  660. */
  661. void Cmd_Mipdir (void)
  662. {
  663.     char    filename[1024];
  664.  
  665.     GetToken (false);
  666.     strcpy (mip_prefix, token);
  667.     // create the directory if needed
  668.     sprintf (filename, "%stextures", gamedir, mip_prefix);
  669.     Q_mkdir (filename); 
  670.     sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
  671.     Q_mkdir (filename); 
  672. }
  673.  
  674.  
  675. /*
  676. =============================================================================
  677.  
  678. ENVIRONMENT MAP GRABBING
  679.  
  680. Creates six pcx files from tga files without any palette edge seams
  681. also copies the tga files for GL rendering.
  682. =============================================================================
  683. */
  684.  
  685. // 3dstudio environment map suffixes
  686. char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
  687.  
  688. /*
  689. =================
  690. Cmd_Environment
  691. =================
  692. */
  693. void Cmd_Environment (void)
  694. {
  695.     char    name[1024];
  696.     int        i, x, y;
  697.     byte    image[256*256];
  698.     byte    *tga;
  699.  
  700.     GetToken (false);
  701.  
  702.     if (g_release)
  703.     {
  704.         for (i=0 ; i<6 ; i++)
  705.         {
  706.             sprintf (name, "env/%s%s.pcx", token, suf[i]);
  707.             ReleaseFile (name);
  708.             sprintf (name, "env/%s%s.tga", token, suf[i]);
  709.             ReleaseFile (name);
  710.         }
  711.         return;
  712.     }
  713.     // get the palette
  714.     BuildPalmap ();
  715.  
  716.     sprintf (name, "%senv/", gamedir);
  717.     CreatePath (name);
  718.  
  719.     // convert the images
  720.     for (i=0 ; i<6 ; i++)
  721.     {
  722.         sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
  723.         printf ("loading %s...\n", name);
  724.         LoadTGA (name, &tga, NULL, NULL);
  725.  
  726.         for (y=0 ; y<256 ; y++)
  727.         {
  728.             for (x=0 ; x<256 ; x++)
  729.             {
  730.                 image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
  731.             }
  732.         }
  733.         free (tga);
  734.         sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
  735.         if (FileTime (name) != -1)
  736.             printf ("%s already exists, not overwriting.\n", name);
  737.         else
  738.             WritePCXfile (name, image, 256, 256, colormap_palette);
  739.     }
  740. }
  741.  
  742.