I guess I can just put this up. Most of these have been sitting here forever.
This commit is contained in:
commit
d2777092d1
26 changed files with 5347 additions and 0 deletions
578
lutconv2.c
Normal file
578
lutconv2.c
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
lutconv2.c : Improved, general purpose LUT converter.
|
||||
Turns 2D LUT textures into DDS Volume Maps for convenience.
|
||||
(C)2017 Marisa Kirisame, UnSX Team.
|
||||
Released under the GNU General Public License version 3 (or later).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <png.h>
|
||||
|
||||
#define dword uint32_t
|
||||
#define byte uint8_t
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
dword magic, size, flags, height, width, pitch, depth, mipmaps,
|
||||
reserved1[11], pf_size, pf_flags, pf_fourcc, pf_bitcount, pf_rmask,
|
||||
pf_gmask, pf_bmask, pf_amask, caps[4], reserved2;
|
||||
} ddsheader_t;
|
||||
#pragma pack(pop)
|
||||
ddsheader_t ddshead =
|
||||
{
|
||||
.magic = 0x20534444, .size = 124, .flags = 0x0080100f, .height = 0,
|
||||
.width = 0, .pitch = 0, .depth = 0, .mipmaps = 0,
|
||||
.reserved1 = {0,0,0,0,0,0,0,0,0,0,0}, .pf_size = 32, .pf_flags = 0x41,
|
||||
.pf_fourcc = 0, .pf_bitcount = 32, .pf_rmask = 0xff,
|
||||
.pf_gmask = 0xff00, .pf_bmask = 0xff0000, .pf_amask = 0xff000000,
|
||||
.caps = {0x1000,0x200000,0,0}, .reserved2 = 0
|
||||
};
|
||||
|
||||
uint8_t *indata, *outdata;
|
||||
int width, height, depth, alpha;
|
||||
|
||||
/* vertical strip LUT, the format I use */
|
||||
int vertconv( void )
|
||||
{
|
||||
int x, y, z, i, s;
|
||||
ddshead.pf_flags = 0x41;
|
||||
ddshead.pf_bitcount = 32;
|
||||
/* guess the format */
|
||||
if ( (width == 8) && (height == 4096) )
|
||||
{
|
||||
/* VGA 8x16 font table */
|
||||
printf("conv: VGA 8x16 font table\n");
|
||||
ddshead.width = width = 8;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 256;
|
||||
ddshead.pitch = 8*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
if ( alpha ) outdata[i++] = indata[x++];
|
||||
else outdata[i++] = 255;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 16) && (height == 256) )
|
||||
{
|
||||
/* unpadded 16x16x16 LUT */
|
||||
printf("conv: vertical 16x16x16 LUT\n");
|
||||
ddshead.width = width = 16;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 16;
|
||||
ddshead.pitch = 16*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
if ( alpha ) outdata[i++] = indata[x++];
|
||||
else outdata[i++] = 255;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 32) && (height == 512) )
|
||||
{
|
||||
/* padded 16x16x16 LUT */
|
||||
printf("conv: vertical padded 16x16x16 LUT\n");
|
||||
ddshead.width = width = 16;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 16;
|
||||
ddshead.pitch = 16*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 8;
|
||||
y = 8;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*32+z*512)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*32+z*512)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*32+z*512)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[(x+y*32+z*512)
|
||||
*(3+alpha)+3];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 24 )
|
||||
{
|
||||
x = 8;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 24 )
|
||||
{
|
||||
y = 8;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 64) && (height == 64) )
|
||||
{
|
||||
/* square 16x16x16 LUT (assuming column-major grid) */
|
||||
printf("conv: column-major 4x4 grid 16x16x16 LUT\n");
|
||||
ddshead.width = width = 16;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 16;
|
||||
ddshead.pitch = 16*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*64+(z&0x3)*1024
|
||||
+(z&0xc)*4)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*64+(z&0x3)*1024
|
||||
+(z&0xc)*4)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*64+(z&0x3)*1024
|
||||
+(z&0xc)*4)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[indata[(x+y*64+(z&0x3)
|
||||
*1024+(z&0xc)*4)*(3+alpha)+3]];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 16 )
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 16 )
|
||||
{
|
||||
y = 0;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 64) && (height == 4096) )
|
||||
{
|
||||
/* unpadded 64x64x64 LUT */
|
||||
printf("conv: vertical 64x64x64 LUT\n");
|
||||
ddshead.width = width = 64;
|
||||
ddshead.height = height = 64;
|
||||
ddshead.depth = depth = 64;
|
||||
ddshead.pitch = 64*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
if ( alpha ) outdata[i++] = indata[x++];
|
||||
else outdata[i++] = 255;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 128) && (height == 8192) )
|
||||
{
|
||||
/* padded 64x64x64 LUT */
|
||||
printf("conv: vertical padded 64x64x64 LUT\n");
|
||||
ddshead.width = width = 64;
|
||||
ddshead.height = height = 64;
|
||||
ddshead.depth = depth = 64;
|
||||
ddshead.pitch = 64*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 32;
|
||||
y = 32;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*128+z*16384)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*128+z*16384)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*128+z*16384)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[(x+y*128+z*16384)
|
||||
*(3+alpha)+3];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 96 )
|
||||
{
|
||||
x = 32;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 96 )
|
||||
{
|
||||
y = 32;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 512) && (height == 512) )
|
||||
{
|
||||
/* square 64x64x64 LUT (assuming column-major grid) */
|
||||
printf("conv: column-major 8x8 grid 64x64x64 LUT\n");
|
||||
ddshead.width = width = 64;
|
||||
ddshead.height = height = 64;
|
||||
ddshead.depth = depth = 64;
|
||||
ddshead.pitch = 64*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*512+(z&0x7)*32768
|
||||
+(z&0x38)*8)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*512+(z&0x7)*32768
|
||||
+(z&0x38)*8)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*512+(z&0x7)*32768
|
||||
+(z&0x38)*8)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[indata[(x+y*512+(z&0x7)
|
||||
*32768+(z&0x38)*16)*(3+alpha)+3]];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 64 )
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 64 )
|
||||
{
|
||||
y = 0;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 256) && (height == 65536) )
|
||||
{
|
||||
/* unpadded 256x256x256 LUT (rare) */
|
||||
printf("conv: vertical 256x256x256 LUT\n");
|
||||
ddshead.width = width = 256;
|
||||
ddshead.height = height = 256;
|
||||
ddshead.depth = depth = 256;
|
||||
ddshead.pitch = 256*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
outdata[i++] = indata[x++];
|
||||
if ( alpha ) outdata[i++] = indata[x++];
|
||||
else outdata[i++] = 255;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 512) && (height == 131072) )
|
||||
{
|
||||
/* padded 256x256x256 LUT (very rare) */
|
||||
printf("conv: vertical padded 256x256x256 LUT\n");
|
||||
ddshead.width = width = 256;
|
||||
ddshead.height = height = 256;
|
||||
ddshead.depth = depth = 256;
|
||||
ddshead.pitch = 256*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 128;
|
||||
y = 128;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*512+z*262144)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*512+z*262144)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*512+z*262144)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[(x+y*512+z*262144)
|
||||
*(3+alpha)+3];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 384 )
|
||||
{
|
||||
x = 128;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 384 )
|
||||
{
|
||||
y = 128;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if ( (width == 4096) && (height == 4096) )
|
||||
{
|
||||
/* square 256x256x256 LUT (assuming column-major grid) */
|
||||
printf("conv: column-major 16x16 grid 256x256x256 LUT\n");
|
||||
ddshead.width = width = 256;
|
||||
ddshead.height = height = 256;
|
||||
ddshead.depth = depth = 256;
|
||||
ddshead.pitch = 256*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*4096+(z&0x0F)*1048576
|
||||
+(z&0xF0)*16)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*4096+(z&0x0F)*1048576
|
||||
+(z&0xF0)*16)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*4096+(z&0x0F)*1048576
|
||||
+(z&0xF0)*16)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[indata[(x+y*4096+(z&0x0F)
|
||||
*1048576+(z&0xF0)*16)*(3+alpha)+3]];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 256 )
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 256 )
|
||||
{
|
||||
y = 0;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
printf("conv: Never heard of a LUT texture of %ux%u\n",width,height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* horizontal strip LUT, what everyone else except me uses */
|
||||
int horconv( void )
|
||||
{
|
||||
int x, y, z, i, s;
|
||||
ddshead.pf_flags = 0x41;
|
||||
ddshead.pf_bitcount = 32;
|
||||
/* guess the format */
|
||||
if ( (width == 256) && (height == 16) )
|
||||
{
|
||||
/* 16x16x16 LUT */
|
||||
printf("conv: horizontal 16x16x16 LUT\n");
|
||||
ddshead.width = width = 16;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 16;
|
||||
ddshead.pitch = 16*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*256+z*16)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*256+z*16)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*256+z*16)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[(x+y*256+z*16)
|
||||
*(3+alpha)+3];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 16 )
|
||||
{
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 16 )
|
||||
{
|
||||
y = 0;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if ( (width == 512) && (height == 32) )
|
||||
{
|
||||
/* padded 16x16x16 LUT */
|
||||
printf("conv: horizontal padded 16x16x16 LUT\n");
|
||||
ddshead.width = width = 16;
|
||||
ddshead.height = height = 16;
|
||||
ddshead.depth = depth = 16;
|
||||
ddshead.pitch = 16*4;
|
||||
s = width*height*depth*4;
|
||||
outdata = malloc(s);
|
||||
i = 0;
|
||||
x = 8;
|
||||
y = 8;
|
||||
z = 0;
|
||||
while ( i < s )
|
||||
{
|
||||
outdata[i++] = indata[(x+y*512+z*32)*(3+alpha)];
|
||||
outdata[i++] = indata[(x+y*512+z*32)*(3+alpha)+1];
|
||||
outdata[i++] = indata[(x+y*512+z*32)*(3+alpha)+2];
|
||||
if ( alpha )
|
||||
outdata[i++] = indata[(x+y*512+z*32)
|
||||
*(3+alpha)+3];
|
||||
else outdata[i++] = 255;
|
||||
x++;
|
||||
if ( x >= 24 )
|
||||
{
|
||||
x = 8;
|
||||
y++;
|
||||
}
|
||||
if ( y >= 24 )
|
||||
{
|
||||
y = 8;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
printf("conv: Never heard of a LUT texture of %ux%u\n",width,height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* png loader code, boilerplate written according to official docs */
|
||||
int loadpng( const char *filename )
|
||||
{
|
||||
if ( !filename )
|
||||
{
|
||||
printf("png: no filename passed\n");
|
||||
return 1;
|
||||
}
|
||||
png_structp pngp;
|
||||
png_infop infp;
|
||||
unsigned int sread = 0;
|
||||
int col, inter;
|
||||
FILE *pf;
|
||||
if ( !(pf = fopen(filename,"rb")) )
|
||||
{
|
||||
printf("png: could not open file: %s\n",strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
unsigned char header[8];
|
||||
fread(header,8,1,pf);
|
||||
if ( png_sig_cmp(header,0,8) )
|
||||
{
|
||||
printf("png: bad signature, not a PNG file\n");
|
||||
return 1;
|
||||
}
|
||||
sread += 8;
|
||||
pngp = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
|
||||
if ( !pngp )
|
||||
{
|
||||
printf("png: failed to create png_struct\n");
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
infp = png_create_info_struct(pngp);
|
||||
if ( !infp )
|
||||
{
|
||||
printf("png: failed to create png_info\n");
|
||||
fclose(pf);
|
||||
png_destroy_read_struct(&pngp,0,0);
|
||||
return 1;
|
||||
}
|
||||
if ( setjmp(png_jmpbuf(pngp)) )
|
||||
{
|
||||
printf("png: failed to set up error handler\n");
|
||||
png_destroy_read_struct(&pngp,&infp,0);
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
png_init_io(pngp,pf);
|
||||
png_set_sig_bytes(pngp,sread);
|
||||
png_read_png(pngp,infp,PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_PACKING
|
||||
|PNG_TRANSFORM_EXPAND,0);
|
||||
png_uint_32 w,h;
|
||||
int dep;
|
||||
png_get_IHDR(pngp,infp,&w,&h,&dep,&col,&inter,0,0);
|
||||
if ( (col != PNG_COLOR_TYPE_RGB) && (col != PNG_COLOR_TYPE_RGB_ALPHA) )
|
||||
{
|
||||
printf("png: only RGB or RGBA are supported\n");
|
||||
png_destroy_read_struct(&pngp,&infp,0);
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
if ( dep != 8 )
|
||||
{
|
||||
printf("png: only 8-bit channels are supported\n");
|
||||
png_destroy_read_struct(&pngp,&infp,0);
|
||||
fclose(pf);
|
||||
return 1;
|
||||
}
|
||||
width = w;
|
||||
height = h;
|
||||
alpha = (col==PNG_COLOR_TYPE_RGB_ALPHA);
|
||||
int rbytes = png_get_rowbytes(pngp,infp);
|
||||
indata = malloc(rbytes*h);
|
||||
png_bytepp rptr = png_get_rows(pngp,infp);
|
||||
for ( unsigned i=0; i<h; i++ )
|
||||
memcpy(indata+(rbytes*i),rptr[i],rbytes);
|
||||
png_destroy_read_struct(&pngp,&infp,0);
|
||||
fclose(pf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
printf("LUTCONV 2.0 - (C)2017 Marisa Kirisame, UnSX Team.\n"
|
||||
"This program is free software under the GNU GPL v3.\n"
|
||||
"See https://www.gnu.org/licenses/gpl.html for details.\n\n");
|
||||
if ( argc < 2 )
|
||||
{
|
||||
printf("No files have been passed for processing.\n");
|
||||
return 1;
|
||||
}
|
||||
FILE *fout;
|
||||
char fname[255] = {0};
|
||||
char *ext;
|
||||
for ( int i=1; i<argc; i++ )
|
||||
{
|
||||
if ( loadpng(argv[i]) )
|
||||
{
|
||||
printf("Failed to load %s\n",argv[i]);
|
||||
continue;
|
||||
}
|
||||
int res = (width>height)?horconv():vertconv();
|
||||
free(indata);
|
||||
if ( !res )
|
||||
{
|
||||
printf("Failed to process %s\n",argv[i]);
|
||||
continue;
|
||||
}
|
||||
strcpy(fname,argv[i]);
|
||||
ext = strrchr(fname,'.');
|
||||
if ( ext ) *ext = 0;
|
||||
strcat(fname,".dds");
|
||||
fout = fopen(fname,"wb");
|
||||
if ( !fout )
|
||||
{
|
||||
printf("Cannot open %s: %s\n",fname,strerror(errno));
|
||||
free(outdata);
|
||||
continue;
|
||||
}
|
||||
fwrite(&ddshead,sizeof(ddsheader_t),1,fout);
|
||||
fwrite(outdata,width*height*depth*4,1,fout);
|
||||
fclose(fout);
|
||||
free(outdata);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue