// w, h - MAXIMUM image dimentions of final product. Set as 0 to be automatic
//
// version history:
-// v1.03 - Added quality switch
+// v1.03 - Added quality switch, moved init (major api revision)
// v1.02 - Improved box filtering, small bug fixes
// v1.01 - switch to OpenGL normal format for input
// v1.00 - (hgn) first release
#define STB_IMAGE_IMPLEMENTATION
#endif
+#define STBI_NO_THREAD_LOCALS
#include "stb/stb_image.h"
#ifdef USE_LIBRGBCX
+ // #define RGBCX_NO_ALGORITHM
#include "librgbcx.h"
-#else
+ #define HAS_DXT_COMPRESSOR
+#endif
+
+#if USE_STB_DXT
#define STB_DXT_IMPLEMENTATION
#include "stb/stb_dxt.h"
+ #define HAS_DXT_COMPRESSOR
+#endif
+
+#ifndef HAS_DXT_COMPRESSOR
+ #warning No DXT compressor specified! S3 Output will be invalid.
#endif
#ifdef NBVTF_SHOW_STDERR
#pragma pack(pop)
+#pragma pack(push, 1)
+struct DDS_PIXELFORMAT
+{
+ uint32_t dwSize;
+ uint32_t dwFlags;
+ uint32_t dwFourCC;
+ uint32_t dwRGBBitCount;
+ uint32_t dwRBitMask;
+ uint32_t dwGBitMask;
+ uint32_t dwBBitMask;
+ uint32_t dwABitMask;
+};
+
+struct DDS_HEADER {
+ uint32_t dwSize;
+ uint32_t dwFlags;
+ uint32_t dwHeight;
+ uint32_t dwWidth;
+ uint32_t dwPitchOrLinearSize;
+ uint32_t dwDepth;
+ uint32_t dwMipMapCount;
+ uint32_t dwReserved1[11];
+ struct DDS_PIXELFORMAT ddspf;
+ uint32_t dwCaps;
+ uint32_t dwCaps2;
+ uint32_t dwCaps3;
+ uint32_t dwCaps4;
+ uint32_t dwReserved2;
+};
+
+#pragma pack(pop)
+
+uint32_t swap_endian(uint32_t val)
+{
+ return (val << 24) | ((val << 8) & 0x00ff0000) |
+ ((val >> 8) & 0x0000ff00) | (val >> 24);
+}
+
+#define DDSD_CAPS 0x1
+#define DDSD_HEIGHT 0x2
+#define DDSD_WIDTH 0x4
+#define DDSD_PITCH 0x8
+#define DDSD_PIXELFORMAT 0x1000
+#define DDSD_MIPMAPCOUNT 0x20000
+#define DDSD_LINEARSIZE 0x80000
+#define DDSD_DEPTH 0x800000
+
+#define DDPF_ALPHAPIXELS 0x1
+#define DDPF_ALPHA 0x2
+#define DDPF_FOURCC 0x4
+#define DDPF_RGB 0x40
+#define DDPF_YUV 0x200
+#define DDPF_LUMINANCE 0x20000
+
+#define DDSCAPS_COMPLEX 0x8
+#define DDSCAPS_MIPMAP 0x400000
+#define DDSCAPS_TEXTURE 0x1000
+
+#define BLOCK_SIZE_DXT1 8
+#define BLOCK_SIZE_DXT5 16
+
+#define BBP_RGB888 24
+#define BBP_RGBA8888 32
+
+#define DDS_HEADER_SIZE 124
+#define DDS_HEADER_PFSIZE 32
+#define DDS_MAGICNUM 0x20534444;
+
+#define DDS_FLIP_VERTICALLY_ON_WRITE
+
typedef struct mipimg
{
uint32_t w;
return 0;
}
-void nbvtf_dxt_block( uint8_t *dest, uint8_t *src, int alpha, int qual )
+#ifdef NBVTF_AS_SO
+__attribute__((visibility("default")))
+#endif
+void nbvtf_init(void)
{
#ifdef USE_LIBRGBCX
- // TODO: move this somewehre else
- static int init = 0;
- if( !init )
- {
- rgbcx__init();
- init = 1;
- }
+ rgbcx__init();
+#endif
+}
+void nbvtf_dxt_block( uint8_t *dest, uint8_t *src, int alpha, int qual )
+{
+#ifdef USE_LIBRGBCX
if( alpha )
{
rgbcx__encode_bc3( qual, dest, src );
{
rgbcx__encode_bc1( qual, dest, src, 0, 0 );
}
-#else
+#endif
+
+#if USE_STB_DXT
stb_compress_dxt_block( dest, src, alpha, STB_DXT_HIGHQUAL );
#endif
+
+#ifndef HAS_DXT_COMPRESSOR
+
+ for( int i=0; i<alpha? 16: 8; i++ )
+ dest[i] = i%1? 0xff: 0x00;
+#endif
}
void nbvtf_compress_dxt( uint8_t *src, int w, int h, int alpha, int qual,
}
}
+
+
+#ifdef NBVTF_AS_SO
+__attribute__((visibility("default")))
+#endif
+int nbvtf_write_dds_dxt1( uint8_t *reference, int w, int h, int qual, const char *dest )
+{
+ if( !nbvtf_power2x(w,h) )
+ {
+ NBVTF_ERR( "nbvtf_write:err image dimentions were not power of two (%d %d)\n", w, h );
+ return 0;
+ }
+
+ struct DDS_HEADER header = {0};
+ header.dwSize = DDS_HEADER_SIZE;
+ header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+ header.dwHeight = h;
+ header.dwWidth = w;
+ header.dwPitchOrLinearSize = nbvtf__max(1, ((w + 3) / 4)) * BLOCK_SIZE_DXT1;
+ header.ddspf.dwSize = DDS_HEADER_PFSIZE;
+ header.ddspf.dwFlags |= DDPF_FOURCC;
+ header.ddspf.dwFourCC = ((uint32_t)'D'<<0) |
+ ((uint32_t)'X'<<8) |
+ ((uint32_t)'T'<<16) |
+ ((uint32_t)'1'<<24);
+
+ header.dwFlags |= DDSD_LINEARSIZE;
+ header.dwMipMapCount = 0;
+ header.dwCaps = DDSCAPS_TEXTURE;
+
+ // Magic number
+ uint32_t magic = DDS_MAGICNUM;
+
+ FILE *file = fopen( dest, "wb" );
+ fwrite( &magic, sizeof(uint32_t), 1, file );
+ fwrite( &header, DDS_HEADER_SIZE, 1, file );
+
+ uint32_t size_highres = nbvtf_sizeimg( w, h, k_EImageFormat_DXT1 );
+ uint8_t *working_buffer = malloc( size_highres );
+
+ nbvtf_compress_dxt( reference, w, h, 0, qual, working_buffer );
+ fwrite( working_buffer, size_highres, 1, file );
+
+ free( working_buffer );
+ fclose( file );
+ return 1;
+}
+
#ifdef NBVTF_AS_SO
__attribute__((visibility("default")))
#endif
return 0;
}
- // Image size needs retargeting
+ // Image size needs to be made smaller
if( (w && h) && ( x > w || y > h ) )
+ {
nbvtf_downscale( data, x, y, w, h, data );
+ x = w;
+ y = h;
+ }
- int status = nbvtf_write( data, w, h, mipmap, format, qual,
- usr_flags, dest );
+ int status = nbvtf_write( data, x,y, mipmap, format, qual, usr_flags, dest );
stbi_image_free( data );