XCF support now works with 16bit+32bit linear float source files, and 16bit int files too.
Added a couple extra pixel formats to the dds loader. Format conversions are handled via a table. Additional conversions added. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5565 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
1d56c1443e
commit
9984042186
3 changed files with 1347 additions and 400 deletions
File diff suppressed because it is too large
Load diff
|
@ -476,6 +476,7 @@ const char *Image_FormatName(uploadfmt_t encoding);
|
|||
qboolean Image_FormatHasAlpha(uploadfmt_t encoding);
|
||||
image_t *Image_LoadTexture (const char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags);
|
||||
struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char *iname, const char *fname, qbyte *filedata, int filesize);
|
||||
void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt, const char *imagename);
|
||||
|
||||
#ifdef D3D8QUAKE
|
||||
void D3D8_Set2D (void);
|
||||
|
|
367
imgtool.c
367
imgtool.c
|
@ -215,6 +215,18 @@ static int QDECL ImgFile_WriteBytes(struct vfsfile_s *file, const void *buffer,
|
|||
struct imgfile_s *f = (struct imgfile_s*)file;
|
||||
return fwrite(buffer, 1, bytestowrite, f->f);
|
||||
}
|
||||
static qboolean QDECL ImgFile_Seek(struct vfsfile_s *file, qofs_t newofs)
|
||||
{
|
||||
struct imgfile_s *f = (struct imgfile_s*)file;
|
||||
if (fseek(f->f, newofs, SEEK_SET)==0)
|
||||
return true; //success
|
||||
return false;
|
||||
}
|
||||
static qofs_t QDECL ImgFile_Tell(struct vfsfile_s *file)
|
||||
{
|
||||
struct imgfile_s *f = (struct imgfile_s*)file;
|
||||
return ftell(f->f);
|
||||
}
|
||||
vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto)
|
||||
{
|
||||
if (!strcmp(mode, "wb"))
|
||||
|
@ -224,6 +236,8 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
|
|||
r->pub.seekstyle = SS_UNSEEKABLE;
|
||||
r->pub.Close = ImgFile_Close;
|
||||
r->pub.WriteBytes = ImgFile_WriteBytes;
|
||||
r->pub.Seek = ImgFile_Seek;
|
||||
r->pub.Tell = ImgFile_Tell;
|
||||
if (r->f)
|
||||
return &r->pub;
|
||||
free(r);
|
||||
|
@ -272,12 +286,59 @@ void VARGS Q_snprintfz (char *dest, size_t size, const char *fmt, ...)
|
|||
va_end (argptr);
|
||||
}
|
||||
|
||||
//palette data is used in lmps, as well as written into pcxes or wads, probably some other things.
|
||||
qbyte *host_basepal;
|
||||
unsigned int d_8to24rgbtable[256];
|
||||
unsigned int d_8to24bgrtable[256];
|
||||
static qbyte default_quakepal[768] =
|
||||
{ //the quake palette was released into the public domain (or at least gpl) to ease development of tools writing quake-format data.
|
||||
0,0,0,15,15,15,31,31,31,47,47,47,63,63,63,75,75,75,91,91,91,107,107,107,123,123,123,139,139,139,155,155,155,171,171,171,187,187,187,203,203,203,219,219,219,235,235,235,15,11,7,23,15,11,31,23,11,39,27,15,47,35,19,55,43,23,63,47,23,75,55,27,83,59,27,91,67,31,99,75,31,107,83,31,115,87,31,123,95,35,131,103,35,143,111,35,11,11,15,19,19,27,27,27,39,39,39,51,47,47,63,55,55,75,63,63,87,71,71,103,79,79,115,91,91,127,99,99,
|
||||
139,107,107,151,115,115,163,123,123,175,131,131,187,139,139,203,0,0,0,7,7,0,11,11,0,19,19,0,27,27,0,35,35,0,43,43,7,47,47,7,55,55,7,63,63,7,71,71,7,75,75,11,83,83,11,91,91,11,99,99,11,107,107,15,7,0,0,15,0,0,23,0,0,31,0,0,39,0,0,47,0,0,55,0,0,63,0,0,71,0,0,79,0,0,87,0,0,95,0,0,103,0,0,111,0,0,119,0,0,127,0,0,19,19,0,27,27,0,35,35,0,47,43,0,55,47,0,67,
|
||||
55,0,75,59,7,87,67,7,95,71,7,107,75,11,119,83,15,131,87,19,139,91,19,151,95,27,163,99,31,175,103,35,35,19,7,47,23,11,59,31,15,75,35,19,87,43,23,99,47,31,115,55,35,127,59,43,143,67,51,159,79,51,175,99,47,191,119,47,207,143,43,223,171,39,239,203,31,255,243,27,11,7,0,27,19,0,43,35,15,55,43,19,71,51,27,83,55,35,99,63,43,111,71,51,127,83,63,139,95,71,155,107,83,167,123,95,183,135,107,195,147,123,211,163,139,227,179,151,
|
||||
171,139,163,159,127,151,147,115,135,139,103,123,127,91,111,119,83,99,107,75,87,95,63,75,87,55,67,75,47,55,67,39,47,55,31,35,43,23,27,35,19,19,23,11,11,15,7,7,187,115,159,175,107,143,163,95,131,151,87,119,139,79,107,127,75,95,115,67,83,107,59,75,95,51,63,83,43,55,71,35,43,59,31,35,47,23,27,35,19,19,23,11,11,15,7,7,219,195,187,203,179,167,191,163,155,175,151,139,163,135,123,151,123,111,135,111,95,123,99,83,107,87,71,95,75,59,83,63,
|
||||
51,67,51,39,55,43,31,39,31,23,27,19,15,15,11,7,111,131,123,103,123,111,95,115,103,87,107,95,79,99,87,71,91,79,63,83,71,55,75,63,47,67,55,43,59,47,35,51,39,31,43,31,23,35,23,15,27,19,11,19,11,7,11,7,255,243,27,239,223,23,219,203,19,203,183,15,187,167,15,171,151,11,155,131,7,139,115,7,123,99,7,107,83,0,91,71,0,75,55,0,59,43,0,43,31,0,27,15,0,11,7,0,0,0,255,11,11,239,19,19,223,27,27,207,35,35,191,43,
|
||||
43,175,47,47,159,47,47,143,47,47,127,47,47,111,47,47,95,43,43,79,35,35,63,27,27,47,19,19,31,11,11,15,43,0,0,59,0,0,75,7,0,95,7,0,111,15,0,127,23,7,147,31,7,163,39,11,183,51,15,195,75,27,207,99,43,219,127,59,227,151,79,231,171,95,239,191,119,247,211,139,167,123,59,183,155,55,199,195,55,231,227,87,127,191,255,171,231,255,215,255,255,103,0,0,139,0,0,179,0,0,215,0,0,255,0,0,255,243,147,255,247,199,255,255,255,159,91,83
|
||||
};
|
||||
qbyte GetPaletteIndexNoFB(int red, int green, int blue)
|
||||
{
|
||||
return 0;
|
||||
int i;
|
||||
int best=0;
|
||||
int bestdist=INT_MAX;
|
||||
int dist;
|
||||
for (i = 0; i < 256-32; i++)
|
||||
{
|
||||
dist =
|
||||
abs(host_basepal[i*3+0]-red)+
|
||||
abs(host_basepal[i*3+1]-green)+
|
||||
abs(host_basepal[i*3+2]-blue);
|
||||
if (dist < bestdist)
|
||||
{
|
||||
bestdist = dist;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
static void ImgTool_SetupPalette(void)
|
||||
{
|
||||
int i;
|
||||
//we ought to try to read gfx/palette.lmp, but its probably in a pak
|
||||
host_basepal = default_quakepal;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
d_8to24rgbtable[i] = (host_basepal[i*3+0]<<0)|(host_basepal[i*3+1]<<8)|(host_basepal[i*3+2]<<16);
|
||||
d_8to24bgrtable[i] = (host_basepal[i*3+0]<<16)|(host_basepal[i*3+1]<<8)|(host_basepal[i*3+2]<<0);
|
||||
}
|
||||
}
|
||||
static void ImgTool_FreeMips(struct pendingtextureinfo *mips)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < mips->mipcount; i++)
|
||||
if (mips->mip[i].needfree)
|
||||
BZ_Free(mips->mip[i].data);
|
||||
if (mips->extrafree)
|
||||
BZ_Free(mips->extrafree);
|
||||
BZ_Free(mips);
|
||||
}
|
||||
|
||||
sh_config_t sh_config;
|
||||
|
@ -373,7 +434,28 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
|||
else if (targfmt == PTI_BC7_RGBA)
|
||||
Q_snprintfz(command, sizeof(command), "nvcompress -bc7");
|
||||
else
|
||||
{
|
||||
if (mips->encoding != targfmt)
|
||||
{
|
||||
for (m = 0; m < PTI_MAX; m++)
|
||||
sh_config.texfmt[m] = (m == targfmt);
|
||||
Image_ChangeFormat(mips, args->flags, PTI_INVALID, inname);
|
||||
if (mips->encoding == targfmt)
|
||||
return true;
|
||||
|
||||
//switch to common formats...
|
||||
for (m = 0; m < PTI_MAX; m++)
|
||||
sh_config.texfmt[m] = (m == targfmt) || (m==PTI_RGBA8);
|
||||
Image_ChangeFormat(mips, args->flags, PTI_INVALID, inname);
|
||||
//and try again...
|
||||
for (m = 0; m < PTI_MAX; m++)
|
||||
sh_config.texfmt[m] = (m == targfmt);
|
||||
Image_ChangeFormat(mips, args->flags, PTI_INVALID, inname);
|
||||
|
||||
return (mips->encoding == targfmt);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (canktx)
|
||||
FS_MakeTempName(raw, sizeof(raw), "itr", ".ktx");
|
||||
else
|
||||
|
@ -397,6 +479,27 @@ static qboolean ImgTool_ConvertPixelFormat(struct opts_s *args, const char *inna
|
|||
Q_strncatz(command, " -normal", sizeof(command)); //looks like a normalmap... tweak metrics to favour normalised results.
|
||||
Q_strncatz(command, ">> /dev/null", sizeof(command));
|
||||
|
||||
|
||||
if (!canktx)
|
||||
{
|
||||
//make sure the source pixel format is acceptable if we're forced to write a png
|
||||
for (m = 0; m < PTI_MAX; m++)
|
||||
sh_config.texfmt[m] =
|
||||
(m == PTI_RGBA8) || (m == PTI_RGBX8) ||
|
||||
(m == PTI_BGRA8) || (m == PTI_BGRX8) ||
|
||||
(m == PTI_LLLA8) || (m == PTI_LLLX8) ||
|
||||
(m == PTI_RGBA16) ||
|
||||
(m == PTI_L8) || (m == PTI_L8A8) ||
|
||||
/*(m == PTI_L16) ||*/
|
||||
(m == PTI_BGR8) || (m == PTI_BGR8) ||
|
||||
0;
|
||||
Image_ChangeFormat(mips, args->flags&~IF_PREMULTIPLYALPHA, PTI_INVALID, inname);
|
||||
|
||||
//make sure we properly read whatever is given back to us
|
||||
for (m = 1; m < countof(sh_config.texfmt); m++)
|
||||
sh_config.texfmt[m] = true;
|
||||
}
|
||||
|
||||
Image_BlockSizeForEncoding(mips->encoding, &bb, &bw, &bh);
|
||||
for (m = 0; m < mips->mipcount; m++)
|
||||
{
|
||||
|
@ -467,7 +570,7 @@ const char *COM_GetFileExtension (const char *in, const char *term)
|
|||
static void ImgTool_Convert(struct opts_s *args, const char *inname, const char *outname)
|
||||
{
|
||||
qbyte *indata;
|
||||
size_t fsize;
|
||||
size_t fsize, k;
|
||||
struct pendingtextureinfo *in;
|
||||
const char *outext = COM_GetFileExtension(outname, NULL);
|
||||
qboolean allowcompressed = false;
|
||||
|
@ -482,19 +585,30 @@ static void ImgTool_Convert(struct opts_s *args, const char *inname, const char
|
|||
if (in)
|
||||
{
|
||||
printf("%s: %s, %i*%i, %i mips\n", inname, Image_FormatName(in->encoding), in->mip[0].width, in->mip[0].height, in->mipcount);
|
||||
/*if (imgtool_convertto >= PTI_BC1_RGB && imgtool_convertto <= PTI_BC5_RG8_SNORM)
|
||||
ImgTool_ConvertToBCn(imgtool_convertto, in);
|
||||
else*/
|
||||
{
|
||||
if (!(args->flags & IF_NOMIPMAP) && in->mipcount == 1)
|
||||
Image_GenerateMips(in, args->flags);
|
||||
|
||||
if (args->newpixelformat != PTI_INVALID && allowcompressed && ImgTool_ConvertPixelFormat(args, inname, in))
|
||||
printf("\t(Converted to %s)\n", Image_FormatName(in->encoding));
|
||||
if (!(args->flags & IF_NOMIPMAP) && in->mipcount == 1)
|
||||
Image_GenerateMips(in, args->flags);
|
||||
|
||||
if (args->mipnum >= in->mipcount)
|
||||
{
|
||||
ImgTool_FreeMips(in);
|
||||
Con_Printf("%s: Requested output mip number was out of bounds %i >= %i\n", outname, args->mipnum, in->mipcount);
|
||||
return;
|
||||
}
|
||||
for (k = 0; k < args->mipnum; k++)
|
||||
{
|
||||
if (in->mip[k].needfree)
|
||||
BZ_Free(in->mip[k].data);
|
||||
}
|
||||
in->mipcount -= k;
|
||||
memmove(in->mip, &in->mip[k], sizeof(in->mip[0])*in->mipcount);
|
||||
|
||||
if (args->newpixelformat != PTI_INVALID && (args->newpixelformat < PTI_BC1_RGB || allowcompressed) && ImgTool_ConvertPixelFormat(args, inname, in))
|
||||
printf("\t(Converted to %s)\n", Image_FormatName(in->encoding));
|
||||
|
||||
if (!in->mipcount)
|
||||
{
|
||||
ImgTool_FreeMips(in);
|
||||
printf("%s: unable to convert any mips\n", inname);
|
||||
return;
|
||||
}
|
||||
|
@ -503,47 +617,83 @@ static void ImgTool_Convert(struct opts_s *args, const char *inname, const char
|
|||
;
|
||||
#ifdef IMAGEFMT_KTX
|
||||
else if (!strcmp(outext, ".ktx"))
|
||||
Image_WriteKTXFile(outname, FS_SYSTEM, in);
|
||||
{
|
||||
if (!Image_WriteKTXFile(outname, FS_SYSTEM, in))
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGEFMT_DDS
|
||||
else if (!strcmp(outext, ".dds"))
|
||||
Image_WriteDDSFile(outname, FS_SYSTEM, in);
|
||||
{
|
||||
if (!Image_WriteDDSFile(outname, FS_SYSTEM, in))
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int bb,bw,bh;
|
||||
Image_BlockSizeForEncoding(in->encoding, &bb, &bw,&bh);
|
||||
if (args->mipnum < in->mipcount)
|
||||
{
|
||||
if (0)
|
||||
;
|
||||
|
||||
if (0)
|
||||
;
|
||||
#ifdef IMAGEFMT_PNG
|
||||
else if (!strcmp(outext, ".png"))
|
||||
{
|
||||
else if (!strcmp(outext, ".png"))
|
||||
{
|
||||
#ifdef AVAIL_PNGLIB
|
||||
if (!Image_WritePNG(outname, FS_SYSTEM, 0, &in->mip[args->mipnum].data, 1, in->mip[args->mipnum].width*bb, in->mip[args->mipnum].width, in->mip[args->mipnum].height, in->encoding, false))
|
||||
#endif
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
//force the format, because we can.
|
||||
for (k = 0; k < PTI_MAX; k++)
|
||||
sh_config.texfmt[k] =
|
||||
(k == PTI_RGBA8) || (k == PTI_RGBX8) ||
|
||||
(k == PTI_BGRA8) || (k == PTI_BGRX8) ||
|
||||
(k == PTI_LLLA8) || (k == PTI_LLLX8) ||
|
||||
(k == PTI_RGBA16) ||
|
||||
(k == PTI_L8) || (k == PTI_L8A8) ||
|
||||
/*(k == PTI_L16) ||*/
|
||||
(k == PTI_BGR8) || (k == PTI_BGR8) ||
|
||||
0;
|
||||
if (!sh_config.texfmt[in->encoding])
|
||||
{
|
||||
Image_ChangeFormat(in, args->flags&~IF_PREMULTIPLYALPHA, PTI_INVALID, inname);
|
||||
printf("\t(Exporting as %s)\n", Image_FormatName(in->encoding));
|
||||
}
|
||||
Image_BlockSizeForEncoding(in->encoding, &bb, &bw,&bh);
|
||||
if (!Image_WritePNG(outname, FS_SYSTEM, 0, &in->mip[0].data, 1, in->mip[0].width*bb, in->mip[0].width, in->mip[0].height, in->encoding, false))
|
||||
#endif
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
}
|
||||
#endif
|
||||
#ifdef IMAGEFMT_TGA
|
||||
else if (!strcmp(outext, ".tga"))
|
||||
else if (!strcmp(outext, ".tga"))
|
||||
{
|
||||
for (k = 0; k < PTI_MAX; k++)
|
||||
sh_config.texfmt[k] =
|
||||
(k == PTI_RGBA8) || (k == PTI_RGBX8) ||
|
||||
(k == PTI_BGRA8) || (k == PTI_BGRX8) ||
|
||||
(k == PTI_LLLA8) || (k == PTI_LLLX8) ||
|
||||
(k == PTI_RGBA16F) || (k == PTI_R16F) || //half-float tgas is a format extension, but allow it.
|
||||
(k == PTI_L8) || (k == PTI_L8A8) ||
|
||||
/*(k == PTI_L16) ||*/
|
||||
(k == PTI_BGR8) || (k == PTI_BGR8) ||
|
||||
0;
|
||||
if (!sh_config.texfmt[in->encoding])
|
||||
{
|
||||
if (!WriteTGA(outname, FS_SYSTEM, in->mip[args->mipnum].data, in->mip[args->mipnum].width*bb, in->mip[args->mipnum].width, in->mip[args->mipnum].height, in->encoding))
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
Image_ChangeFormat(in, args->flags&~IF_PREMULTIPLYALPHA, PTI_INVALID, inname);
|
||||
printf("\t(Exporting as %s)\n", Image_FormatName(in->encoding));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
Con_Printf("%s: Unknown output file format\n", outname);
|
||||
Image_BlockSizeForEncoding(in->encoding, &bb, &bw,&bh);
|
||||
if (!WriteTGA(outname, FS_SYSTEM, in->mip[0].data, in->mip[0].width*bb, in->mip[0].width, in->mip[0].height, in->encoding))
|
||||
Con_Printf("%s(%s): Write failed\n", outname, Image_FormatName(in->encoding));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
Con_Printf("%s: Requested output mip number was out of bounds %i >= %i\n", outname, args->mipnum, in->mipcount);
|
||||
Con_Printf("%s: Unknown output file format\n", outname);
|
||||
}
|
||||
|
||||
// printf("%s: %s, %i*%i, %i mips\n", outname, Image_FormatName(in->encoding), in->mip[0].width, in->mip[0].height, in->mipcount);
|
||||
|
||||
// for (m = 0; m < in->mipcount; m++)
|
||||
// printf("\t%u: %i*%i*%i, %u\n", (unsigned)m, in->mip[m].width, in->mip[m].height, in->mip[m].depth, (unsigned)in->mip[m].datasize);
|
||||
|
||||
ImgTool_FreeMips(in);
|
||||
}
|
||||
else
|
||||
printf("%s: unsupported format\n", inname);
|
||||
|
@ -571,6 +721,8 @@ static void ImgTool_Info(struct opts_s *args, const char *inname)
|
|||
printf("%s: %s, %i*%i, %i mips\n", inname, Image_FormatName(in->encoding), in->mip[0].width, in->mip[0].height, in->mipcount);
|
||||
for (m = 0; m < in->mipcount; m++)
|
||||
printf("\t%u: %i*%i*%i, %u\n", (unsigned)m, in->mip[m].width, in->mip[m].height, in->mip[m].depth, (unsigned)in->mip[m].datasize);
|
||||
|
||||
ImgTool_FreeMips(in);
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
|
@ -731,27 +883,26 @@ static void ImgTool_TreeConvert(struct opts_s *args, const char *srcpath, const
|
|||
|
||||
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
long offset; // Position of the entry in WAD
|
||||
long dsize; // Size of the entry in WAD file
|
||||
long size; // Size of the entry in memory
|
||||
char type; // type of entry
|
||||
char cmprs; // Compression. 0 if none.
|
||||
short dummy; // Not used
|
||||
char name[16]; // we use only first 8
|
||||
unsigned int offset; // Position of the entry in WAD
|
||||
unsigned int dsize; // Size of the entry in WAD file
|
||||
unsigned int size; // Size of the entry in memory
|
||||
char type; // type of entry
|
||||
char cmprs; // Compression. 0 if none.
|
||||
short dummy; // Not used
|
||||
char name[16]; // we use only first 8
|
||||
} wad2entry_t;
|
||||
typedef struct
|
||||
{
|
||||
char magic[4]; //should be WAD2
|
||||
long num; //number of entries
|
||||
long offset; //location of directory
|
||||
char magic[4]; //should be WAD2
|
||||
unsigned int num; //number of entries
|
||||
unsigned int offset; //location of directory
|
||||
} wad2_t;
|
||||
static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const char *destpath)
|
||||
static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const char *destpath, int wadtype/*x,2,3*/)
|
||||
{
|
||||
char file[MAX_OSPATH];
|
||||
const char *exts[] = {".png", ".bmp", ".tga", ".jpg", ".exr", ".hdr", NULL};
|
||||
const char *exts[] = {".png", ".bmp", ".tga", ".exr", ".hdr", ".dds", ".ktx", ".xcf", ".pcx", ".jpg", NULL};
|
||||
struct filelist_s list = {exts};
|
||||
size_t i, u;
|
||||
vfsfile_t *f;
|
||||
|
@ -760,7 +911,7 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
size_t fsize;
|
||||
wad2_t wad2;
|
||||
wad2entry_t *wadentries = NULL, *entry;
|
||||
size_t maxentries;
|
||||
size_t maxentries = 0;
|
||||
miptex_t mip;
|
||||
ImgTool_TreeScan(&list, srcpath, NULL);
|
||||
|
||||
|
@ -768,7 +919,9 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
wad2.magic[0] = 'W';
|
||||
wad2.magic[1] = 'A';
|
||||
wad2.magic[2] = 'D';
|
||||
wad2.magic[3] = '3'; //wad3 instead of 2, so we can include a palette for tools to validate against
|
||||
wad2.magic[3] = (wadtype==2)?'3':'2'; //wad3 instead of 2, so we can include a palette for tools to validate against
|
||||
wad2.num = 0;
|
||||
wad2.offset = 0;
|
||||
VFS_WRITE(f, &wad2, 12);
|
||||
|
||||
//try to decompress everything to a nice friendly palletizable range.
|
||||
|
@ -787,7 +940,7 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
indata = FS_LoadMallocFile(file, &fsize);
|
||||
if (indata)
|
||||
{
|
||||
struct pendingtextureinfo *in = Image_LoadMipsFromMemory(args->flags|IF_PALETTIZE, inname, file, indata, fsize);
|
||||
struct pendingtextureinfo *in = Image_LoadMipsFromMemory(args->flags, inname, file, indata, fsize);
|
||||
Image_GenerateMips(in, args->flags);
|
||||
if (in)
|
||||
{
|
||||
|
@ -796,17 +949,56 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
|
||||
if (!in->mipcount)
|
||||
{
|
||||
printf("%s: unable to load any mips\n", inname);
|
||||
ImgTool_FreeMips(in);
|
||||
Con_Printf("%s: unable to load any mips\n", inname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (args->mipnum >= in->mipcount)
|
||||
{
|
||||
printf("%s: not enough mips\n", inname);
|
||||
ImgTool_FreeMips(in);
|
||||
Con_Printf("%s: not enough mips\n", inname);
|
||||
continue;
|
||||
}
|
||||
|
||||
//strip out all but the 4 mip levels we care about.
|
||||
for (u = 0; u < in->mipcount; u++)
|
||||
{
|
||||
if (u >= args->mipnum && u < args->mipnum+4)
|
||||
{
|
||||
if (!wadtype)
|
||||
{ //if we're stripping out the wad data (so that the engine ends up requiring external textures) then do it now before palettizing, for efficiency.
|
||||
if (in->mip[u].needfree)
|
||||
BZ_Free(in->mip[u].data);
|
||||
in->mip[u].data = NULL;
|
||||
in->mip[u].datasize = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in->mip[u].needfree)
|
||||
BZ_Free(in->mip[u].data);
|
||||
memset(&in->mip[u], 0, sizeof(in->mip[u]));
|
||||
}
|
||||
}
|
||||
in->mipcount -= args->mipnum;
|
||||
if (in->mipcount > 4)
|
||||
in->mipcount = 4;
|
||||
memmove(&in->mip[0], &in->mip[args->mipnum], sizeof(in->mip[0])*in->mipcount);
|
||||
memset(&in->mip[in->mipcount], 0, sizeof(in->mip[0])*((args->mipnum+4)-in->mipcount)); //null it out, just in case.
|
||||
if (!in->mip[0].width || (in->mip[0].width & 15))
|
||||
Con_Printf("%s(%i): WARNING: miptex width is not a multiple of 16 - %i*%i\n", inname, args->mipnum, in->mip[0].width, in->mip[0].height);
|
||||
if (!in->mip[0].height || (in->mip[0].height & 15))
|
||||
Con_Printf("%s(%i): WARNING: miptex height is not a not multiple of 16 - %i*%i\n", inname, args->mipnum, in->mip[0].width, in->mip[0].height);
|
||||
|
||||
if (in->encoding != PTI_P8)
|
||||
Image_ChangeFormat(in, IF_PALETTIZE, (*inname=='{')?TF_TRANS8:PTI_INVALID, inname);
|
||||
if (in->encoding != PTI_P8)
|
||||
{ //erk! we failed to palettize...
|
||||
ImgTool_FreeMips(in);
|
||||
continue;
|
||||
}
|
||||
if ((in->mip[args->mipnum].width|in->mip[args->mipnum].height) & 15)
|
||||
printf("%s(%i): WARNING: not multiple of 16 - %i*%i\n", inname, args->mipnum, in->mip[args->mipnum].width, in->mip[args->mipnum].height);
|
||||
|
||||
if (wad2.num == maxentries)
|
||||
{
|
||||
|
@ -816,24 +1008,28 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
entry = &wadentries[wad2.num++];
|
||||
Q_strncpyz(entry->name, inname, 16);
|
||||
entry->name[list.file[i].baselen] = 0; //kill any .tga
|
||||
if (*entry->name == '#')
|
||||
*entry->name = '*'; //* is not valid in a filename, yet needed for turbs, so by convention # is used instead. this is only relevant for the first char.
|
||||
entry->type = TYP_MIPTEX;
|
||||
entry->cmprs = 0;
|
||||
entry->dummy = 0;
|
||||
entry->offset = VFS_TELL(f);
|
||||
|
||||
memcpy(mip.name, entry->name, sizeof(mip.name));
|
||||
mip.width = in->mip[args->mipnum].width;
|
||||
mip.height = in->mip[args->mipnum].height;
|
||||
mip.offsets[0] = in->mip[args->mipnum+0].datasize?sizeof(mip):0;
|
||||
mip.offsets[1] = in->mip[args->mipnum+1].datasize?mip.offsets[args->mipnum+0]+in->mip[args->mipnum+0].datasize:0;
|
||||
mip.offsets[2] = in->mip[args->mipnum+2].datasize?mip.offsets[args->mipnum+1]+in->mip[args->mipnum+1].datasize:0;
|
||||
mip.offsets[3] = in->mip[args->mipnum+3].datasize?mip.offsets[args->mipnum+2]+in->mip[args->mipnum+2].datasize:0;
|
||||
mip.width = in->mip[0].width;
|
||||
mip.height = in->mip[0].height;
|
||||
mip.offsets[0] = in->mip[0].datasize?sizeof(mip):0;
|
||||
mip.offsets[1] = in->mip[1].datasize?mip.offsets[0]+in->mip[0].datasize:0;
|
||||
mip.offsets[2] = in->mip[2].datasize?mip.offsets[1]+in->mip[1].datasize:0;
|
||||
mip.offsets[3] = in->mip[3].datasize?mip.offsets[2]+in->mip[2].datasize:0;
|
||||
|
||||
Con_Printf("%s: %ix%i\n", mip.name, mip.width, mip.height);
|
||||
|
||||
VFS_WRITE(f, &mip, sizeof(mip));
|
||||
VFS_WRITE(f, in->mip[args->mipnum+0].data, in->mip[args->mipnum+0].datasize);
|
||||
VFS_WRITE(f, in->mip[args->mipnum+1].data, in->mip[args->mipnum+1].datasize);
|
||||
VFS_WRITE(f, in->mip[args->mipnum+2].data, in->mip[args->mipnum+2].datasize);
|
||||
VFS_WRITE(f, in->mip[args->mipnum+3].data, in->mip[args->mipnum+3].datasize);
|
||||
VFS_WRITE(f, in->mip[0].data, in->mip[0].datasize);
|
||||
VFS_WRITE(f, in->mip[1].data, in->mip[1].datasize);
|
||||
VFS_WRITE(f, in->mip[2].data, in->mip[2].datasize);
|
||||
VFS_WRITE(f, in->mip[3].data, in->mip[3].datasize);
|
||||
if (wad2.magic[3] == '3')
|
||||
{
|
||||
VFS_WRITE(f, "\x00\x01", 2);
|
||||
|
@ -841,6 +1037,7 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
}
|
||||
|
||||
entry->size = entry->dsize = VFS_TELL(f)-entry->offset;
|
||||
ImgTool_FreeMips(in);
|
||||
}
|
||||
}
|
||||
wad2.offset = VFS_TELL(f);
|
||||
|
@ -851,7 +1048,7 @@ static void ImgTool_WadConvert(struct opts_s *args, const char *srcpath, const c
|
|||
|
||||
FileList_Release(&list);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
|
@ -860,7 +1057,9 @@ int main(int argc, const char **argv)
|
|||
mode_info,
|
||||
mode_convert,
|
||||
mode_autotree,
|
||||
mode_genwad
|
||||
mode_genwadx,
|
||||
mode_genwad2,
|
||||
mode_genwad3,
|
||||
} mode = mode_info;
|
||||
size_t u, f;
|
||||
struct opts_s args;
|
||||
|
@ -881,6 +1080,7 @@ int main(int argc, const char **argv)
|
|||
sh_config.npot_rounddown = true; //shouldn't be relevant
|
||||
sh_config.havecubemaps = true; //I don't think this matters.
|
||||
|
||||
ImgTool_SetupPalette();
|
||||
Image_Init();
|
||||
|
||||
if (argc==1)
|
||||
|
@ -897,22 +1097,43 @@ showhelp:
|
|||
Con_Printf("compress : %s --astc_6x6_ldr [--nomips] in.png out.ktx [in2.png out2.ktx]\n", argv[0]);
|
||||
Con_Printf("compress : %s --bc3_rgba [--premul] [--nomips] in.png out.dds\n\tConvert pixel format (to bc3 aka dxt5) before writing to output file.\n", argv[0]);
|
||||
Con_Printf("convert : %s --convert in.exr out.dds\n\tConvert to different file format, while trying to preserve pixel formats.\n", argv[0]);
|
||||
Con_Printf("recursive : %s --astc_6x6_ldr -r srcdir destdir\n", argv[0]);
|
||||
Con_Printf("decompress: %s --decompress [--exportmip 0] [--nomips] in.ktx out.png\n\tDecompresses any block-compressed pixel data.\n", argv[0]);
|
||||
// Con_Printf("gen wad : %s --genwad [--exportmip 2] srcdir out.wad\n", argv[0]);
|
||||
// Con_Printf("auto : %s --astc_6x6_ldr -r _postfix.png srcdir destdir\n", argv[0]);
|
||||
Con_Printf("gen wad : %s --genwad3 [--exportmip 2] srcdir out.wad\n", argv[0]);
|
||||
|
||||
Image_PrintInputFormatVersions();
|
||||
Con_Printf("Supported compressed pixelformats are:\n");
|
||||
Con_Printf("Supported compressed/interesting pixelformats are:\n");
|
||||
for (f = 0; f < PTI_MAX; f++)
|
||||
{
|
||||
int bb,bw,bh;
|
||||
Image_BlockSizeForEncoding(f, &bb,&bw,&bh);
|
||||
if (f >= PTI_ASTC_FIRST && f <= PTI_ASTC_LAST)
|
||||
Con_Printf(" --%-15s %.2fbpp (requires astcenc)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
Con_Printf(" --%-16s %5.3g-bpp (requires astcenc)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
else if (f==PTI_BC1_RGB||f==PTI_BC1_RGBA||f==PTI_BC2_RGBA||f==PTI_BC3_RGBA||f==PTI_BC4_R8||f==PTI_BC5_RG8)
|
||||
Con_Printf(" --%-15s %.2fbpp (requires nvcompress)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
Con_Printf(" --%-16s %5.3g-bpp (requires nvcompress)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
else if (f==PTI_BC6_RGB_UFLOAT || f==PTI_BC6_RGB_SFLOAT || f==PTI_BC7_RGBA)
|
||||
Con_Printf(" --%-15s %.2fbpp (requires nvcompress 2.1+)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
Con_Printf(" --%-16s %5.3g-bpp (requires nvcompress 2.1+)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
else if ( f==PTI_RGBA16F ||
|
||||
f==PTI_RGBA32F ||
|
||||
f==PTI_E5BGR9 ||
|
||||
f==PTI_B10G11R11F ||
|
||||
f==PTI_RGB565 ||
|
||||
f==PTI_RGBA4444 ||
|
||||
f==PTI_ARGB4444 ||
|
||||
f==PTI_RGBA5551 ||
|
||||
f==PTI_ARGB1555 ||
|
||||
f==PTI_A2BGR10 ||
|
||||
// f==PTI_R8 ||
|
||||
// f==PTI_R16 ||
|
||||
// f==PTI_R16F ||
|
||||
// f==PTI_R32F ||
|
||||
f==PTI_RG8 ||
|
||||
f==PTI_L8 ||
|
||||
f==PTI_L8A8 ||
|
||||
0)
|
||||
Con_Printf(" --%-16s %5.3g-bpp\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
// else
|
||||
// Con_DPrintf(" --%-16s %5.3g-bpp (unsupported)\n", Image_FormatName(f), 8*(float)bb/(bw*bh));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -928,8 +1149,12 @@ showhelp:
|
|||
mode = mode_autotree;
|
||||
else if (!strcmp(argv[u], "-i") || !strcmp(argv[u], "--info"))
|
||||
mode = mode_info;
|
||||
else if (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwad"))
|
||||
mode = mode_genwad;
|
||||
else if (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwad3"))
|
||||
mode = mode_genwad3;
|
||||
else if (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwad2"))
|
||||
mode = mode_genwad2;
|
||||
else if (!strcmp(argv[u], "-w") || !strcmp(argv[u], "--genwadx"))
|
||||
mode = mode_genwadx;
|
||||
else if (!strcmp(argv[u], "--nomips") )
|
||||
args.flags |= IF_NOMIPMAP;
|
||||
else if (!strcmp(argv[u], "--mips"))
|
||||
|
@ -989,11 +1214,11 @@ showhelp:
|
|||
u++;
|
||||
}
|
||||
}
|
||||
else if (mode == mode_genwad)
|
||||
else if (mode == mode_genwad2 || mode == mode_genwad3 || mode == mode_genwadx)
|
||||
{
|
||||
if (u+1 < argc)
|
||||
{
|
||||
//ImgTool_WadConvert(&args, argv[u], argv[u+1]);
|
||||
ImgTool_WadConvert(&args, argv[u], argv[u+1], mode-mode_genwadx);
|
||||
u++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue