2013-02-21 21:07:31 -08:00
/*
2016-01-01 00:11:04 -08:00
* Copyright 2011 - 2016 Branimir Karadzic . All rights reserved .
* License : https : //github.com/bkaradzic/bgfx#license-bsd-2-clause
2013-02-21 21:07:31 -08:00
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
// Just hacking DDS loading code in here.
# include "bgfx_p.h"
2013-09-02 16:22:53 -07:00
# include "image.h"
2015-12-14 17:35:24 -08:00
# include <libsquish/squish.h>
2015-12-15 22:13:01 -08:00
# include <etc1/etc1.h>
2016-01-28 21:09:03 -08:00
# include <etc2/ProcessRGB.hpp>
2015-12-20 20:40:35 -08:00
# include <nvtt/nvtt.h>
2015-12-22 18:05:06 -08:00
# include <pvrtc/PvrTcEncoder.h>
2015-12-22 20:31:46 -08:00
# include <tinyexr/tinyexr.h>
2016-01-30 16:15:25 -08:00
# include <edtaa3/edtaa3func.h>
2013-02-21 21:07:31 -08:00
2015-12-23 22:17:51 -08:00
# define STB_IMAGE_IMPLEMENTATION
# include <stb/stb_image.c>
2013-02-21 21:07:31 -08:00
#if 0
# define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__)
# endif // DEBUG
# include <bx/bx.h>
2015-11-19 20:10:51 -08:00
# include <bx/allocator.h>
2013-02-21 21:07:31 -08:00
# include <bx/commandline.h>
# include <bx/uint32_t.h>
namespace bgfx
{
const Memory * alloc ( uint32_t _size )
{
Memory * mem = ( Memory * ) : : realloc ( NULL , sizeof ( Memory ) + _size ) ;
mem - > size = _size ;
mem - > data = ( uint8_t * ) mem + sizeof ( Memory ) ;
return mem ;
}
2015-12-23 22:17:51 -08:00
const Memory * makeRef ( const void * _data , uint32_t _size , ReleaseFn _releaseFn , void * _userData )
{
BX_UNUSED ( _releaseFn , _userData ) ;
Memory * mem = ( Memory * ) : : realloc ( NULL , sizeof ( Memory ) ) ;
mem - > size = _size ;
mem - > data = ( uint8_t * ) _data ;
return mem ;
}
2015-11-15 20:40:23 -08:00
void release ( const Memory * _mem )
2013-02-21 21:07:31 -08:00
{
2015-11-15 20:40:23 -08:00
Memory * mem = const_cast < Memory * > ( _mem ) ;
: : free ( mem ) ;
}
2013-02-21 21:07:31 -08:00
2016-01-12 22:32:22 -08:00
bool imageEncodeFromRgba8 ( void * _dst , const void * _src , uint32_t _width , uint32_t _height , uint8_t _format )
2015-12-22 15:40:55 -08:00
{
TextureFormat : : Enum format = TextureFormat : : Enum ( _format ) ;
switch ( format )
{
case TextureFormat : : BC1 :
case TextureFormat : : BC2 :
case TextureFormat : : BC3 :
case TextureFormat : : BC4 :
case TextureFormat : : BC5 :
2016-01-04 21:48:01 -08:00
squish : : CompressImage ( ( const uint8_t * ) _src , _width , _height , _dst
2015-12-23 22:17:51 -08:00
, format = = TextureFormat : : BC2 ? squish : : kDxt3
2015-12-22 15:40:55 -08:00
: format = = TextureFormat : : BC3 ? squish : : kDxt5
: format = = TextureFormat : : BC4 ? squish : : kBc4
2015-12-23 22:17:51 -08:00
: format = = TextureFormat : : BC5 ? squish : : kBc5
: squish : : kDxt1
2015-12-22 15:40:55 -08:00
) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 15:40:55 -08:00
case TextureFormat : : BC6H :
2016-01-04 21:48:01 -08:00
nvtt : : compressBC6H ( ( const uint8_t * ) _src , _width , _height , 4 , _dst ) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 15:40:55 -08:00
case TextureFormat : : BC7 :
2016-01-04 21:48:01 -08:00
nvtt : : compressBC7 ( ( const uint8_t * ) _src , _width , _height , 4 , _dst ) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 15:40:55 -08:00
case TextureFormat : : ETC1 :
2016-01-04 21:48:01 -08:00
etc1_encode_image ( ( const uint8_t * ) _src , _width , _height , 4 , _width * 4 , ( uint8_t * ) _dst ) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 18:05:06 -08:00
2016-01-28 21:09:03 -08:00
case TextureFormat : : ETC2 :
{
2016-02-01 17:44:56 -08:00
const uint32_t blockWidth = ( _width + 3 ) / 4 ;
const uint32_t blockHeight = ( _height + 3 ) / 4 ;
const uint32_t pitch = _width * 4 ;
2016-01-28 21:09:03 -08:00
const uint8_t * src = ( const uint8_t * ) _src ;
uint64_t * dst = ( uint64_t * ) _dst ;
2016-02-01 17:44:56 -08:00
for ( uint32_t yy = 0 ; yy < blockHeight ; + + yy )
2016-01-28 21:09:03 -08:00
{
2016-02-01 17:44:56 -08:00
for ( uint32_t xx = 0 ; xx < blockWidth ; + + xx )
2016-01-28 21:09:03 -08:00
{
2016-02-01 17:44:56 -08:00
uint8_t block [ 4 * 4 * 4 ] ;
const uint8_t * ptr = & src [ ( yy * pitch + xx ) * 4 ] ;
memcpy ( & block [ 0 ] , ptr + pitch * 0 , 16 ) ;
memcpy ( & block [ 16 ] , ptr + pitch * 1 , 16 ) ;
memcpy ( & block [ 32 ] , ptr + pitch * 2 , 16 ) ;
memcpy ( & block [ 48 ] , ptr + pitch * 3 , 16 ) ;
for ( uint32_t ii = 0 ; ii < 16 ; + + ii )
{ // BGRx
bx : : xchg ( block [ ii * 4 + 0 ] , block [ ii * 4 + 2 ] ) ;
}
* dst + + = ProcessRGB_ETC2 ( block ) ;
2016-01-28 21:09:03 -08:00
}
}
}
return true ;
2015-12-22 15:40:55 -08:00
case TextureFormat : : PTC14 :
2015-12-22 18:05:06 -08:00
{
using namespace Javelin ;
RgbBitmap bmp ;
bmp . width = _width ;
bmp . height = _height ;
2016-01-04 21:48:01 -08:00
bmp . data = ( uint8_t * ) const_cast < void * > ( _src ) ;
2015-12-22 18:05:06 -08:00
PvrTcEncoder : : EncodeRgb4Bpp ( _dst , bmp ) ;
bmp . data = NULL ;
}
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 18:05:06 -08:00
2015-12-22 15:40:55 -08:00
case TextureFormat : : PTC14A :
2015-12-22 18:05:06 -08:00
{
using namespace Javelin ;
RgbaBitmap bmp ;
bmp . width = _width ;
bmp . height = _height ;
2016-01-04 21:48:01 -08:00
bmp . data = ( uint8_t * ) const_cast < void * > ( _src ) ;
2015-12-22 18:05:06 -08:00
PvrTcEncoder : : EncodeRgba4Bpp ( _dst , bmp ) ;
bmp . data = NULL ;
}
2016-01-12 22:32:22 -08:00
return true ;
2015-12-22 15:40:55 -08:00
2015-12-31 20:05:00 -08:00
case TextureFormat : : BGRA8 :
imageSwizzleBgra8 ( _width , _height , _width * 4 , _src , _dst ) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-31 20:05:00 -08:00
2015-12-23 22:17:51 -08:00
case TextureFormat : : RGBA8 :
memcpy ( _dst , _src , _width * _height * 4 ) ;
2016-01-12 22:32:22 -08:00
return true ;
2015-12-23 22:17:51 -08:00
2015-12-22 15:40:55 -08:00
default :
2016-01-12 22:32:22 -08:00
return imageConvert ( _dst , format , _src , TextureFormat : : RGBA8 , _width , _height ) ;
2015-12-22 15:40:55 -08:00
}
2016-01-12 22:32:22 -08:00
return false ;
2015-12-22 15:40:55 -08:00
}
2016-01-12 22:32:22 -08:00
bool imageEncodeFromRgba32f ( bx : : AllocatorI * _allocator , void * _dst , const void * _src , uint32_t _width , uint32_t _height , uint8_t _format )
2016-01-04 21:48:01 -08:00
{
TextureFormat : : Enum format = TextureFormat : : Enum ( _format ) ;
2016-01-05 18:32:54 -08:00
2016-01-07 17:31:57 -08:00
const uint8_t * src = ( const uint8_t * ) _src ;
2016-01-05 18:32:54 -08:00
2016-01-04 21:48:01 -08:00
switch ( format )
{
case TextureFormat : : RGBA8 :
2016-01-05 18:32:54 -08:00
{
uint8_t * dst = ( uint8_t * ) _dst ;
for ( uint32_t yy = 0 ; yy < _height ; + + yy )
{
for ( uint32_t xx = 0 ; xx < _width ; + + xx )
{
2016-01-07 17:31:57 -08:00
const uint32_t offset = yy * _width + xx ;
const float * input = ( const float * ) & src [ offset * 16 ] ;
uint8_t * output = & dst [ offset * 4 ] ;
output [ 0 ] = uint8_t ( input [ 0 ] * 255.0f + 0.5f ) ;
output [ 1 ] = uint8_t ( input [ 1 ] * 255.0f + 0.5f ) ;
output [ 2 ] = uint8_t ( input [ 2 ] * 255.0f + 0.5f ) ;
output [ 3 ] = uint8_t ( input [ 3 ] * 255.0f + 0.5f ) ;
2016-01-05 18:32:54 -08:00
}
}
}
2016-01-12 22:32:22 -08:00
return true ;
2016-01-05 18:32:54 -08:00
case TextureFormat : : BC5 :
2016-01-07 17:31:57 -08:00
{
uint8_t * temp = ( uint8_t * ) BX_ALLOC ( _allocator , _width * _height * 4 ) ;
for ( uint32_t yy = 0 ; yy < _height ; + + yy )
{
for ( uint32_t xx = 0 ; xx < _width ; + + xx )
{
const uint32_t offset = yy * _width + xx ;
const float * input = ( const float * ) & src [ offset * 16 ] ;
uint8_t * output = & temp [ offset * 4 ] ;
output [ 0 ] = uint8_t ( input [ 0 ] * 255.0f + 0.5f ) ;
output [ 1 ] = uint8_t ( input [ 1 ] * 255.0f + 0.5f ) ;
output [ 2 ] = uint8_t ( input [ 2 ] * 255.0f + 0.5f ) ;
output [ 3 ] = uint8_t ( input [ 3 ] * 255.0f + 0.5f ) ;
}
}
imageEncodeFromRgba8 ( _dst , temp , _width , _height , _format ) ;
BX_FREE ( _allocator , temp ) ;
}
2016-01-12 22:32:22 -08:00
return true ;
2016-01-04 21:48:01 -08:00
default :
2016-01-12 22:32:22 -08:00
return imageConvert ( _dst , format , _src , TextureFormat : : RGBA32F , _width , _height ) ;
2016-01-04 21:48:01 -08:00
}
2016-01-12 22:32:22 -08:00
return false ;
2016-01-04 21:48:01 -08:00
}
2016-01-07 17:31:57 -08:00
void imageRgba32f11to01 ( void * _dst , uint32_t _width , uint32_t _height , uint32_t _pitch , const void * _src )
{
const uint8_t * src = ( const uint8_t * ) _src ;
uint8_t * dst = ( uint8_t * ) _dst ;
for ( uint32_t yy = 0 ; yy < _height ; + + yy )
{
for ( uint32_t xx = 0 ; xx < _width ; + + xx )
{
const uint32_t offset = yy * _pitch + xx * 16 ;
const float * input = ( const float * ) & src [ offset ] ;
float * output = ( float * ) & dst [ offset ] ;
output [ 0 ] = input [ 0 ] * 0.5f + 0.5f ;
output [ 1 ] = input [ 1 ] * 0.5f + 0.5f ;
output [ 2 ] = input [ 2 ] * 0.5f + 0.5f ;
output [ 3 ] = input [ 3 ] * 0.5f + 0.5f ;
}
}
}
2016-01-30 16:15:25 -08:00
static void edtaa3 ( bx : : AllocatorI * _allocator , double * _dst , uint32_t _width , uint32_t _height , double * _src )
{
const uint32_t numPixels = _width * _height ;
short * xdist = ( short * ) BX_ALLOC ( _allocator , numPixels * sizeof ( short ) ) ;
short * ydist = ( short * ) BX_ALLOC ( _allocator , numPixels * sizeof ( short ) ) ;
double * gx = ( double * ) BX_ALLOC ( _allocator , numPixels * sizeof ( double ) ) ;
double * gy = ( double * ) BX_ALLOC ( _allocator , numPixels * sizeof ( double ) ) ;
: : computegradient ( _src , _width , _height , gx , gy ) ;
: : edtaa3 ( _src , gx , gy , _width , _height , xdist , ydist , _dst ) ;
for ( uint32_t ii = 0 ; ii < numPixels ; + + ii )
{
if ( _dst [ ii ] < 0.0 )
{
_dst [ ii ] = 0.0 ;
}
}
BX_FREE ( _allocator , xdist ) ;
BX_FREE ( _allocator , ydist ) ;
BX_FREE ( _allocator , gx ) ;
BX_FREE ( _allocator , gy ) ;
}
inline double min ( double _a , double _b )
{
return _a > _b ? _b : _a ;
}
inline double max ( double _a , double _b )
{
return _a > _b ? _a : _b ;
}
inline double clamp ( double _val , double _min , double _max )
{
return max ( min ( _val , _max ) , _min ) ;
}
void imageMakeDist ( bx : : AllocatorI * _allocator , void * _dst , uint32_t _width , uint32_t _height , uint32_t _pitch , float _edge , const void * _src )
{
const uint32_t numPixels = _width * _height ;
double * imgIn = ( double * ) BX_ALLOC ( _allocator , numPixels * sizeof ( double ) ) ;
double * outside = ( double * ) BX_ALLOC ( _allocator , numPixels * sizeof ( double ) ) ;
double * inside = ( double * ) BX_ALLOC ( _allocator , numPixels * sizeof ( double ) ) ;
for ( uint32_t yy = 0 ; yy < _height ; + + yy )
{
const uint8_t * src = ( const uint8_t * ) _src + yy * _pitch ;
double * dst = & imgIn [ yy * _width ] ;
for ( uint32_t xx = 0 ; xx < _width ; + + xx )
{
dst [ xx ] = double ( src [ xx ] ) / 255.0 ;
}
}
edtaa3 ( _allocator , outside , _width , _height , imgIn ) ;
for ( uint32_t ii = 0 ; ii < numPixels ; + + ii )
{
imgIn [ ii ] = 1.0 - imgIn [ ii ] ;
}
edtaa3 ( _allocator , inside , _width , _height , imgIn ) ;
BX_FREE ( _allocator , imgIn ) ;
uint8_t * dst = ( uint8_t * ) _dst ;
double edgeOffset = _edge * 0.5 ;
double invEdge = 1.0 / _edge ;
for ( uint32_t ii = 0 ; ii < numPixels ; + + ii )
{
double dist = clamp ( ( ( outside [ ii ] - inside [ ii ] ) + edgeOffset ) * invEdge , 0.0 , 1.0 ) ;
dst [ ii ] = 255 - uint8_t ( dist * 255.0 ) ;
}
BX_FREE ( _allocator , inside ) ;
BX_FREE ( _allocator , outside ) ;
}
2015-11-15 20:40:23 -08:00
} // namespace bgfx
void help ( const char * _error = NULL )
{
if ( NULL ! = _error )
{
fprintf ( stderr , " Error: \n %s \n \n " , _error ) ;
2013-02-21 21:07:31 -08:00
}
2015-11-15 20:40:23 -08:00
fprintf ( stderr
, " texturec, bgfx texture compiler tool \n "
2016-01-01 00:11:04 -08:00
" Copyright 2011-2016 Branimir Karadzic. All rights reserved. \n "
" License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause \n \n "
2015-11-15 20:40:23 -08:00
) ;
2015-12-27 20:04:17 -08:00
fprintf ( stderr
, " Usage: texturec -f <in> -o <out> -t <format> \n "
" \n "
" Supported input file types: \n "
" *.png Portable Network Graphics \n "
" *.tga Targa \n "
" *.dds Direct Draw Surface \n "
" *.ktx Khronos Texture \n "
" *.pvr PowerVR \n "
" \n "
" Options: \n "
" -f <file path> Input file path. \n "
" -o <file path> Output file path (file will be written in KTX format). \n "
" -t <format> Output format type (BC1/2/3/4/5, ETC1, PVR14, etc.). \n "
" -m, --mips Generate mip-maps. \n "
2016-01-04 21:48:01 -08:00
" -n, --normalmap Input texture is normal map. \n "
2016-01-30 16:15:25 -08:00
" --sdf <edge> Compute SDF texture. \n "
2015-12-27 20:04:17 -08:00
" \n "
" For additional information, see https://github.com/bkaradzic/bgfx \n "
) ;
2013-02-21 21:07:31 -08:00
}
int main ( int _argc , const char * _argv [ ] )
{
bx : : CommandLine cmdLine ( _argc , _argv ) ;
2015-11-15 20:40:23 -08:00
if ( cmdLine . hasArg ( ' h ' , " help " ) )
{
help ( ) ;
return EXIT_FAILURE ;
}
2013-09-02 16:22:53 -07:00
2015-12-27 20:04:17 -08:00
const char * inputFileName = cmdLine . findOption ( ' f ' ) ;
2013-09-02 16:22:53 -07:00
if ( NULL = = inputFileName )
{
2015-11-15 20:40:23 -08:00
help ( " Input file must be specified. " ) ;
return EXIT_FAILURE ;
2013-09-02 16:22:53 -07:00
}
2015-11-19 20:10:51 -08:00
const char * outputFileName = cmdLine . findOption ( ' o ' ) ;
if ( NULL = = outputFileName )
{
help ( " Output file must be specified. " ) ;
return EXIT_FAILURE ;
}
2016-01-30 16:15:25 -08:00
bool sdf = false ;
double edge = 16.0 ;
const char * edgeOpt = cmdLine . findOption ( " sdf " ) ;
if ( NULL ! = edgeOpt )
{
sdf = true ;
edge = atof ( edgeOpt ) ;
}
BX_UNUSED ( sdf , edge ) ;
2013-09-02 16:22:53 -07:00
bx : : CrtFileReader reader ;
2016-01-31 16:00:02 -08:00
if ( ! bx : : open ( & reader , inputFileName ) )
2015-11-15 20:40:23 -08:00
{
help ( " Failed to open input file. " ) ;
return EXIT_FAILURE ;
}
2015-12-18 18:15:30 -08:00
const char * type = cmdLine . findOption ( ' t ' ) ;
2015-12-27 20:04:17 -08:00
bgfx : : TextureFormat : : Enum format = bgfx : : TextureFormat : : BGRA8 ;
2015-12-18 18:15:30 -08:00
if ( NULL ! = type )
{
2015-12-27 20:04:17 -08:00
format = bgfx : : getFormat ( type ) ;
if ( ! isValid ( format ) )
2015-12-23 22:17:51 -08:00
{
help ( " Invalid format specified. " ) ;
return EXIT_FAILURE ;
}
2015-12-18 18:15:30 -08:00
}
2016-01-04 21:48:01 -08:00
const bool mips = cmdLine . hasArg ( ' m ' , " mips " ) ;
const bool normalMap = cmdLine . hasArg ( ' n ' , " normalmap " ) ;
2013-09-02 16:22:53 -07:00
uint32_t size = ( uint32_t ) bx : : getSize ( & reader ) ;
2015-12-27 20:04:17 -08:00
const bgfx : : Memory * mem = bgfx : : alloc ( size ) ;
2013-09-02 16:22:53 -07:00
bx : : read ( & reader , mem - > data , mem - > size ) ;
bx : : close ( & reader ) ;
2013-02-21 21:07:31 -08:00
2015-11-19 20:10:51 -08:00
{
2015-12-27 20:04:17 -08:00
using namespace bgfx ;
2015-12-22 15:40:55 -08:00
2015-12-27 20:04:17 -08:00
uint8_t * decodedImage = NULL ;
ImageContainer imageContainer ;
2015-12-23 22:17:51 -08:00
2015-12-27 20:04:17 -08:00
bool loaded = imageParse ( imageContainer , mem - > data , mem - > size ) ;
if ( ! loaded )
2015-12-23 22:17:51 -08:00
{
2015-12-27 20:04:17 -08:00
int width = 0 ;
int height = 0 ;
int comp = 0 ;
2015-11-19 20:10:51 -08:00
2015-12-27 20:04:17 -08:00
decodedImage = stbi_load_from_memory ( ( uint8_t * ) mem - > data , mem - > size , & width , & height , & comp , 4 ) ;
loaded = NULL ! = decodedImage ;
if ( loaded )
{
release ( mem ) ;
mem = makeRef ( decodedImage , width * height * 4 ) ;
imageContainer . m_data = mem - > data ;
imageContainer . m_size = mem - > size ;
imageContainer . m_offset = 0 ;
imageContainer . m_width = width ;
imageContainer . m_height = height ;
imageContainer . m_depth = 1 ;
imageContainer . m_format = bgfx : : TextureFormat : : RGBA8 ;
imageContainer . m_numMips = 1 ;
imageContainer . m_hasAlpha = true ;
imageContainer . m_cubeMap = false ;
imageContainer . m_ktx = false ;
imageContainer . m_ktxLE = false ;
imageContainer . m_srgb = false ;
}
}
2013-02-21 21:07:31 -08:00
2015-12-27 20:04:17 -08:00
if ( loaded )
2013-02-21 21:07:31 -08:00
{
2015-12-27 20:04:17 -08:00
bx : : CrtAllocator allocator ;
const Memory * output = NULL ;
2013-02-21 21:07:31 -08:00
2015-12-27 20:04:17 -08:00
ImageMip mip ;
if ( imageGetRawData ( imageContainer , 0 , 0 , mem - > data , mem - > size , mip ) )
{
2015-12-31 20:05:00 -08:00
uint8_t numMips = mips
? imageGetNumMips ( format , mip . m_width , mip . m_height )
: 1
;
2015-12-18 18:15:30 -08:00
2016-01-04 21:48:01 -08:00
void * temp = NULL ;
2015-12-27 20:04:17 -08:00
2016-01-04 21:48:01 -08:00
if ( normalMap )
{
uint32_t size = imageGetSize ( TextureFormat : : RGBA32F , mip . m_width , mip . m_height ) ;
temp = BX_ALLOC ( & allocator , size ) ;
float * rgba = ( float * ) temp ;
2016-01-07 17:31:57 -08:00
float * rgbaDst = ( float * ) BX_ALLOC ( & allocator , size ) ;
2016-01-04 21:48:01 -08:00
imageDecodeToRgba32f ( & allocator
, rgba
, mip . m_data
, mip . m_width
, mip . m_height
, mip . m_width * mip . m_bpp / 8
2016-01-05 18:32:54 -08:00
, mip . m_format
2016-01-04 21:48:01 -08:00
) ;
2016-01-07 17:31:57 -08:00
if ( TextureFormat : : BC5 ! = mip . m_format )
2016-01-06 18:15:05 -08:00
{
2016-01-07 17:31:57 -08:00
for ( uint32_t yy = 0 ; yy < mip . m_height ; + + yy )
2016-01-06 18:15:05 -08:00
{
2016-01-07 17:31:57 -08:00
for ( uint32_t xx = 0 ; xx < mip . m_width ; + + xx )
{
const uint32_t offset = ( yy * mip . m_width + xx ) * 4 ;
float * inout = & rgba [ offset ] ;
inout [ 0 ] = inout [ 0 ] * 2.0f / 255.0f - 1.0f ;
inout [ 1 ] = inout [ 1 ] * 2.0f / 255.0f - 1.0f ;
inout [ 2 ] = inout [ 2 ] * 2.0f / 255.0f - 1.0f ;
inout [ 3 ] = inout [ 3 ] * 2.0f / 255.0f - 1.0f ;
}
2016-01-06 18:15:05 -08:00
}
}
2016-01-07 17:31:57 -08:00
output = imageAlloc ( imageContainer , format , mip . m_width , mip . m_height , 0 , false , mips ) ;
2016-01-04 21:48:01 -08:00
2016-01-07 17:31:57 -08:00
imageRgba32f11to01 ( rgbaDst , mip . m_width , mip . m_height , mip . m_width * 16 , rgba ) ;
imageEncodeFromRgba32f ( & allocator , output - > data , rgbaDst , mip . m_width , mip . m_height , format ) ;
2016-01-04 21:48:01 -08:00
for ( uint8_t lod = 1 ; lod < numMips ; + + lod )
{
2016-01-06 18:15:05 -08:00
imageRgba32fDownsample2x2NormalMap ( mip . m_width , mip . m_height , mip . m_width * 16 , rgba , rgba ) ;
2016-01-07 17:31:57 -08:00
imageRgba32f11to01 ( rgbaDst , mip . m_width , mip . m_height , mip . m_width * 16 , rgba ) ;
2016-01-06 18:15:05 -08:00
ImageMip dstMip ;
imageGetRawData ( imageContainer , 0 , lod , output - > data , output - > size , dstMip ) ;
uint8_t * data = const_cast < uint8_t * > ( dstMip . m_data ) ;
2016-01-07 17:31:57 -08:00
imageEncodeFromRgba32f ( & allocator , data , rgbaDst , dstMip . m_width , dstMip . m_height , format ) ;
2016-01-04 21:48:01 -08:00
}
2016-01-07 17:31:57 -08:00
BX_FREE ( & allocator , rgbaDst ) ;
2016-01-04 21:48:01 -08:00
}
else
2015-12-31 20:05:00 -08:00
{
2016-01-04 21:48:01 -08:00
uint32_t size = imageGetSize ( TextureFormat : : RGBA8 , mip . m_width , mip . m_height ) ;
temp = BX_ALLOC ( & allocator , size ) ;
uint8_t * rgba = ( uint8_t * ) temp ;
2016-01-06 18:15:05 -08:00
imageDecodeToRgba8 ( rgba
, mip . m_data
, mip . m_width
, mip . m_height
, mip . m_width * mip . m_bpp / 8
, mip . m_format
) ;
2016-01-07 17:31:57 -08:00
output = imageAlloc ( imageContainer , format , mip . m_width , mip . m_height , 0 , false , mips ) ;
2016-01-04 21:48:01 -08:00
imageEncodeFromRgba8 ( output - > data , rgba , mip . m_width , mip . m_height , format ) ;
for ( uint8_t lod = 1 ; lod < numMips ; + + lod )
{
2016-01-06 18:15:05 -08:00
imageRgba8Downsample2x2 ( mip . m_width , mip . m_height , mip . m_width * 4 , rgba , rgba ) ;
ImageMip dstMip ;
imageGetRawData ( imageContainer , 0 , lod , output - > data , output - > size , dstMip ) ;
uint8_t * data = const_cast < uint8_t * > ( dstMip . m_data ) ;
imageEncodeFromRgba8 ( data , rgba , dstMip . m_width , dstMip . m_height , format ) ;
2016-01-04 21:48:01 -08:00
}
2015-12-31 20:05:00 -08:00
}
2016-01-04 21:48:01 -08:00
BX_FREE ( & allocator , temp ) ;
2015-12-27 20:04:17 -08:00
}
if ( NULL ! = output )
2013-02-21 21:07:31 -08:00
{
2015-12-27 20:04:17 -08:00
bx : : CrtFileWriter writer ;
2016-02-01 17:44:56 -08:00
if ( bx : : open ( & writer , outputFileName ) )
2013-02-21 21:07:31 -08:00
{
2015-12-27 20:04:17 -08:00
if ( NULL ! = bx : : stristr ( outputFileName , " .ktx " ) )
{
imageWriteKtx ( & writer , imageContainer , output - > data , output - > size ) ;
}
bx : : close ( & writer ) ;
2013-02-21 21:07:31 -08:00
}
2016-01-07 17:31:57 -08:00
else
{
help ( " Failed to open output file. " ) ;
return EXIT_FAILURE ;
}
2015-12-18 18:15:30 -08:00
2016-01-07 17:31:57 -08:00
imageFree ( output ) ;
2013-02-21 21:07:31 -08:00
}
}
2015-12-27 20:04:17 -08:00
release ( mem ) ;
}
2015-11-15 20:40:23 -08:00
2013-02-21 21:07:31 -08:00
return EXIT_SUCCESS ;
}