/* lutflat.c : LUT flattener. Converts DDS Volume Map LUTs back into flat textures. (C)2017 Marisa Kirisame, UnSX Team. Released under the MIT license. */ #include #include #include #include #include #include #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) uint8_t *indata, *outdata; int width, height, depth; unsigned pngw, pngh; int flattenlut( void ) { int x = 0, y = 0, z = 0, i = 0, s = width*height*depth*4; /* guess the format */ if ( (width == 256) && (height == 256) && (depth == 256) ) { printf("flatten: 256x256x256 table\n"); pngw = pngh = 4096; while ( i < s ) { outdata[(x+y*4096+(z&0x0F)*1048576+(z&0xF0)*16)*3] = indata[i++]; outdata[(x+y*4096+(z&0x0F)*1048576+(z&0xF0)*16)*3+1] = indata[i++]; outdata[(x+y*4096+(z&0x0F)*1048576+(z&0xF0)*16)*3+2] = indata[i++]; i++; x++; if ( x >= 256 ) { x = 0; y++; } if ( y >= 256 ) { y = 0; z++; } } return 1; } else if ( (width == 64) && (height == 64) && (depth == 64) ) { printf("flatten: 64x64x64 table\n"); pngw = pngh = 512; while ( i < s ) { outdata[(x+y*512+(z&0x7)*32768+(z&0x38)*8)*3] = indata[i++]; outdata[(x+y*512+(z&0x7)*32768+(z&0x38)*8)*3+1] = indata[i++]; outdata[(x+y*512+(z&0x7)*32768+(z&0x38)*8)*3+2] = indata[i++]; i++; x++; if ( x >= 64 ) { x = 0; y++; } if ( y >= 64 ) { y = 0; z++; } } return 1; } else if ( (width == 32) && (height == 32) && (depth == 32) ) { printf("flatten: 32x32x32 table\n"); pngw = 1024; pngh = 32; while ( i < s ) { outdata[(x+y*1024+z*32)*3] = indata[i++]; outdata[(x+y*1024+z*32)*3+1] = indata[i++]; outdata[(x+y*1024+z*32)*3+2] = indata[i++]; i++; x++; if ( x >= 32 ) { x = 0; y++; } if ( y >= 32 ) { y = 0; z++; } } return 1; } else if ( (width == 16) && (height == 16) && (depth == 16) ) { printf("flatten: 16x16x16 table\n"); pngw = pngh = 64; while ( i < s ) { outdata[(x+y*64+(z&0x3)*1024+(z&0xc)*4)*3] = indata[i++]; outdata[(x+y*64+(z&0x3)*1024+(z&0xc)*4)*3+1] = indata[i++]; outdata[(x+y*64+(z&0x3)*1024+(z&0xc)*4)*3+2] = indata[i++]; i++; x++; if ( x >= 16 ) { x = 0; y++; } if ( y >= 16 ) { y = 0; z++; } } return 1; } printf("flat: Unsupported dimensions %ux%ux%u\n",width,height,depth); return 0; } int savepng( const char *filename ) { if ( !filename ) { printf("png: no filename passed\n"); return 1; } png_structp pngp; png_infop infp; FILE *pf; if ( !(pf = fopen(filename,"wb")) ) { printf("png: could not open file: %s\n",strerror(errno)); return 1; } pngp = png_create_write_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_write_struct(&pngp,&infp); return 1; } if ( setjmp(png_jmpbuf(pngp)) ) { printf("png: failed to set up error handler\n"); png_destroy_write_struct(&pngp,&infp); fclose(pf); return 1; } png_init_io(pngp,pf); png_set_IHDR(pngp,infp,pngw,pngh,8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(pngp,infp); png_bytepp rptr = malloc(sizeof(png_bytep)*pngh); for ( unsigned i=0; i