Skip to content

Instantly share code, notes, and snippets.

@mikearmstrong001
Created October 3, 2014 08:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikearmstrong001/3355da4794527fe91cae to your computer and use it in GitHub Desktop.
Save mikearmstrong001/3355da4794527fe91cae to your computer and use it in GitHub Desktop.
Random train snippets
// brickportals.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <malloc.h>
#include <vector>
#include <map>
#include <set>
class sparebitset
{
std::map<unsigned int, unsigned char> bits;
public:
void set( unsigned int index )
{
bits[index/8] |= (index%8);
}
bool get( unsigned int index )
{
return (bits[index/8] & (index%8)) ? true : false;
}
};
struct brick
{
int version;
int x, y, z;
unsigned char solid[256][256][256/8];
};
void *readfile( const char *filename, int *len = NULL )
{
if ( filename == NULL )
return NULL;
FILE *f = fopen( filename, "rb" );
if ( f )
{
fseek( f, 0, SEEK_END );
int l = ftell( f );
fseek( f, 0, SEEK_SET );
char *mem = (char*)malloc( l + 1 );
fread( mem, l, 1, f );
mem[l] = 0;
fclose( f );
if ( len )
{
*len = l;
}
return mem;
}
else
{
return NULL;
}
}
struct node
{
short box[2][3];
node *kids[2];
int id;
short group;
node()
{
kids[0] = kids[1] = NULL;
}
~node()
{
delete kids[0];
delete kids[1];
}
};
inline int min( int a, int b )
{
return (a<b) ? a : b;
}
inline int max( int a, int b )
{
return (a>b) ? a : b;
}
node* genportals( brick *b, int mnx, int mny, int mnz, int mxx, int mxy, int mxz, int depth, int axis )
{
if ( b == NULL )
{
node *n = new node;
n->box[0][0] = mnx;
n->box[0][1] = mny;
n->box[0][2] = mnz;
n->box[1][0] = mxx;
n->box[1][1] = mxy;
n->box[1][2] = mxz;
n->kids[0] = NULL;
n->kids[1] = NULL;
return n;
}
if ( depth )
{
int mdy = (mny+mxy) / 2;
int mdz = (mnz+mxz) / 2;
node *g0;
node *g1;
if ( axis == 0 )
{
int mdx = (mnx+mxx) / 2;
g0 = genportals( b, mnx, mny, mnz, mdx, mxy, mxz, depth-1, (axis+1)%3 );
g1 = genportals( b, mdx, mny, mnz, mxx, mxy, mxz, depth-1, (axis+1)%3 );
}
else
if ( axis == 1 )
{
int mdy = (mny+mxy) / 2;
g0 = genportals( b, mnx, mny, mnz, mxx, mdy, mxz, depth-1, (axis+1)%3 );
g1 = genportals( b, mnx, mdy, mnz, mxx, mxy, mxz, depth-1, (axis+1)%3 );
}
else
//if ( axis == 2 )
{
int mdz = (mnz+mxz) / 2;
g0 = genportals( b, mnx, mny, mnz, mxx, mxy, mdz, depth-1, (axis+1)%3 );
g1 = genportals( b, mnx, mny, mdz, mxx, mxy, mxz, depth-1, (axis+1)%3 );
}
// both empty combine
if ( g0 && g1 && g0->kids[0] == NULL && g1->kids[1] == NULL )
{
node *n = new node;
n->box[0][0] = mnx;
n->box[0][1] = mny;
n->box[0][2] = mnz;
n->box[1][0] = mxx;
n->box[1][1] = mxy;
n->box[1][2] = mxz;
n->kids[0] = NULL;
n->kids[1] = NULL;
delete g0;
delete g1;
return n;
}
else
if ( g0 == NULL && g1 == NULL )
{
return NULL;
}
else
{
node *n = new node;
n->box[0][0] = mnx;
n->box[0][1] = mny;
n->box[0][2] = mnz;
n->box[1][0] = mxx;
n->box[1][1] = mxy;
n->box[1][2] = mxz;
n->kids[0] = g0;
n->kids[1] = g1;
return n;
}
}
else
{
bool g = false;
for (int z=mnz; z<mxz; z++)
{
for (int y=mny; y<mxy; y++)
{
for (int x=mnx; x<mxx; x++)
{
if ( b->solid[z][y][x/8] & (1<<(x%8)) )
g = true;
}
}
}
if ( g )
{
return NULL;
}
else
{
node *n = new node;
n->box[0][0] = mnx;
n->box[0][1] = mny;
n->box[0][2] = mnz;
n->box[1][0] = mxx;
n->box[1][1] = mxy;
n->box[1][2] = mxz;
n->kids[0] = NULL;
n->kids[1] = NULL;
return n;
}
}
}
void outputleafboxes( FILE *f, node *n )
{
if ( n == NULL )
return;
if ( n->kids[0]==NULL && n->kids[1]==NULL )
{
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[0][1], n->box[0][2] );
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[0][1], n->box[0][2] );
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[1][1], n->box[0][2] );
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[1][1], n->box[0][2] );
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[0][1], n->box[1][2] );
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[0][1], n->box[1][2] );
fprintf( f, "v %d %d %d\n", n->box[0][0], n->box[1][1], n->box[1][2] );
fprintf( f, "v %d %d %d\n", n->box[1][0], n->box[1][1], n->box[1][2] );
fprintf( f, "f -8 -7 -5 -6\n" );
fprintf( f, "f -6 -5 -1 -2\n" );
fprintf( f, "f -8 -6 -2 -4\n" );
fprintf( f, "f -7 -8 -4 -3\n" );
fprintf( f, "f -5 -7 -3 -1\n" );
fprintf( f, "f -1 -2 -4 -3\n" );
}
else
{
outputleafboxes( f, n->kids[0] );
outputleafboxes( f, n->kids[1] );
}
}
void addleaves( std::vector<node*> &leaves, node *n )
{
if ( n == NULL )
return;
if ( n->kids[0]==NULL && n->kids[1]==NULL )
{
leaves.push_back( n );
}
else
{
addleaves( leaves, n->kids[0] );
addleaves( leaves, n->kids[1] );
}
}
bool touching( node *a, node *b )
{
for (int axis=0; axis<3; axis++)
{
if ( a->box[1][axis] < b->box[0][axis] )
return false;
if ( a->box[0][axis] > b->box[1][axis] )
return false;
}
return true;
}
struct quad
{
short v[4][3];
};
quad generatequad( node *n, int face )
{
const static int faceids[6][4] =
{
{ 0, 2, 6, 4 }, // ---, -+-, -++, --+ -x
{ 1, 0, 4, 5 }, // +--, ---, --+, +-+ -y
{ 0, 1, 3, 2 }, // ---, +--, ++-, -+- -z
{ 3, 1, 5, 7 }, // ++-, +--, +-+, +++ +x
{ 2, 3, 7, 6 }, // -+-, ++-, +++, -++ +y
{ 7, 6, 4, 5 }, // +++, -++, --+, +-+ +z
};
quad q;
for (int i=0; i<4; i++)
{
q.v[i][0] = faceids[face][i] & 1 ? n->box[1][0] : n->box[0][0];
q.v[i][1] = faceids[face][i] & 2 ? n->box[1][1] : n->box[0][1];
q.v[i][2] = faceids[face][i] & 4 ? n->box[1][2] : n->box[0][2];
}
return q;
}
quad clipquad( quad q, node *n )
{
quad empty;
memset( &empty, 0, sizeof(empty) );
int bb[2][4];
bb[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) );
bb[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) );
bb[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) );
bb[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) );
bb[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) );
bb[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) );
for (int axis=0; axis<3; axis++)
{
if ( bb[1][axis] < n->box[0][axis] )
return empty;
if ( bb[0][axis] > n->box[1][axis] )
return empty;
}
for (int i=0; i<4; i++)
{
q.v[i][0] = max( n->box[0][0], min( n->box[1][0], q.v[i][0] ) );
q.v[i][1] = max( n->box[0][1], min( n->box[1][1], q.v[i][1] ) );
q.v[i][2] = max( n->box[0][2], min( n->box[1][2], q.v[i][2] ) );
}
return q;
}
bool isvalidquad( quad const &q )
{
int mn[3] = { q.v[0][0], q.v[0][1], q.v[0][2] };
int mx[3] = { q.v[0][0], q.v[0][1], q.v[0][2] };
for (int i=0; i<4; i++)
{
mn[0] = min( mn[0], q.v[i][0] );
mn[1] = min( mn[1], q.v[i][1] );
mn[2] = min( mn[2], q.v[i][2] );
mx[0] = max( mx[0], q.v[i][0] );
mx[1] = max( mx[1], q.v[i][1] );
mx[2] = max( mx[2], q.v[i][2] );
}
int count = 0;
count += (mn[0] == mx[0]) ? 0 : 1;
count += (mn[1] == mx[1]) ? 0 : 1;
count += (mn[2] == mx[2]) ? 0 : 1;
return count == 2;
}
void outputquad( FILE *f, quad const &q )
{
fprintf( f, "v %d %d %d\n", q.v[0][0], q.v[0][1], q.v[0][2] );
fprintf( f, "v %d %d %d\n", q.v[1][0], q.v[1][1], q.v[1][2] );
fprintf( f, "v %d %d %d\n", q.v[2][0], q.v[2][1], q.v[2][2] );
fprintf( f, "v %d %d %d\n", q.v[3][0], q.v[3][1], q.v[3][2] );
fprintf( f, "f -1 -2 -3 -4\n" );
}
node *createbound( int mnx, int mny, int mnz, int mxx, int mxy, int mxz )
{
node *n = new node;
n->box[0][0] = mnx;
n->box[0][1] = mny;
n->box[0][2] = mnz;
n->box[1][0] = mxx;
n->box[1][1] = mxy;
n->box[1][2] = mxz;
n->kids[0] = NULL;
n->kids[1] = NULL;
return n;
}
node *findfreenode( std::vector< node* > const &leaves )
{
for (unsigned int i=0; i<leaves.size(); i++)
{
if ( leaves[i]->group == -1 )
return leaves[i];
}
return NULL;
}
#include <assert.h>
void floodfill( node *n, std::vector< node* > const &leaves, std::map<int,std::set<int>> &connected, int group )
{
assert( n->group == -1 );
n->group = group;
std::set<int>::const_iterator b = connected[n->id].cbegin();
while ( b != connected[n->id].cend() )
{
int c = *b++;
if ( leaves[c]->group == group )
{
continue;
}
floodfill( leaves[c], leaves, connected, group );
}
}
bool canmerge( node *a, node *b )
{
if ( a->group != b->group )
return false;
for (int axis=0; axis<3; axis++)
{
if ( a->box[1][axis] < b->box[0][axis] )
return false;
if ( a->box[0][axis] > b->box[1][axis] )
return false;
int ext0 = (axis+1)%3;
int ext1 = (axis+2)%3;
if ( a->box[0][ext0] == b->box[0][ext0] &&
a->box[0][ext1] == b->box[0][ext1] &&
a->box[1][ext0] == b->box[1][ext0] &&
a->box[1][ext1] == b->box[1][ext1] )
{
return true;
}
}
return false;
}
void merge( node *a, node *b )
{
a->box[0][0] = min( a->box[0][0], b->box[0][0] );
a->box[0][1] = min( a->box[0][1], b->box[0][1] );
a->box[0][2] = min( a->box[0][2], b->box[0][2] );
a->box[1][0] = max( a->box[1][0], b->box[1][0] );
a->box[1][1] = max( a->box[1][1], b->box[1][1] );
a->box[1][2] = max( a->box[1][2], b->box[1][2] );
b->group = -1;
}
struct cellbound
{
short bb[2][3];
int group;
};
struct portal
{
short v[2][3];
short group;
unsigned char other_group;
unsigned char other_cell;
};
struct cell
{
int grid[3];
std::vector< cellbound > bounds;
std::vector< portal > portals;
sparebitset vis;
};
struct plane
{
float n[3];
int loc[3];
};
void fwriteint( FILE *f, int v )
{
fwrite( &v, sizeof(v), 1, f );
}
void fwriteshort( FILE *f, short v )
{
fwrite( &v, sizeof(v), 1, f );
}
int freadint( FILE *f )
{
int v;
fread( &v, sizeof(v), 1, f );
return v;
}
short freadshort( FILE *f )
{
short v;
fread( &v, sizeof(v), 1, f );
return v;
}
void writecell( const char *filename, cell &c )
{
FILE *f = fopen( filename, "wb" );
if ( f )
{
fwriteint( f, 0x100 );
fwriteint( f, c.grid[0] );
fwriteint( f, c.grid[1] );
fwriteint( f, c.grid[2] );
fwriteint( f, c.bounds.size() );
fwriteint( f, c.portals.size() );
for (unsigned int i=0; i<c.bounds.size(); i++)
{
fwriteshort( f, c.bounds[i].bb[0][0] );
fwriteshort( f, c.bounds[i].bb[0][1] );
fwriteshort( f, c.bounds[i].bb[0][2] );
fwriteshort( f, c.bounds[i].bb[1][0] );
fwriteshort( f, c.bounds[i].bb[1][1] );
fwriteshort( f, c.bounds[i].bb[1][2] );
fwriteint( f, c.bounds[i].group );
}
for (unsigned int i=0; i<c.portals.size(); i++)
{
fwriteshort( f, c.portals[i].v[0][0] );
fwriteshort( f, c.portals[i].v[0][1] );
fwriteshort( f, c.portals[i].v[0][2] );
fwriteshort( f, c.portals[i].v[1][0] );
fwriteshort( f, c.portals[i].v[1][1] );
fwriteshort( f, c.portals[i].v[1][2] );
fwriteint( f, c.portals[i].group );
fwriteint( f, c.portals[i].other_cell );
fwriteint( f, c.portals[i].other_group );
}
fclose( f );
}
}
void writeobjofcell( const char *filename, cell *cs, int numcells )
{
FILE *f = fopen( filename, "wb" );
if ( f )
{
for (int n=0; n<numcells; n++)
{
cell &c = cs[n];
for (unsigned int i=0; i<c.portals.size(); i++)
{
portal &p = c.portals[i];
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[0][1], p.v[0][2] );
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[0][1], p.v[0][2] );
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[1][1], p.v[0][2] );
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[1][1], p.v[0][2] );
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[0][1], p.v[1][2] );
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[0][1], p.v[1][2] );
fprintf( f, "v %d %d %d\n", p.v[0][0],p.v[1][1], p.v[1][2] );
fprintf( f, "v %d %d %d\n", p.v[1][0],p.v[1][1], p.v[1][2] );
fprintf( f, "f -8 -7 -5 -6\n" );
fprintf( f, "f -6 -5 -1 -2\n" );
fprintf( f, "f -8 -6 -2 -4\n" );
fprintf( f, "f -7 -8 -4 -3\n" );
fprintf( f, "f -5 -7 -3 -1\n" );
fprintf( f, "f -1 -2 -4 -3\n" );
}
}
fclose( f );
}
}
void offsetcell( cell &c, int ox, int oy, int oz )
{
for (unsigned int i=0; i<c.bounds.size(); i++)
{
c.bounds[i].bb[0][0] += ox;
c.bounds[i].bb[0][1] += oy;
c.bounds[i].bb[0][2] += oz;
c.bounds[i].bb[1][0] += ox;
c.bounds[i].bb[1][1] += oy;
c.bounds[i].bb[1][2] += oz;
}
for (unsigned int i=0; i<c.portals.size(); i++)
{
c.portals[i].v[0][0] += ox;
c.portals[i].v[0][1] += oy;
c.portals[i].v[0][2] += oz;
c.portals[i].v[1][0] += ox;
c.portals[i].v[1][1] += oy;
c.portals[i].v[1][2] += oz;
}
}
bool readcell( cell &c, const char *filename, int ox, int oy, int oz )
{
FILE *f = fopen( filename, "rb" );
if ( f )
{
int version = freadint( f );
assert( version == 0x100 );
c.grid[0] = freadint( f );
c.grid[1] = freadint( f );
c.grid[2] = freadint( f );
c.bounds.resize( freadint( f ) );
c.portals.resize( freadint( f ) );
for (unsigned int i=0; i<c.bounds.size(); i++)
{
c.bounds[i].bb[0][0] = freadshort( f ) + ox;
c.bounds[i].bb[0][1] = freadshort( f ) + oy;
c.bounds[i].bb[0][2] = freadshort( f ) + oz;
c.bounds[i].bb[1][0] = freadshort( f ) + ox;
c.bounds[i].bb[1][1] = freadshort( f ) + oy;
c.bounds[i].bb[1][2] = freadshort( f ) + oz;
c.bounds[i].group = freadint( f );
}
for (unsigned int i=0; i<c.portals.size(); i++)
{
c.portals[i].v[0][0] = freadshort( f ) + ox;
c.portals[i].v[0][1] = freadshort( f ) + oy;
c.portals[i].v[0][2] = freadshort( f ) + oz;
c.portals[i].v[1][0] = freadshort( f ) + ox;
c.portals[i].v[1][1] = freadshort( f ) + oy;
c.portals[i].v[1][2] = freadshort( f ) + oz;
c.portals[i].group = freadint( f );
c.portals[i].other_cell = freadint( f );
c.portals[i].other_group = freadint( f );
}
fclose( f );
return true;
}
return false;
}
void makecell( cell &c, const char *cellfilename, const char *voxelfilename )
{
brick *b = (brick*)readfile( voxelfilename );
node *n = genportals( b, 0, 0, 0, 256, 256, 256, 10, 0 );
c.grid[0] = b ? b->x : 0;
c.grid[1] = b ? b->y : 0;
c.grid[2] = b ? b->z : 0;
free( b );
std::vector< node* > leaves;
addleaves( leaves, n );
{
std::map<int,std::set<int>> connected;
for (unsigned int i=0; i<leaves.size(); i++)
{
leaves[i]->id = i;
leaves[i]->group = -1;
for (unsigned int j=0; j<leaves.size(); j++)
{
if ( i == j )
continue;
if ( !touching( leaves[i], leaves[j] ) )
continue;
for (int face=0; face<6; face++)
{
quad q = clipquad( generatequad( leaves[i], face ), leaves[j] );
if ( isvalidquad( q ) )
{
connected[i].insert(j);
}
}
}
}
int group = 0;
do
{
node *n = findfreenode( leaves );
if ( n == NULL )
break;
floodfill( n, leaves, connected, group );
group++;
} while ( true );
}
{
bool done = false;
while ( !done )
{
done = true;
for (unsigned int i=0; i<leaves.size(); i++)
{
if ( leaves[i]->group == -1 )
continue;
for (unsigned int j=0; j<leaves.size(); j++)
{
if ( i == j )
continue;
if ( leaves[j]->group == -1 )
continue;
if ( canmerge( leaves[i], leaves[j] ) )
{
merge( leaves[i], leaves[j] );
done = false;
}
}
}
}
}
{
std::vector< node* >::iterator b = leaves.begin();
while ( b != leaves.end() )
{
if ( (*b)->group == -1 )
{
b = leaves.erase( b );
}
else
{
b++;
}
}
}
{
std::vector< node* > external;
external.push_back( createbound( 256, 0, 0, 512, 256, 256 ) );
external.push_back( createbound( 0, 256, 0, 256, 512, 256 ) );
external.push_back( createbound( 0, 0, 256, 256, 256, 512 ) );
external.push_back( createbound( -256, 0, 0, 0, 256, 256 ) );
external.push_back( createbound( 0, -256, 0, 256, 0, 256 ) );
external.push_back( createbound( 0, 0, -256, 256, 256, 0 ) );
for (unsigned int i=0; i<leaves.size(); i++)
{
cellbound cb;
cb.group = leaves[i]->group;
cb.bb[0][0] = leaves[i]->box[0][0];
cb.bb[0][1] = leaves[i]->box[0][1];
cb.bb[0][2] = leaves[i]->box[0][2];
cb.bb[1][0] = leaves[i]->box[1][0];
cb.bb[1][1] = leaves[i]->box[1][1];
cb.bb[1][2] = leaves[i]->box[1][2];
c.bounds.push_back( cb );
for (unsigned int j=0; j<external.size(); j++)
{
if ( !touching( leaves[i], external[j] ) )
continue;
for (int face=0; face<6; face++)
{
quad q = clipquad( generatequad( leaves[i], face ), external[j] );
if ( isvalidquad( q ) )
{
portal p;
p.group = leaves[i]->group;
p.other_cell = face;
p.other_group = 255;
p.v[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) );
p.v[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) );
p.v[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) );
p.v[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) );
p.v[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) );
p.v[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) );
c.portals.push_back( p );
}
}
}
}
}
if ( cellfilename )
{
writecell( cellfilename, c );
}
delete n;
}
bool touching( portal const *a, portal const *b )
{
for (int axis=0; axis<3; axis++)
{
if ( a->v[1][axis] < b->v[0][axis] )
return false;
if ( a->v[0][axis] > b->v[1][axis] )
return false;
}
return true;
}
quad generatequad( portal const *n, int face )
{
const static int faceids[6][4] =
{
{ 0, 2, 6, 4 }, // ---, -+-, -++, --+ -x
{ 1, 0, 4, 5 }, // +--, ---, --+, +-+ -y
{ 0, 1, 3, 2 }, // ---, +--, ++-, -+- -z
{ 3, 1, 5, 7 }, // ++-, +--, +-+, +++ +x
{ 2, 3, 7, 6 }, // -+-, ++-, +++, -++ +y
{ 7, 6, 4, 5 }, // +++, -++, --+, +-+ +z
};
quad q;
for (int i=0; i<4; i++)
{
q.v[i][0] = faceids[face][i] & 1 ? n->v[1][0] : n->v[0][0];
q.v[i][1] = faceids[face][i] & 2 ? n->v[1][1] : n->v[0][1];
q.v[i][2] = faceids[face][i] & 4 ? n->v[1][2] : n->v[0][2];
}
return q;
}
quad clipquad( quad q, portal const *n )
{
quad empty;
memset( &empty, 0, sizeof(empty) );
int bb[2][4];
bb[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) );
bb[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) );
bb[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) );
bb[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) );
bb[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) );
bb[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) );
for (int axis=0; axis<3; axis++)
{
if ( bb[1][axis] < n->v[0][axis] )
return empty;
if ( bb[0][axis] > n->v[1][axis] )
return empty;
}
for (int i=0; i<4; i++)
{
q.v[i][0] = max( n->v[0][0], min( n->v[1][0], q.v[i][0] ) );
q.v[i][1] = max( n->v[0][1], min( n->v[1][1], q.v[i][1] ) );
q.v[i][2] = max( n->v[0][2], min( n->v[1][2], q.v[i][2] ) );
}
return q;
}
void intersect( cell &c, cell const *neighbours, int numn )
{
std::vector< portal > src;
std::swap( c.portals, src );
for (unsigned int i=0; i<src.size(); i++)
{
portal srcp = src[i];
for (unsigned int ni=0; ni<numn; ni++)
{
cell const &n = neighbours[ni];
for (unsigned int j=0; j<n.portals.size(); j++)
{
if ( !touching( &srcp, &n.portals[j] ) )
continue;
{
quad q = clipquad( generatequad( &srcp, srcp.other_cell ), &n.portals[j] );
if ( isvalidquad( q ) )
{
portal p;
p.group = srcp.group;
p.other_cell = srcp.other_cell;
p.other_group = n.portals[j].group;
p.v[0][0] = min( q.v[0][0], min( q.v[1][0], min( q.v[2][0], q.v[3][0] ) ) );
p.v[0][1] = min( q.v[0][1], min( q.v[1][1], min( q.v[2][1], q.v[3][1] ) ) );
p.v[0][2] = min( q.v[0][2], min( q.v[1][2], min( q.v[2][2], q.v[3][2] ) ) );
p.v[1][0] = max( q.v[0][0], max( q.v[1][0], max( q.v[2][0], q.v[3][0] ) ) );
p.v[1][1] = max( q.v[0][1], max( q.v[1][1], max( q.v[2][1], q.v[3][1] ) ) );
p.v[1][2] = max( q.v[0][2], max( q.v[1][2], max( q.v[2][2], q.v[3][2] ) ) );
c.portals.push_back( p );
}
}
}
}
}
}
#include <string>
#include <vector>
#include <io.h>
#include <algorithm>
char fixseparator( char c )
{
return ( c == '/' ) ? '\\' : c;
}
void findFiles( std::vector< std::string > &files, const char *pattern )
{
std::string path = pattern;
std::transform( path.begin(), path.end(), path.begin(), fixseparator );
std::string::size_type pos = path.find_last_of( '\\' );
if ( pos != std::string::npos )
{
path = path.substr( 0, pos );
}
else
{
path = ".";
}
_finddata_t fi;
intptr_t fh = _findfirst( pattern, &fi );
if ( fh != -1 )
{
do
{
files.push_back( path + "\\" + fi.name );
}
while ( _findnext( fh, &fi ) == 0 );
_findclose( fh );
}
}
bool readhdr( float bb[2][3], const char *filename )
{
FILE *f = fopen( filename, "rb" );
if ( f )
{
bool failed = false;
failed |= (fscanf( f, "%f,%f,%f\n", &bb[0][0], &bb[0][1], &bb[0][2] ) != 3);
failed |= (fscanf( f, "%f,%f,%f\n", &bb[1][0], &bb[1][1], &bb[1][2] ) != 3);
fclose( f );
return !failed;
}
return false;
}
bool readormakecell( cell &c, const char *filename, int x, int y, int z )
{
if ( readcell( c, filename, x, y, z ) )
return true;
makecell( c, NULL, NULL );
offsetcell( c, x, y, z );
return false;
}
void clipcelltoportals( cell &c, int x, int y, int z )
{
char filename[256];
sprintf( filename, "brick_%d_%d_%d.v.cell", x, y, z );
if ( !readormakecell( c, filename, x*256, y*256, z*256 ) )
return;
int ofs[][3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 } };
cell n[6];
for (int i=0; i<6; i++)
{
sprintf( filename, "brick_%d_%d_%d.v.cell", x+ofs[i][0], y+ofs[i][1], z+ofs[i][2] );
readormakecell( n[i], filename, (x+ofs[i][0])*256, (y+ofs[i][1])*256, (z+ofs[i][2])*256 );
}
intersect( c, n, 6 );
}
int _tmain(int argc, _TCHAR* argv[])
{
#if 0
std::vector< std::string > files;
findFiles( files, argv[1] );
for (unsigned int i=0; i<files.size(); i++)
{
printf( "cell '%s'\n", files[i].c_str() );
makecell( (files[i]+".cell").c_str(), files[i].c_str() );
}
#endif
#if 1
float bb[2][3];
if ( readhdr( bb, "voxel.hdr" ) )
{
int ibb[2][3];
ibb[0][0] = 85-16;//(int)floorf( bb[0][0] );
ibb[0][1] = -712-16;//(int)floorf( bb[0][1] );
ibb[0][2] = 0-16;//(int)floorf( bb[0][2] );
ibb[1][0] = ibb[0][0]+16;//(int)ceilf( bb[1][0] );
ibb[1][1] = ibb[0][1]+16;//(int)ceilf( bb[1][1] );
ibb[1][2] = ibb[0][2]+16;//(int)ceilf( bb[1][2] );
ibb[0][0] = (int)floorf( bb[0][0] );
ibb[0][1] = (int)floorf( bb[0][1] );
ibb[0][2] = (int)floorf( bb[0][2] );
ibb[1][0] = (int)ceilf( bb[1][0] );
ibb[1][1] = (int)ceilf( bb[1][1] );
ibb[1][2] = (int)ceilf( bb[1][2] );
std::vector< cell > cells;
int w = (ibb[1][0]-ibb[0][0]);
int h = (ibb[1][1]-ibb[0][1]);
int d = (ibb[1][2]-ibb[0][2]);
cells.resize( w*h*d );
for (int z=ibb[0][2]; z<ibb[1][2]; z++)
{
printf("."); fflush(stdout);
int basez = z - ibb[0][2];
for (int y=ibb[0][1]; y<ibb[1][1]; y++)
{
int basey = y - ibb[0][1];
for (int x=ibb[0][0]; x<ibb[1][0]; x++)
{
int basex = x - ibb[0][0];
clipcelltoportals( cells[basex+(basey*w)+(basez*(w*h))], x, y, z );
}
}
}
writeobjofcell( "vis2.obj", &cells[0], cells.size() );
}
#endif
#if 0
makecell( "brick_25_-705_-7.cell", "brick_25_-705_-7.v" );
makecell( "brick_26_-705_-7.cell", "brick_26_-705_-7.v" );
makecell( "brick_25_-704_-7.cell", "brick_25_-704_-7.v" );
makecell( "brick_25_-705_-6.cell", "brick_25_-705_-6.v" );
makecell( "brick_24_-705_-7.cell", "brick_24_-705_-7.v" );
makecell( "brick_25_-706_-7.cell", "brick_25_-706_-7.v" );
makecell( "brick_25_-705_-8.cell", "brick_25_-705_-8.v" );
cell c00;
readcell( c00, "brick_25_-705_-7.cell", 0, 0, 0 );
cell n[6];
readcell( n[0], "brick_26_-705_-7.cell", 256, 0, 0 );
readcell( n[1], "brick_25_-704_-7.cell", 0, 256, 0 );
readcell( n[2], "brick_25_-705_-6.cell", 0, 0, 256 );
readcell( n[3], "brick_24_-705_-7.cell",-256, 0, 0 );
readcell( n[4], "brick_25_-706_-7.cell", 0,-256, 0 );
readcell( n[5], "brick_25_-705_-8.cell", 0, 0,-256 );
intersect( c00, n, 6 );
#endif
#if 0
{
FILE *f = fopen( "inter_portals.obj", "wb" );
if ( f )
{
for (unsigned int i=0; i<leaves.size(); i++)
{
for (unsigned int j=i+1; j<leaves.size(); j++)
{
if ( !touching( leaves[i], leaves[j] ) )
continue;
for (int face=0; face<6; face++)
{
quad q = clipquad( generatequad( leaves[i], face ), leaves[j] );
if ( isvalidquad( q ) )
{
outputquad( f, q );
}
}
}
}
}
}
{
std::vector< node* > external;
external.push_back( createbound( 0, 0, 256, 256, 256, 512 ) );
external.push_back( createbound( 256, 0, 0, 512, 256, 256 ) );
external.push_back( createbound( 0, 256, 0, 256, 512, 256 ) );
external.push_back( createbound( -256, 0, 0, 0, 256, 256 ) );
external.push_back( createbound( 0, -256, 0, 256, 0, 256 ) );
external.push_back( createbound( 0, 0, -256, 256, 256, 0 ) );
FILE *f = fopen( "external_portals.obj", "wb" );
if ( f )
{
for (unsigned int i=0; i<leaves.size(); i++)
{
for (unsigned int j=0; j<external.size(); j++)
{
if ( !touching( leaves[i], external[j] ) )
continue;
for (int face=0; face<6; face++)
{
quad q = clipquad( generatequad( leaves[i], face ), external[j] );
if ( isvalidquad( q ) )
{
outputquad( f, q );
}
}
}
}
}
}
if ( 0 )
{
FILE *f = fopen( "debug.obj", "wb" );
if ( f )
{
outputleafboxes( f, n );
fclose( f );
}
}
#endif
return 0;
}
// compressiondxt.cpp : Defines the entry point for the console application.
//
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stdafx.h"
#include "malloc.h"
#include "DDS.h"
#include "DDSTextureLoader.h"
#include "stb_image_write.h"
#include "crn_win32_timer.h"
#include <math.h>
#include <vector>
#include "miniz.h"
#define PARANOID 0
#include <map>
#include <list>
int *k_means( float **data, float *weights, int n, int m, int k, float t, float **centroids)
{
int iter = 50;
/* output cluster label for each data point */
int *labels = (int*)calloc(n, sizeof(int));
int h, i, j; /* loop counters, of course :) */
float *counts = (float*)calloc(k, sizeof(float)); /* size of each cluster */
float old_error, error = FLT_MAX; /* sum of squared euclidean distance */
float **c = centroids ? centroids : (float**)calloc(k, sizeof(float*));
float **c1 = (float**)calloc(k, sizeof(float*)); /* temp centroids */
assert(data && k > 0 && k <= n && m > 0 && t >= 0); /* for debugging */
/****** initialization */
for (h = i = 0; i < k; h += n / k, i++) {
c1[i] = (float*)calloc(m, sizeof(float));
if (!centroids) {
c[i] = (float*)calloc(m, sizeof(float));
}
/* pick k points as initial centroids */
for (j = m; j-- > 0; c[i][j] = data[h][j]);
}
/****** main loop */
do {
/* save error from last step */
old_error = error, error = 0;
/* clear old counts and temp centroids */
for (i = 0; i < k; counts[i++] = 0) {
for (j = 0; j < m; c1[i][j++] = 0);
}
for (h = 0; h < n; h++) {
/* identify the closest cluster */
float min_distance = FLT_MAX;
for (i = 0; i < k; i++) {
float distance = 0.f;
for (j = m; j-- > 0; distance += pow(data[h][j] - c[i][j], 2));
if (distance < min_distance) {
labels[h] = i;
min_distance = distance;
}
}
float w = weights ? weights[h] : 1.f;
/* update size and temp centroid of the destination cluster */
for (j = m; j-- > 0; c1[labels[h]][j] += data[h][j]*w);
counts[labels[h]]+=w;
/* update standard error */
error += min_distance;
}
for (i = 0; i < k; i++) { /* update all centroids */
for (j = 0; j < m; j++) {
c[i][j] = (counts[i]>0.f) ? c1[i][j] / counts[i] : c1[i][j];
}
}
printf("err %f\n", fabs(error - old_error) );
} while (--iter && fabs(error - old_error) > t);
/****
** housekeeping */
for (i = 0; i < k; i++) {
if (!centroids) {
free(c[i]);
}
free(c1[i]);
}
if (!centroids) {
free(c);
}
free(c1);
free(counts);
return labels;
}
struct rc_model
{
unsigned int tot;
unsigned int *pmf;
unsigned int *cdf;
int numSym;
};
static void rc_model_init (rc_model *acm, int nsym, int *ifreq, int adapt)
{
int i;
if ( nsym == 0 )
{
memset( acm, 0, sizeof(rc_model) );
return;
}
acm->numSym = nsym;
acm->pmf = (unsigned int *) (void *) calloc (nsym, sizeof (int));
acm->cdf = (unsigned int *) (void *) calloc (nsym+1, sizeof (int));
acm->tot = 0;
if (ifreq) {
acm->cdf[acm->numSym] = 0;
for (i=acm->numSym-1; i>=0; i--) {
acm->pmf[i] = ifreq[i];
acm->cdf[i] = acm->cdf[i+1] + acm->pmf[i];
}
} else {
for (i=0; i<acm->numSym; i++) {
acm->pmf[i] = 1;
acm->cdf[i] = acm->numSym - i;
}
}
acm->tot = acm->cdf[0];
}
static void rc_model_update(rc_model *acm, int sym)
{
int i;
if (acm->tot==16383) {
acm->cdf[acm->numSym] = 0;
for (i = acm->numSym-1; i>=0; i--) {
acm->pmf[i] = (acm->pmf[i] + 1) / 2;
acm->cdf[i] = acm->cdf[i+1] + acm->pmf[i];
}
acm->tot = acm->cdf[0];
return;
} else
{
acm->pmf[sym]++;
for (i=sym; i>=0; i--) {
acm->cdf[i]++;
}
acm->tot = acm->cdf[0];
}
}
static void rc_model_done (rc_model *acm)
{
free (acm->pmf);
acm->pmf = NULL;
free (acm->cdf);
acm->cdf = NULL;
}
struct rc_context
{
FILE *f;
unsigned char *readbuffer;
unsigned int bufferSize;
unsigned int range;
unsigned int low;
unsigned int code;
unsigned int pos;
unsigned int total_bits;
};
// output most significant byte
static void putbyte ( rc_context *ctx )
{
unsigned char c = ctx->low >> 24;
if ( ctx->f )
{
fwrite( &c, 1, 1, ctx->f );
}
else
{
if ( (ctx->total_bits/8) < ctx->bufferSize )
{
ctx->readbuffer[ctx->total_bits/8] = c;
}
}
ctx->low <<= 8; // shift out top 8 bits
ctx->total_bits += 8;
}
// normalize the range and output data
void rc_normalise_enc ( rc_context *ctx )
{
while ((( ctx->low ^ ( ctx->low + ctx->range )) >> 24) == 0)
{
putbyte( ctx ); // top 8 bits of interval are fixed ;...
ctx->range <<= 8; // ... output them and normalize interval
}
if (( ctx->range >> 16) == 0)
{
putbyte ( ctx ); // top 8 bits are not fixed but range ...
putbyte ( ctx ); // ... is small ; fudge range to avoid ...
ctx->range = (~ctx->low+1);//- ctx->low ; // ... carry and output top 16 bits
}
}
inline unsigned int firstHighBit( unsigned int v )
{
register unsigned int r;
register unsigned int shift;
r = (v > 0xFFFF) << 4; v >>= r;
shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
r |= (v >> 1);
return r;
}
// normalize the range and output data
void rc_normalise_dec ( rc_context *ctx )
{
unsigned int bitTest = ctx->low ^ ( ctx->low + ctx->range );
unsigned int bitShift = 24 - ( firstHighBit( bitTest ) & (~0x7) );
unsigned int rangeShift = 16 * ( ctx->range <= ( (unsigned int)0xffff >> bitShift ) );
bitShift += rangeShift;
ctx->pos += bitShift >> 3;
ctx->low <<= bitShift;
ctx->range = rangeShift ? (~ctx->low+1) : (ctx->range<<bitShift);
ctx->code = (((unsigned int)ctx->readbuffer[ctx->pos+0])<<24) |
(((unsigned int)ctx->readbuffer[ctx->pos+1])<<16) |
(((unsigned int)ctx->readbuffer[ctx->pos+2])<<8) |
(((unsigned int)ctx->readbuffer[ctx->pos+3])<<0);
}
void rc_encoder_init( rc_context *rc, FILE *f )
{
rc->f = f;
rc->low = 0;
rc->code = 0;
rc->pos = 0;
rc->range = 0xffffffff;
rc->readbuffer = 0;
rc->bufferSize = 0;
rc->total_bits = 0;
}
void rc_encoder_init( rc_context *rc, unsigned char *buffer, int bufferSize )
{
rc->f = NULL;
rc->low = 0;
rc->code = 0;
rc->pos = 0;
rc->range = 0xffffffff;
rc->readbuffer = buffer;
rc->bufferSize = bufferSize;
rc->total_bits = 0;
}
void rc_encoder_done( rc_context *ctx )
{
for (int n=0; n<4; n++)
{
putbyte( ctx );
}
}
void rc_decoder_init( rc_context *rc, const unsigned char *data )
{
rc->f = NULL;
rc->readbuffer = (unsigned char*)data;
rc->low = 0;
rc->code = 0;
rc->pos = 0;
rc->range = 0xffffffff;
rc->total_bits = 0;
rc->code = (((unsigned int)rc->readbuffer[rc->pos+0])<<24) |
(((unsigned int)rc->readbuffer[rc->pos+1])<<16) |
(((unsigned int)rc->readbuffer[rc->pos+2])<<8) |
(((unsigned int)rc->readbuffer[rc->pos+3])<<0);
}
// encode a symbol s using probability modeling
void rc_encode_symbol ( rc_context *ctx, rc_model * m, unsigned s )
{
if ( m->numSym == 0 )
return;
assert( s < m->numSym );
unsigned int cdf = m->cdf[s] - m->pmf[s];
ctx->range /= m-> tot ; // tot = sum of pmf
if ( ctx->range == 0 )
printf("");
ctx->low += ctx->range * cdf; // cdf = cum . distribution function P(x < s)
ctx->range *= m-> pmf [s ]; // pmf = probability mass function P(x = s)
if ( ctx->range == 0 )
printf("");
rc_model_update(m, s ); // update probabilities
rc_normalise_enc ( ctx ); // normalize interval
}
unsigned rc_decode_symbol ( rc_context *ctx, rc_model * m )
{
ctx->range /= m->tot;
//unsigned freq= ((*(unsigned int*)&ctx->readbuffer[ctx->pos])/*ctx->code*/-ctx->low) / (ctx->range);
unsigned int freq= (ctx->code-ctx->low) / (ctx->range);
assert( freq < m->tot );
unsigned s;
if ( m->numSym < 8 )
{
for (s = 0; m->cdf[s+1]>freq; s++) ;
} else
{
int mn = 0;
int mx = m->numSym;
while ( (mx-mn) > 8 )
{
int md = (mn+mx+1)/2;
if ( m->cdf[md+1] > freq )
{
mn = md;
} else
{
mx = md;
}
}
for (s = mn; m->cdf[s+1]>freq; s++) ;
}
unsigned int cdf = m->cdf[s] - m->pmf[s];
ctx->low += ctx->range * cdf; // cdf = cum . distribution function P(x < s)
ctx->range *= m->pmf[s]; // pmf = probability mass function P(x = s)
rc_model_update(m, s ); // update probabilities
rc_normalise_dec ( ctx ); // normalize interval
return s;
}
static unsigned int makeCtx( unsigned int a, unsigned int b, unsigned int c )
{
return (a<<16)|(b<<8)|c;
}
static int determineMatchSize( const unsigned char *buffer, int buffer_len, int a, int b )
{
int len = 0;
while ( len < 255 && (a+len)<buffer_len && (b+len)<buffer_len && buffer[a+len] == buffer[b+len] )
{
len++;
}
return len;
}
static bool findCode( int &code, int &ofs, const int distances[], int numDistances, int inputDist )
{
for (int i=0; i<numDistances; i++)
{
if ( inputDist >= distances[i] && inputDist < distances[i+1] )
{
code = i;
ofs = inputDist - distances[code];
return true;
}
}
code = numDistances-1;
ofs = inputDist - distances[code];
return true;
}
int zz_compress( unsigned char *outbuffer, unsigned int *out_buffer_len, const unsigned char *buffer, int buffer_len, int numBits )
{
std::map< unsigned int, std::list<unsigned int> > match;
const int lengths[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 83, 99, 115, 131, 163, 195, 227, 258, 259 };
const int numLengths = (sizeof(lengths) / sizeof(lengths[0]))-1;
const int distances[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769 };
const int numDistances = (sizeof(distances) / sizeof(distances[0]))-1;
const int symbols = 1 << numBits;
const int eos = symbols+1;
const int matched = eos+1;
rc_context ctx;
rc_encoder_init( &ctx, outbuffer, *out_buffer_len );
rc_model rc_m_symbol;
rc_model rc_m_distances;
rc_model rc_m_lengths[numLengths];
rc_model rc_m_distancesExtra[numDistances];
rc_model_init( &rc_m_symbol, symbols+1+numLengths, NULL, 1 );
rc_model_init( &rc_m_distances, 30, NULL, 1 );
for (int i=0; i<numLengths; i++)
{
rc_model_init( &rc_m_lengths[i], lengths[i+1]-lengths[i], NULL, 1 );
}
for (int i=0; i<numDistances; i++)
{
rc_model_init( &rc_m_distancesExtra[i], distances[i+1]-distances[i], NULL, 1 );
}
for (int i=0; i<buffer_len;)
{
int matchLen = 0;
int matchLoc = -1;
if ( (i+3) < buffer_len )
{
std::map< unsigned int, std::list<unsigned int> >::iterator f = match.find( makeCtx(buffer[i+0], buffer[i+1], buffer[i+2]) );
if ( f != match.end() )
{
std::list<unsigned int> &matches = f->second;
std::list<unsigned int>::iterator m = matches.begin();
while ( m != matches.end() )
{
unsigned int distance = i - *m;
if ( distance < 32768 )
{
int ml = determineMatchSize( buffer, buffer_len, i, *m );
if ( ml > matchLen )
{
matchLen = ml;
matchLoc = *m;
}
m++;
}
else
{
m = matches.erase( m );
}
}
}
}
int starti = i;
if ( matchLen < 3 )
{
rc_encode_symbol( &ctx, &rc_m_symbol, buffer[i] );
i++;
}
else
{
int distance = i - matchLoc;
int cl, ol;
findCode( cl, ol, lengths, numLengths, matchLen );
rc_encode_symbol( &ctx, &rc_m_symbol, matched+cl );
if ( rc_m_lengths[cl].numSym > 1 )
rc_encode_symbol( &ctx, &rc_m_lengths[cl], ol );
int cd, od;
findCode( cd, od, distances, numDistances, distance );
rc_encode_symbol( &ctx, &rc_m_distances, cd );
if ( rc_m_distancesExtra[cd].numSym > 1 )
rc_encode_symbol( &ctx, &rc_m_distancesExtra[cd], od );
i+=matchLen;
}
unsigned int lastCtx = -1;
while ( starti < i )
{
int ctxLoc = starti-2;
if ( ctxLoc >= 0 )
{
unsigned int newCtx = makeCtx(buffer[ctxLoc+0], buffer[ctxLoc+1], buffer[ctxLoc+2]);
if ( newCtx != lastCtx )
{
match[newCtx].push_back( ctxLoc );
lastCtx = newCtx;
}
}
starti++;
}
}
rc_encode_symbol( &ctx, &rc_m_symbol, eos );
rc_encoder_done( &ctx );
rc_model_done( &rc_m_symbol );
rc_model_done( &rc_m_distances );
for (int i=0; i<numLengths; i++)
{
rc_model_done( &rc_m_lengths[i] );
}
for (int i=0; i<numDistances; i++)
{
rc_model_done( &rc_m_distancesExtra[i] );
}
if ( (*out_buffer_len) > (ctx.total_bits / 8) )
{
*out_buffer_len = ctx.total_bits / 8;
return 0;
}
else
{
return -5;
}
}
int zz_decompress( unsigned char *outbuffer, unsigned int *out_buffer_len, const unsigned char *buffer, int buffer_len, int numBits )
{
const int lengths[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 83, 99, 115, 131, 163, 195, 227, 258, 259 };
const int numLengths = (sizeof(lengths) / sizeof(lengths[0]))-1;
const int distances[] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769 };
const int numDistances = (sizeof(distances) / sizeof(distances[0]))-1;
const int symbols = 1 << numBits;
const int eos = symbols+1;
const int matched = eos+1;
rc_context ctx;
rc_decoder_init( &ctx, buffer );
rc_model rc_m_symbol;
rc_model rc_m_distances;
rc_model rc_m_lengths[numLengths];
rc_model rc_m_distancesExtra[numDistances];
rc_model_init( &rc_m_symbol, symbols+1+numLengths, NULL, 1 );
rc_model_init( &rc_m_distances, 30, NULL, 1 );
for (int i=0; i<numLengths; i++)
{
rc_model_init( &rc_m_lengths[i], lengths[i+1]-lengths[i], NULL, 1 );
}
for (int i=0; i<numDistances; i++)
{
rc_model_init( &rc_m_distancesExtra[i], distances[i+1]-distances[i], NULL, 1 );
}
unsigned int writePos = 0;
while ( 1 )
{
int sym = rc_decode_symbol( &ctx, &rc_m_symbol );
if ( sym == eos )
break;
if ( sym < symbols )
{
outbuffer[writePos++] = sym;
}
else
{
int cl = sym - matched;
int ol = 0;
if ( rc_m_lengths[cl].numSym > 1 )
ol = rc_decode_symbol( &ctx, &rc_m_lengths[cl] );
int cd = rc_decode_symbol( &ctx, &rc_m_distances );
int od = 0;
if ( rc_m_distancesExtra[cd].numSym > 1 )
od = rc_decode_symbol( &ctx, &rc_m_distancesExtra[cd] );
int distance = distances[cd] + od;
int matchLen = lengths[cl] + ol;
int matchLoc = writePos - distance;
for (int i=0; i<matchLen; i++)
{
if ( writePos < *out_buffer_len )
outbuffer[writePos] = outbuffer[matchLoc];
writePos++;
matchLoc++;
}
}
}
rc_model_done( &rc_m_symbol );
rc_model_done( &rc_m_distances );
for (int i=0; i<numLengths; i++)
{
rc_model_done( &rc_m_lengths[i] );
}
for (int i=0; i<numDistances; i++)
{
rc_model_done( &rc_m_distancesExtra[i] );
}
if ( (*out_buffer_len) <= writePos )
{
*out_buffer_len = writePos;
return 0;
}
else
{
return -5;
}
}
static void *readFile( const char *filename, int &len )
{
FILE *f = fopen( filename, "rb" );
if ( f )
{
fseek( f, 0, SEEK_END );
len = ftell( f );
fseek( f, 0, SEEK_SET );
void *m = malloc( len );
fread( m, 1, len, f );
fclose( f );
return m;
}
return NULL;
}
struct dxtrgbblock
{
unsigned char c0[2];
unsigned char c1[2];
unsigned char bits[4];
};
struct bc3block
{
unsigned char a[2];
unsigned char bits[6];
};
struct dxta5block
{
unsigned char a0;
unsigned char a1;
unsigned char a[6];
};
struct dxt5block
{
bc3block a;
dxtrgbblock rgb;
};
void extractRGB565( unsigned char rgb[3], unsigned short colour )
{
rgb[0] = (colour >> ( 5 + 6 )) & ((1<<5)-1);
rgb[1] = (colour >> ( 5 )) & ((1<<6)-1);
rgb[2] = (colour >> ( 0 )) & ((1<<5)-1);
rgb[0] = (rgb[0] << 3) | (rgb[0] >> (5-3));
rgb[1] = (rgb[1] << 2) | (rgb[1] >> (6-2));
rgb[2] = (rgb[2] << 3) | (rgb[2] >> (5-3));
}
void generate4ColourSet( unsigned char rgb2[3], unsigned char rgb3[3], const unsigned char rgb0[3], const unsigned char rgb1[3] )
{
rgb2[0] = (2*(int)rgb0[0] + (int)rgb1[0])/3;
rgb2[1] = (2*(int)rgb0[1] + (int)rgb1[1])/3;
rgb2[2] = (2*(int)rgb0[2] + (int)rgb1[2])/3;
rgb3[0] = ((int)rgb0[0] + 2*(int)rgb1[0])/3;
rgb3[1] = ((int)rgb0[1] + 2*(int)rgb1[1])/3;
rgb3[2] = ((int)rgb0[2] + 2*(int)rgb1[2])/3;
}
void generate3ColourSet( unsigned char rgb2[3], unsigned char rgb3[3], const unsigned char rgb0[3], const unsigned char rgb1[3] )
{
rgb2[0] = ((int)rgb0[0] + (int)rgb1[0])/2;
rgb2[1] = ((int)rgb0[1] + (int)rgb1[1])/2;
rgb2[2] = ((int)rgb0[2] + (int)rgb1[2])/2;
rgb3[0] = 0;
rgb3[1] = 0;
rgb3[2] = 0;
}
int predictGreen( int up, int left, int diag, int &method )
{
int ma = abs(abs(diag-up) - abs(diag-left));
int mb = abs(diag-up);
int mc = abs(diag-left);
if ( ma < 4 && mb < 4 )
{
method = 0;
return left+up-diag;
} else
if ( ma < 10 )
{
method = 1;
return (left+up)/2;
} else
if ( ma < 64 )
{
if ( mb < mc )
{
method = 2;
return (3*left+up)/4;
} else
{
method = 3;
return (3*up+left)/4;
}
} else
{
if ( mb < mc )
{
method = 4;
return left;
} else
{
method = 5;
return up;
}
}
}
int findClosestG( unsigned char blockrgb[4][3], int g )
{
int best = 0;
int besterr = abs( blockrgb[best][1] - g );
for (int i=1; i<4; i++)
{
int err = abs( blockrgb[i][1] - g );
if ( err < besterr )
{
besterr = err;
best = i;
}
}
return best;
}
inline int sqr( int v )
{
return v*v;
}
int findClosestRGB( unsigned char blockrgb[4][3], int r, int g, int b )
{
int best = 0;
int besterr = sqr( blockrgb[best][0] - r ) + sqr( blockrgb[best][1] - g ) + sqr( blockrgb[best][2] - b );
for (int i=1; i<4; i++)
{
int err = sqr( blockrgb[i][0] - r ) + sqr( blockrgb[i][1] - g ) + sqr( blockrgb[i][2] - b );//abs( blockrgb[i][1] - g );
if ( err < besterr )
{
besterr = err;
best = i;
}
}
return best;
}
int findClosestA( unsigned char blocka[8], int a )
{
int best = 0;
int besterr = abs(blocka[best] - a);
for (int i=1; i<8; i++)
{
int err = abs(blocka[i] - a);
if ( err < besterr )
{
besterr = err;
best = i;
}
}
return best;
}
inline unsigned int ZigZag(int word) {
return (word >> 15) ^ (word << 1);
}
inline unsigned int UnZigZag(int word) {
return (word >> 1) ^ (-(word&1));
}
int jpeglsPredictor( int up, int left, int diag, int &method )
{
int mxul = max(up,left);
int mnul = min(up,left);
if ( diag >= mxul )
{
method = 0;
return mnul;
} else
if ( diag <= mnul )
{
method = 1;
return mxul;
}
method = 2;
return up+left-diag;
}
int PaethPredictor(int up, int left, int diag, int &method )
{
int p = left + up - diag;
int pa = abs(p - left);
int pb = abs(p - up);
int pc = abs(p - diag);
// return nearest of left,b,c,
// breaking ties in order left,b,c.
if ( pa <= pb && pa <= pc )
{
method = 0;
return left;
}
if ( pb <= pc )
{
method = 1;
return up;
}
method = 2;
return diag;
}
int iFreq0[] =
{ 53, 1, 24, 8 };
int iFreq1[] =
{ 2, 79, 10, 28 };
int iFreq2[] =
{ 18, 5, 37, 19 };
int iFreq3[] =
{ 6, 26, 31, 58 };
int runLength( dxtrgbblock *blocks, int x, int w )
{
int count = 0;
for (int i=1; i<8 && (x+i)<w; i++)
{
if ( memcmp( &blocks[x], &blocks[x+i], sizeof(dxtrgbblock) ) )
{
break;
}
count++;
}
return count;
}
int runLength( dxt5block *blocks, int x, int w )
{
int count = 0;
for (int i=1; i<8 && (x+i)<w; i++)
{
if ( memcmp( &blocks[x], &blocks[x+i], sizeof(dxt5block) ) )
{
break;
}
count++;
}
return count;
}
int runLength( void *blocks, int blockSize, int x, int w )
{
int count = 0;
for (int i=1; i<8 && (x+i)<w; i++)
{
if ( memcmp( &(((char*)blocks)[i*blockSize]), blocks, blockSize ) )
{
break;
}
count++;
}
return count;
}
static float IndexGradientOrder4[] = { 0.f, 3.f, 1.f, 2.f };
static float IndexGradientOrder3[] = { 1.f, 3.f, 2.f, -10000.f };
static int remap4[] = { 0, 2, 3, 1 };
static int remap3[] = { 3, 0, 2, 1 };
int roundf( float v )
{
return (int)floorf( v + 0.5f );
}
inline int clamp( int v, int mn, int mx )
{
return (v<mn) ? mn : (v>mx) ? mx : v;
}
unsigned int mapSelector( float *v, int *remap )
{
unsigned int bits = 0;
int selectorIndex = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
int idx = remap[ clamp( roundf( v[selectorIndex++] ), (remap == remap3) ? 1 : 0, 3 ) ];
bits |= idx << (2*(4*i+j));
}
}
return bits;
}
void kmeanstest( const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
return;
int curw = desc.width;
int curh = desc.height;
int numSelectors = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
numSelectors += blockw * blockh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
float **selectors = (float**)malloc( numSelectors * sizeof( float* ) );
float *weights = (float*)malloc( numSelectors * sizeof( float ) );
float *selectorVectors = (float*)malloc( numSelectors * sizeof( float ) * 16 );
int curSelector = 0;
curw = desc.width;
curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256;
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256;
unsigned int bits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3]));
unsigned char blockrgb[2][3];
extractRGB565( blockrgb[0], colour0 );
extractRGB565( blockrgb[1], colour1 );
selectors[curSelector] = &selectorVectors[curSelector*16];
weights[curSelector] = /*sqrtf*/( (((float)blockrgb[0][0]-(float)blockrgb[1][0]) * ((float)blockrgb[0][0]-(float)blockrgb[1][0])) +
(((float)blockrgb[0][1]-(float)blockrgb[1][1]) * ((float)blockrgb[0][1]-(float)blockrgb[1][1])) +
(((float)blockrgb[0][2]-(float)blockrgb[1][2]) * ((float)blockrgb[0][2]-(float)blockrgb[1][2])) );
float *gradient;
if ( (colour0 > colour1) || !isdxt1 )
{
gradient = IndexGradientOrder4;
} else
{
gradient = IndexGradientOrder3;
}
int selectorIndex = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
selectors[curSelector][selectorIndex] = gradient[ (bits >> (2*(4*i+j))) & 3 ];
selectorIndex++;
}
}
curSelector++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
int k = 2048;
float **centroids = (float **)malloc( k * sizeof( float* ) );
float *centroidVector = (float *)malloc( k * sizeof( float ) * 16 );
for (int i=0; i<k; i++)
{
centroids[i] = &centroidVector[ i * 16 ];
}
int *label = k_means( selectors, weights, numSelectors, 16, k, 0.01f, centroids );
curSelector = 0;
curw = desc.width;
curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256;
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256;
unsigned int testbits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3]));
unsigned int bits = mapSelector( centroids[ label[curSelector] ], ( (colour0 > colour1) || !isdxt1 ) ? remap4 : remap3 );
blocks[x].bits[0] = bits & 0xff;
blocks[x].bits[1] = (bits>>8) & 0xff;
blocks[x].bits[2] = (bits>>16) & 0xff;
blocks[x].bits[3] = (bits>>24) & 0xff;
curSelector++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
void compress_bc1_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
static unsigned char imgchunks[2][(4096/4) * (4096/4) * 3 ] = {0};
static unsigned char decompressed[4096 * 4096 * 3] = {0};
// static unsigned char imgindices[2048 * 2048 ] = {0};
// static unsigned char predindices[2048 * 2048 ] = {0};
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
rc_context rciindicesEnc;
rc_encoder_init( &rciindicesEnc, f );
rc_model rciindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rciindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rciindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rciindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rciindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rcTestModel;
rc_model_init( &rcTestModel, 256, NULL, 1 );
rc_model rccolmodel[6][2][3];
int initialfreq[256*2];
for (int j=0; j<2; j++)
{
for (int c=0; c<3; c++)
{
int bits = c == 1 ? 6 : 5;
for (int i = 0; i<((1<<bits)*2)+1; i++)
{
initialfreq[i] = 1+((1<<bits)/(((i+1)/2)+1));
}
rc_model_init( &rccolmodel[0][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[1][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[2][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[3][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[4][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[5][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
}
}
int rcencodeindexbits = 0;
int rcencodeimagebits[2] = { 0 };
int uncindexbits = 0;
int uncimagebits[2] = { 0 };
int counts[3] = { 0 };
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
int indices[4][4];
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256;
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256;
unsigned int bits = blocks[x].bits[0] + 256 * ((int)blocks[x].bits[1] + 256 * ((int)blocks[x].bits[2] + 256 * (int)blocks[x].bits[3]));
unsigned char blockrgb[4][3];
extractRGB565( blockrgb[0], colour0 );
extractRGB565( blockrgb[1], colour1 );
if ( (colour0 > colour1) || !isdxt1 )
{
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
} else
{
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
}
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
int index = (y * blockw + x)*3;
imgchunks[0][index+0] = blockrgb[0][0];
imgchunks[0][index+1] = blockrgb[0][1];
imgchunks[0][index+2] = blockrgb[0][2];
imgchunks[1][index+0] = blockrgb[1][0];
imgchunks[1][index+1] = blockrgb[1][1];
imgchunks[1][index+2] = blockrgb[1][2];
{
int upy = (y-1);
int leftx = (x-1);
int upindex = (upy * blockw + x) * 3;
int leftindex = (y * blockw + leftx) * 3;
int diagindex = (upy * blockw + leftx) * 3;
int curindex = (y * blockw + x) * 3;
for (int r=0; r<2; r++)
{
long rcstartbits = rciindicesEnc.total_bits;
int error = 0;
for (int c=0; c<3; c++)
{
int up = upy >= 0 ? imgchunks[r][upindex+c] : 0;
int left = leftx >= 0 ? imgchunks[r][leftindex+c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex+c] : 0;
int actual = imgchunks[r][curindex+c];
int bits = c == 1 ? 6 : 5;
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
actual >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
//int predict = predictGreen( up, left, diag, method );
predict += error;
if ( predict < 0 )
{
predict = 0;
}
if ( predict >= (1<<bits) )
{
predict = (1<<bits)-1;
}
int diff = predict - actual;
int zzdiff = ZigZag( diff );
error = -diff;
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff);
uncimagebits[r] += 16;
}
long rcendbits = rciindicesEnc.total_bits;
rcencodeimagebits[r] += rcendbits - rcstartbits;
}
}
long rcstartbits = rciindicesEnc.total_bits;
#if 1
int errorR = 0;
int errorG = 0;
int errorB = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[3] = { 0, 0, 0 };
int upy = (y*4+i-1);
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j)) * 3;
int leftindex = ((y*4+i) * (blockw*4) +leftx) * 3;
int diagindex = (upy * (blockw*4) + leftx) * 3;
int curindex = ((y*4+i) * (blockw*4) + (x*4+j)) * 3;
unsigned char* left = leftx >= 0 ? &decompressed[leftindex] : zeros;
unsigned char* up = upy >= 0 ? &decompressed[upindex] : left;//zeros;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? &decompressed[diagindex] : up;//zeros;
int actualIndex = indices[i][j];
int methodr, methodg, methodb;
int pr = predictGreen( up[0], left[0], diag[0], methodr );
int pg = predictGreen( up[1], left[1], diag[1], methodg );
int pb = predictGreen( up[2], left[2], diag[2], methodb );
int pindex = findClosestG( blockrgb, pg );
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
predictR += errorR;
predictG += errorG;
predictB += errorB;
int pindex2 = findClosestRGB( blockrgb, pr, pg, pb );
int pindex3 = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = methodg;
method = ((methodR * 3 + methodG)*3 + methodB);// % 6;
assert( method < (3*3*3) );
pindex = pindex3;
counts[0] += pindex == actualIndex;
counts[1] += pindex2 == actualIndex;
counts[2] += pindex3 == actualIndex;
float diffr = ((float)blockrgb[actualIndex][0] - (float)blockrgb[pindex][0]);
float diffg = ((float)blockrgb[actualIndex][1] - (float)blockrgb[pindex][1]);
float diffb = ((float)blockrgb[actualIndex][2] - (float)blockrgb[pindex][2]);
//errorR = diffr;//blockrgb[actualIndex][0] - predictR;
//errorG = diffg;//blockrgb[actualIndex][1] - predictG;
//errorB = diffb;//blockrgb[actualIndex][2] - predictB;
//if ( i || j )
//{
// errorR = blockrgb[actualIndex][0] - predictR;
// errorG = blockrgb[actualIndex][1] - predictG;
// errorB = blockrgb[actualIndex][2] - predictB;
//}
float dist = sqrtf( diffr * diffr + diffg * diffg + diffb * diffb );
if ( (((int)dist)>>3) <= 0.f )
{
//actualIndex = pindex;
}
int diff = pindex - actualIndex;
int zzdiff = ZigZag( diff );
int decindex = ((y*4+i) * (blockw*4) + (x*4+j));
// predindices[decindex] = zzdiff * 16;
rc_encode_symbol (&rciindicesEnc, &rciindicesModel[method][pindex], actualIndex);
decompressed[curindex+0] = blockrgb[actualIndex][0];
decompressed[curindex+1] = blockrgb[actualIndex][1];
decompressed[curindex+2] = blockrgb[actualIndex][2];
}
}
#else
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[0] );
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[1] );
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[2] );
rc_encode_symbol( &rciindicesEnc, &rcTestModel, blocks[x].bits[3] );
#endif
uncindexbits += 2 * 16;
long rcendbits = rciindicesEnc.total_bits;
rcencodeindexbits += rcendbits - rcstartbits;
int rll = runLength( blocks, x, blockw );
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll);
for (int r=0; r<rll; r++)
{
memcpy( &imgchunks[0][index+(r+1)*3], &imgchunks[0][index+0], 3 );
memcpy( &imgchunks[1][index+(r+1)*3], &imgchunks[1][index+0], 3 );
for (int j=0; j<4; j++)
{
int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4) * 3;
int curindex = ((y*4+j) * (blockw*4) + (x*4)) * 3;
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*3 );
}
}
x += rll;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
rc_encoder_done (&rciindicesEnc);
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rciindicesModel[i][0]);
rc_model_done (&rciindicesModel[i][1]);
rc_model_done (&rciindicesModel[i][2]);
rc_model_done (&rciindicesModel[i][3]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<3; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
//printf( "index %f k (%.2f%%) (%.2f%% of original)\n", rcencodeindexbits / (8.f*1024.f), (rcencodeindexbits*100.f)/(rcencodeindexbits), (rcencodeindexbits*100.f)/(uncindexbits) );
printf( "index %f k (%.2f%%) (%.2f%% of original)\n", rcencodeindexbits / (8.f*1024.f), (rcencodeindexbits*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeindexbits*100.f)/(uncindexbits) );
printf( "rgb0 %f k (%.2f%%) (%.2f%% of original)\n", rcencodeimagebits[0] / (8.f*1024.f), (rcencodeimagebits[0]*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeimagebits[0]*100.f)/(uncimagebits[0]) );
printf( "rgb1 %f k (%.2f%%) (%.2f%% of original)\n", rcencodeimagebits[1] / (8.f*1024.f), (rcencodeimagebits[1]*100.f)/(rcencodeindexbits+rcencodeimagebits[0]+rcencodeimagebits[1]), (rcencodeimagebits[1]*100.f)/(uncimagebits[1]) );
fclose( f );
}
struct rgba
{
union
{
struct
{
unsigned char r, g, b, a;
};
unsigned char c[4];
};
};
void extractBC1BlockData( unsigned char cols[4][3], int indices[4][4], dxtrgbblock const *block, bool isBC1 )
{
unsigned short colour0 = block->c0[0] + block->c0[1] * 256;
unsigned short colour1 = block->c1[0] + block->c1[1] * 256;
unsigned int bits = block->bits[0] + 256 * ((unsigned int)block->bits[1] + 256 * ((unsigned int)block->bits[2] + 256 * (unsigned int)block->bits[3]));
extractRGB565( cols[0], colour0 );
extractRGB565( cols[1], colour1 );
if ( (colour0 > colour1) || !isBC1 )
{
generate4ColourSet( cols[2], cols[3], cols[0], cols[1] );
} else
{
generate3ColourSet( cols[2], cols[3], cols[0], cols[1] );
}
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
}
static void generate6AlphaSet( unsigned char *a, unsigned char alpha_0, unsigned char alpha_1 )
{
a[0] = alpha_0;
a[1] = alpha_1;
a[2] = (6*alpha_0)/7 + (1*alpha_1)/7; // bit code 010
a[3] = (5*alpha_0)/7 + (2*alpha_1)/7; // bit code 011
a[4] = (4*alpha_0)/7 + (3*alpha_1)/7; // bit code 100
a[5] = (3*alpha_0)/7 + (4*alpha_1)/7; // bit code 101
a[6] = (2*alpha_0)/7 + (5*alpha_1)/7; // bit code 110
a[7] = (1*alpha_0)/7 + (6*alpha_1)/7; // bit code 111
}
static void generate4AlphaSet( unsigned char *a, unsigned char alpha_0, unsigned char alpha_1 )
{
// 4 interpolated alpha values.
a[0] = alpha_0;
a[1] = alpha_1;
a[2] = (4*alpha_0)/5 + (1*alpha_1)/5; // bit code 010
a[3] = (3*alpha_0)/5 + (2*alpha_1)/5; // bit code 011
a[4] = (2*alpha_0)/5 + (3*alpha_1)/5; // bit code 100
a[5] = (1*alpha_0)/5 + (4*alpha_1)/5; // bit code 101
a[6] = 0; // bit code 110
a[7] = 255; // bit code 111
}
void extractBC3BlockData( unsigned char alpha[8], int indices[4][4], bc3block const *block )
{
unsigned __int64 bits;
if ( block == NULL )
{
generate4AlphaSet( alpha, 0, 5 );
bits = 255 + 256 * ((unsigned __int64)255 +
256 * ((unsigned __int64)255 +
256 * ((unsigned __int64)255 +
256 * ((unsigned __int64)255 +
256 * ((unsigned __int64)255
)))));
}
else
{
if ( block->a[0] > block->a[1] )
{
generate6AlphaSet( alpha, block->a[0], block->a[1] );
}
else
{
generate4AlphaSet( alpha, block->a[0], block->a[1] );
}
bits = block->bits[0] + 256 * ((unsigned __int64)block->bits[1] +
256 * ((unsigned __int64)block->bits[2] +
256 * ((unsigned __int64)block->bits[3] +
256 * ((unsigned __int64)block->bits[4] +
256 * ((unsigned __int64)block->bits[5]
)))));
}
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
}
inline int QuantizeGradient( int g )
{
const int T1 = 3;
const int T2 = 7;
const int T3 = 21;
const int NR = 0;
int Q;
if (g <= -T3) Q=-4;
else if (g <= -T2) Q=-3;
else if (g <= -T1) Q=-2;
else if (g < -NR) Q=-1;
else if (g <= NR) Q= 0;
else if (g < T1) Q= 1;
else if (g < T2) Q= 2;
else if (g < T3) Q= 3;
else Q= 4;
return Q;
}
int MergeContext( int &sign, int q1, int q2, int q3 )
{
if ( q1 < 0
|| (q1 == 0 && q2 < 0)
|| (q1 == 0 && q2 == 0 && q3 < 0) ) {
q1=-q1;
q2=-q2;
q3=-q3;
sign=-1; // signifies -ve
}
else {
sign=1; // signifies +ve
}
int q;
if (q1 == 0) {
if (q2 == 0) {
q=360+q3; // fills 360..364
}
else { // Q2 is 1 to 4
q=324+(q2-1)*9+(q3+4); // fills 324..359
}
}
else { // Q1 is 1 to 4
q=(q1-1)*81+(q2+4)*9+(q3+4); // fills 0..323
}
return q;
}
static int clockAdd( int a, int b, int numBits )
{
return (a+b) & ((1<<numBits)-1);
}
static int clockDiff( int a, int b, int numBits )
{
return ((a+(1<<numBits))-b) & ((1<<numBits)-1);
}
void compress_bc3_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
static rgba imgchunks[2][(4096/4) * 2 ] = {0};
static rgba decompressed[4096 * 8] = {0};
const int predictionbits[4] = { 5, 6, 5, 8 };
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
rc_context rciindicesEnc;
rc_encoder_init( &rciindicesEnc, f );
rc_model rc_c_iindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rc_a_iindicesModel[3][8];
for (int i=0; i<(3); i++)
{
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rcTestModel;
rc_model_init( &rcTestModel, 256, NULL, 1 );
rc_model rccolmodel[6][2][4];
int initialfreq[256*2+1];
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
int bits = predictionbits[c];
for (int i=0; i<(1<<bits); i++)
{
int mid = (1<<bits)/2;
int dist = i < mid ? i : ((1<<bits)-i-1);
initialfreq[i] = ((1<<bits)/(dist+1))+1;
}
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 );
}
}
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxt5block *blocks = (dxt5block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
int indicesrgb[4][4];
unsigned char blockrgb[4][3];
extractBC1BlockData( blockrgb, indicesrgb, &blocks[x].rgb, false );
int indicesa[4][4];
unsigned char blocka[8];
extractBC3BlockData( blocka, indicesa, &blocks[x].a );
int index = ((y%2) * blockw + x);
imgchunks[0][index].r = blockrgb[0][0];
imgchunks[0][index].g = blockrgb[0][1];
imgchunks[0][index].b = blockrgb[0][2];
imgchunks[0][index].a = blocka[0];
imgchunks[1][index].r = blockrgb[1][0];
imgchunks[1][index].g = blockrgb[1][1];
imgchunks[1][index].b = blockrgb[1][2];
imgchunks[1][index].a = blocka[1];
// block end point encode
{
int cury = (y) % 2;
int upy = (y-1) % 2;
int leftx = (x-1);
int upindex = (upy * blockw + x);
int leftindex = (cury * blockw + leftx);
int diagindex = (upy * blockw + leftx);
int curindex = (cury * blockw + x);
int error = 0;
for (int r=0; r<2; r++)
{
for (int c=0; c<4; c++)
{
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0;
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0;
int actual = imgchunks[r][curindex].c[c];
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual);
#endif
int bits = predictionbits[c];
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
actual >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
predict += error;
if ( predict < 0 )
predict = 0;
if ( predict >= (1<<bits) )
predict = (1<<bits)-1;
int diff = predict - actual;
int zzdiff = clockDiff( actual, predict , bits );
int test = clockAdd( predict, zzdiff, bits );
assert( test == actual );
error = -diff;
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predict);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual);
#endif
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff);
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], c);
#endif
}
}
unsigned short colour0 = ((unsigned short)(imgchunks[0][curindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[0][curindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[0][curindex].c[2]>>3));
unsigned short colour1 = ((unsigned short)(imgchunks[1][curindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[1][curindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[1][curindex].c[2]>>3));
assert( (colour0&0xff) == blocks[x].rgb.c0[0] );
assert( ((colour0>>8)&0xff) == blocks[x].rgb.c0[1] );
assert( (colour1&0xff) == blocks[x].rgb.c1[0] );
assert( ((colour1>>8)&0xff) == blocks[x].rgb.c1[1] );
}
if ( 1 )
{
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c0[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c0[1]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c1[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blocks[x].rgb.c1[1]);
#endif
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
int curindex = (cury * (blockw*4) + (x*4+j));
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros;
int actualIndex = indicesrgb[i][j];
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = ((methodR * 3 + methodG)*3 + methodB);
assert( method < (3*3*3) );
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], methodR);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predictR);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex);
#endif
rc_encode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex], actualIndex);
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j);
#endif
decompressed[curindex].r = blockrgb[actualIndex][0];
decompressed[curindex].g = blockrgb[actualIndex][1];
decompressed[curindex].b = blockrgb[actualIndex][2];
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].r);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].g);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].b);
#endif
}
}
}
if ( 1 )
{
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
int curindex = (cury * (blockw*4) + (x*4+j));
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up;
int actualIndex = indicesa[i][j];
int method;
int predict = jpeglsPredictor( up[3], left[3], diag[3], method );
int pindex = findClosestA( blocka, predict );
rc_encode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex], actualIndex);
decompressed[curindex].a = blocka[actualIndex];
}
}
}
if ( 1 )
{
int rll = runLength( blocks, x, blockw );
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll);
for (int r=0; r<rll; r++)
{
memcpy( &imgchunks[0][index+(r+1)], &imgchunks[0][index+0], 4 );
memcpy( &imgchunks[1][index+(r+1)], &imgchunks[1][index+0], 4 );
for (int j=0; j<4; j++)
{
int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4);
int curindex = ((y*4+j) * (blockw*4) + (x*4));
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 );
}
}
x += rll;
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
rc_encoder_done (&rciindicesEnc);
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rc_c_iindicesModel[i][0]);
rc_model_done (&rc_c_iindicesModel[i][1]);
rc_model_done (&rc_c_iindicesModel[i][2]);
rc_model_done (&rc_c_iindicesModel[i][3]);
}
for (int i=0; i<(3); i++)
{
rc_model_done (&rc_a_iindicesModel[i][0]);
rc_model_done (&rc_a_iindicesModel[i][1]);
rc_model_done (&rc_a_iindicesModel[i][2]);
rc_model_done (&rc_a_iindicesModel[i][3]);
rc_model_done (&rc_a_iindicesModel[i][4]);
rc_model_done (&rc_a_iindicesModel[i][5]);
rc_model_done (&rc_a_iindicesModel[i][6]);
rc_model_done (&rc_a_iindicesModel[i][7]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
fclose( f );
}
void compress_bc1and3_lcct( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
rgba *imgchunks[2];//[(4096/4) * 2 ] = {0};
rgba *decompressed;//[4096 * 8] = {0};
imgchunks[0] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 );
imgchunks[1] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 );
decompressed = (rgba*)malloc( sizeof(rgba) * desc.width * 8 );
const int predictionbits[4] = { 5, 6, 5, 8 };
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
rc_context rciindicesEnc;
rc_encoder_init( &rciindicesEnc, f );
rc_model rc_c_iindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rc_a_iindicesModel[3][8];
for (int i=0; i<(3); i++)
{
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rcTestModel;
rc_model_init( &rcTestModel, 256, NULL, 1 );
rc_model rccolmodel[6][2][4];
int initialfreq[256*2+1];
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
int bits = predictionbits[c];
for (int i=0; i<(1<<bits); i++)
{
int mid = (1<<bits)/2;
int dist = i < mid ? i : ((1<<bits)-i-1);
initialfreq[i] = ((1<<bits)/(dist+1))+1;
}
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 );
}
}
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
if ( x == 342 )
printf("");
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
int indicesrgb[4][4];
unsigned char blockrgb[4][3];
extractBC1BlockData( blockrgb, indicesrgb, blockbc1, isdxt1 );
int indicesa[4][4];
unsigned char blocka[8];
extractBC3BlockData( blocka, indicesa, blockbc3a );
int curblocky = (y) % 2;
int curblockindex = (curblocky * blockw + x);
imgchunks[0][curblockindex].r = blockrgb[0][0];
imgchunks[0][curblockindex].g = blockrgb[0][1];
imgchunks[0][curblockindex].b = blockrgb[0][2];
imgchunks[0][curblockindex].a = blocka[0];
imgchunks[1][curblockindex].r = blockrgb[1][0];
imgchunks[1][curblockindex].g = blockrgb[1][1];
imgchunks[1][curblockindex].b = blockrgb[1][2];
imgchunks[1][curblockindex].a = blocka[1];
// block end point encode
{
int numc = blockbc3a ? 4 : 3;
int upy = (y-1) % 2;
int leftx = (x-1);
int upindex = (upy * blockw + x);
int leftindex = (curblocky * blockw + leftx);
int diagindex = (upy * blockw + leftx);
int error = 0;
for (int r=0; r<2; r++)
{
for (int c=0; c<numc; c++)
{
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0;
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0;
int actual = imgchunks[r][curblockindex].c[c];
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual);
#endif
int bits = predictionbits[c];
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
actual >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
predict += error;
if ( predict < 0 )
predict = 0;
if ( predict >= (1<<bits) )
predict = (1<<bits)-1;
int diff = predict - actual;
int zzdiff = clockDiff( actual, predict , bits );
int test = clockAdd( predict, zzdiff, bits );
assert( test == actual );
error = -diff;
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predict);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], actual);
#endif
rc_encode_symbol (&rciindicesEnc, &rccolmodel[method][r][c], zzdiff);
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], c);
#endif
}
}
unsigned short colour0 = ((unsigned short)(imgchunks[0][curblockindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[0][curblockindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[0][curblockindex].c[2]>>3));
unsigned short colour1 = ((unsigned short)(imgchunks[1][curblockindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[1][curblockindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[1][curblockindex].c[2]>>3));
assert( (colour0&0xff) == blockbc1->c0[0] );
assert( ((colour0>>8)&0xff) == blockbc1->c0[1] );
assert( (colour1&0xff) == blockbc1->c1[0] );
assert( ((colour1>>8)&0xff) == blockbc1->c1[1] );
}
if ( 1 )
{
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c0[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c0[1]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c1[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc1->c1[1]);
#endif
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
int curindex = (cury * (blockw*4) + (x*4+j));
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros;
int actualIndex = indicesrgb[i][j];
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = ((methodR * 3 + methodG)*3 + methodB);
assert( method < (3*3*3) );
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], methodR);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], predictR);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex);
#endif
rc_encode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex], actualIndex);
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j);
#endif
decompressed[curindex].r = blockrgb[actualIndex][0];
decompressed[curindex].g = blockrgb[actualIndex][1];
decompressed[curindex].b = blockrgb[actualIndex][2];
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].r);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].g);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].b);
#endif
}
}
}
if ( blockbc3a )
{
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc3a->a[0]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], blockbc3a->a[1]);
#endif
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
int curindex = (cury * (blockw*4) + (x*4+j));
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up;
int actualIndex = indicesa[i][j];
int method;
int predict = jpeglsPredictor( up[3], left[3], diag[3], method );
int pindex = findClosestA( blocka, predict );
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], up[3]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], left[3]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], diag[3]);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], method);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], pindex);
#endif
rc_encode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex], actualIndex);
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], i);
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], j);
#endif
decompressed[curindex].a = blocka[actualIndex];
#if PARANOID
rc_encode_symbol (&rciindicesEnc, &rccolmodel[0][0][3], decompressed[curindex].a);
#endif
}
}
}
if ( 1 )
{
int rll = runLength( ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)), blockSize, x, blockw );
rc_encode_symbol (&rciindicesEnc, &rcrllModel, rll);
for (int r=0; r<rll; r++)
{
memcpy( &imgchunks[0][curblockindex+(r+1)], &imgchunks[0][curblockindex+0], 4 );
memcpy( &imgchunks[1][curblockindex+(r+1)], &imgchunks[1][curblockindex+0], 4 );
for (int j=0; j<4; j++)
{
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4);
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4));
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 );
}
}
x += rll;
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
rc_encoder_done (&rciindicesEnc);
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rc_c_iindicesModel[i][0]);
rc_model_done (&rc_c_iindicesModel[i][1]);
rc_model_done (&rc_c_iindicesModel[i][2]);
rc_model_done (&rc_c_iindicesModel[i][3]);
}
for (int i=0; i<(3); i++)
{
rc_model_done (&rc_a_iindicesModel[i][0]);
rc_model_done (&rc_a_iindicesModel[i][1]);
rc_model_done (&rc_a_iindicesModel[i][2]);
rc_model_done (&rc_a_iindicesModel[i][3]);
rc_model_done (&rc_a_iindicesModel[i][4]);
rc_model_done (&rc_a_iindicesModel[i][5]);
rc_model_done (&rc_a_iindicesModel[i][6]);
rc_model_done (&rc_a_iindicesModel[i][7]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
free( imgchunks[0] );
free( imgchunks[1] );
free( decompressed );
fclose( f );
}
void deltaEncode( unsigned char *stream, int num, int bits )
{
int last = 0;
for (int i=0; i<num; i++)
{
int diff = clockDiff( stream[i], last, bits );
last = stream[i];
stream[i] = diff;
}
}
void deltaDecode( unsigned char *stream, int num, int bits )
{
int last = 0;
for (int i=0; i<num; i++)
{
int value = clockAdd( last, stream[i], bits );
stream[i] = value;
last = value;
}
}
int fwrite_compressed( const void *data, int len, FILE *f )
{
mz_ulong compressedSize = mz_deflateBound( NULL, len );
unsigned char *comp = (unsigned char*)malloc(compressedSize);
int res = mz_compress2( comp, &compressedSize, (const unsigned char*)data, len, MZ_UBER_COMPRESSION );
if ( res != 0 )
{
printf( "failed compress %d\n", res );
}
fwrite( comp, compressedSize, 1, f );
free( comp );
return compressedSize;
}
int fwrite_compressed_zz( const void *data, int len, FILE *f, int numBits=8 )
{
unsigned int compressedSize = mz_deflateBound( NULL, len );
unsigned char *comp = (unsigned char*)malloc(compressedSize);
int res = zz_compress( comp, &compressedSize, (const unsigned char*)data, len, numBits );
if ( res != 0 )
{
printf( "failed compress %d\n", res );
}
fwrite( comp, compressedSize, 1, f );
free( comp );
return compressedSize;
}
void* decompress( int expected, const void *data, int len )
{
unsigned char *dst = (unsigned char*)malloc( expected );
mz_ulong pDest_len = expected;
int res = mz_uncompress(dst, &pDest_len, (const unsigned char*)data, len);
if ( res != 0 )
{
printf( "failed decompress %d\n", res );
}
assert( expected == pDest_len );
return dst;
}
void* decompress_zz( int expected, const void *data, int len, int numBits=8 )
{
unsigned char *dst = (unsigned char*)malloc( expected );
unsigned int pDest_len = expected;
int res = zz_decompress(dst, &pDest_len, (const unsigned char*)data, len, numBits );
if ( res != 0 )
{
printf( "failed decompress %d\n", res );
}
assert( expected == pDest_len );
return dst;
}
void compress_bc1and3_i( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_rgb[2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
ep_rgb[0].push_back( blockbc1->c0[0] );
ep_rgb[0].push_back( blockbc1->c0[1] );
ep_rgb[1].push_back( blockbc1->c1[0] );
ep_rgb[1].push_back( blockbc1->c1[1] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
std::vector<unsigned char> all;
all.insert( all.end(), ep_rgb[0].begin(), ep_rgb[0].end() );
all.insert( all.end(), ep_rgb[1].begin(), ep_rgb[1].end() );
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() );
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() );
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() );
all.insert( all.end(), indices_a.begin(), indices_a.end() );
fwrite_compressed( &all[0], all.size(), f );
fclose( f );
}
void decompress_bc1and3_i( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_rgb[2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
ep_rgb[0] = &all[0];
ep_rgb[1] = &ep_rgb[0][totalblocks*2];
indices_rgb = &ep_rgb[1][totalblocks*2];
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
indices_a = &ep_a[1][totalblocks];
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0];
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1];
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0];
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1];
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( all );
free( hdr );
}
void compress_bc1and3_i2( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_rgb[2][2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
ep_rgb[0][0].push_back( blockbc1->c0[0] );
ep_rgb[0][1].push_back( blockbc1->c0[1] );
ep_rgb[1][0].push_back( blockbc1->c1[0] );
ep_rgb[1][1].push_back( blockbc1->c1[1] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
std::vector<unsigned char> all;
all.insert( all.end(), ep_rgb[0][0].begin(), ep_rgb[0][0].end() );
all.insert( all.end(), ep_rgb[0][1].begin(), ep_rgb[0][1].end() );
all.insert( all.end(), ep_rgb[1][0].begin(), ep_rgb[1][0].end() );
all.insert( all.end(), ep_rgb[1][1].begin(), ep_rgb[1][1].end() );
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() );
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() );
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() );
all.insert( all.end(), indices_a.begin(), indices_a.end() );
fwrite_compressed( &all[0], all.size(), f );
fclose( f );
}
void decompress_bc1and3_i2( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_rgb[2][2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
ep_rgb[0][0] = &all[0];
ep_rgb[0][1] = &ep_rgb[0][0][totalblocks];
ep_rgb[1][0] = &ep_rgb[0][1][totalblocks];
ep_rgb[1][1] = &ep_rgb[1][0][totalblocks];
indices_rgb = &ep_rgb[1][1][totalblocks];
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
indices_a = &ep_a[1][totalblocks];
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
blockbc1->c0[0] = ep_rgb[0][0][blockIndex];
blockbc1->c0[1] = ep_rgb[0][1][blockIndex];
blockbc1->c1[0] = ep_rgb[1][0][blockIndex];
blockbc1->c1[1] = ep_rgb[1][1][blockIndex];
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( all );
free( hdr );
}
void compress_bc1and3_i3( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_r[2],ep_b[2],ep_g[2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
unsigned short colour0 = blockbc1->c0[0] + blockbc1->c0[1] * 256;
unsigned short colour1 = blockbc1->c1[0] + blockbc1->c1[1] * 256;
unsigned char rgb[2][3];
rgb[0][0] = (colour0 >> ( 5 + 6 )) & ((1<<5)-1);
rgb[0][1] = (colour0 >> ( 5 )) & ((1<<6)-1);
rgb[0][2] = (colour0 >> ( 0 )) & ((1<<5)-1);
rgb[1][0] = (colour1 >> ( 5 + 6 )) & ((1<<5)-1);
rgb[1][1] = (colour1 >> ( 5 )) & ((1<<6)-1);
rgb[1][2] = (colour1 >> ( 0 )) & ((1<<5)-1);
ep_r[0].push_back( rgb[0][0] );
ep_g[0].push_back( rgb[0][1] );
ep_b[0].push_back( rgb[0][2] );
ep_r[1].push_back( rgb[1][0] );
ep_g[1].push_back( rgb[1][1] );
ep_b[1].push_back( rgb[1][2] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
std::vector< unsigned char > all5bit;
all5bit.insert( all5bit.end(), ep_r[0].begin(), ep_r[0].end() );
all5bit.insert( all5bit.end(), ep_r[1].begin(), ep_r[1].end() );
all5bit.insert( all5bit.end(), ep_b[0].begin(), ep_b[0].end() );
all5bit.insert( all5bit.end(), ep_b[1].begin(), ep_b[1].end() );
std::vector< unsigned char > all6bit;
all6bit.insert( all6bit.end(), ep_g[0].begin(), ep_g[0].end() );
all6bit.insert( all6bit.end(), ep_g[1].begin(), ep_g[1].end() );
std::vector< unsigned char > all8bit;
all8bit.insert( all8bit.end(), indices_rgb.begin(), indices_rgb.end() );
all8bit.insert( all8bit.end(), ep_a[0].begin(), ep_a[0].end() );
all8bit.insert( all8bit.end(), ep_a[1].begin(), ep_a[1].end() );
all8bit.insert( all8bit.end(), indices_a.begin(), indices_a.end() );
fwrite_compressed_zz( &all5bit[0], all5bit.size(), f, 5 );
fwrite_compressed_zz( &all6bit[0], all6bit.size(), f, 6 );
fwrite_compressed_zz( &all8bit[0], all8bit.size(), f, 8 );
fclose( f );
}
void decompress_bc1and3_i3( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_rgb[2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
ep_rgb[0] = &all[0];
ep_rgb[1] = &ep_rgb[0][totalblocks*2];
indices_rgb = &ep_rgb[1][totalblocks*2];
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
indices_a = &ep_a[1][totalblocks];
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0];
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1];
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0];
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1];
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( all );
free( hdr );
}
void compress_bc1and3_id( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_rgb[2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
ep_rgb[0].push_back( blockbc1->c0[0] );
ep_rgb[0].push_back( blockbc1->c0[1] );
ep_rgb[1].push_back( blockbc1->c1[0] );
ep_rgb[1].push_back( blockbc1->c1[1] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
deltaEncode( &ep_rgb[0][0], ep_rgb[0].size(), 8 );
deltaEncode( &ep_rgb[1][0], ep_rgb[1].size(), 8 );
deltaEncode( &indices_rgb[0], indices_rgb.size(), 8 );
if ( ep_a[0].size() )
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 );
if ( ep_a[1].size() )
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 );
if ( indices_a.size() )
deltaEncode( &indices_a[0], indices_a.size(), 8 );
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
std::vector<unsigned char> all;
all.insert( all.end(), ep_rgb[0].begin(), ep_rgb[0].end() );
all.insert( all.end(), ep_rgb[1].begin(), ep_rgb[1].end() );
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() );
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() );
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() );
all.insert( all.end(), indices_a.begin(), indices_a.end() );
fwrite_compressed( &all[0], all.size(), f );
fclose( f );
}
void decompress_bc1and3_id( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_rgb[2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
ep_rgb[0] = &all[0];
ep_rgb[1] = &ep_rgb[0][totalblocks*2];
indices_rgb = &ep_rgb[1][totalblocks*2];
deltaDecode( &ep_rgb[0][0], totalblocks*2, 8 );
deltaDecode( &ep_rgb[1][0], totalblocks*2, 8 );
deltaDecode( &indices_rgb[0], totalblocks*4, 8 );
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
indices_a = &ep_a[1][totalblocks];
deltaDecode( &ep_a[0][0], totalblocks, 8 );
deltaDecode( &ep_a[1][0], totalblocks, 8 );
deltaDecode( &indices_a[0], totalblocks*6, 8 );
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
blockbc1->c0[0] = ep_rgb[0][blockIndex*2+0];
blockbc1->c0[1] = ep_rgb[0][blockIndex*2+1];
blockbc1->c1[0] = ep_rgb[1][blockIndex*2+0];
blockbc1->c1[1] = ep_rgb[1][blockIndex*2+1];
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( all );
free( hdr );
}
void compress_bc1and3_i2d( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_rgb[2][2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
ep_rgb[0][0].push_back( blockbc1->c0[0] );
ep_rgb[0][1].push_back( blockbc1->c0[1] );
ep_rgb[1][0].push_back( blockbc1->c1[0] );
ep_rgb[1][1].push_back( blockbc1->c1[1] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
deltaEncode( &ep_rgb[0][0][0], ep_rgb[0][0].size(), 8 );
deltaEncode( &ep_rgb[0][1][0], ep_rgb[0][1].size(), 8 );
deltaEncode( &ep_rgb[1][0][0], ep_rgb[1][0].size(), 8 );
deltaEncode( &ep_rgb[1][1][0], ep_rgb[1][1].size(), 8 );
deltaEncode( &indices_rgb[0], indices_rgb.size(), 8 );
if ( ep_a[0].size() )
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 );
if ( ep_a[1].size() )
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 );
if ( indices_a.size() )
deltaEncode( &indices_a[0], indices_a.size(), 8 );
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
std::vector<unsigned char> all;
all.insert( all.end(), ep_rgb[0][0].begin(), ep_rgb[0][0].end() );
all.insert( all.end(), ep_rgb[0][1].begin(), ep_rgb[0][1].end() );
all.insert( all.end(), ep_rgb[1][0].begin(), ep_rgb[1][0].end() );
all.insert( all.end(), ep_rgb[1][1].begin(), ep_rgb[1][1].end() );
all.insert( all.end(), indices_rgb.begin(), indices_rgb.end() );
all.insert( all.end(), ep_a[0].begin(), ep_a[0].end() );
all.insert( all.end(), ep_a[1].begin(), ep_a[1].end() );
all.insert( all.end(), indices_a.begin(), indices_a.end() );
fwrite_compressed( &all[0], all.size(), f );
fclose( f );
}
void decompress_bc1and3_i2d( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_rgb[2][2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
ep_rgb[0][0] = &all[0];
ep_rgb[0][1] = &ep_rgb[0][0][totalblocks];
ep_rgb[1][0] = &ep_rgb[0][1][totalblocks];
ep_rgb[1][1] = &ep_rgb[1][0][totalblocks];
indices_rgb = &ep_rgb[1][1][totalblocks];
deltaDecode( &ep_rgb[0][0][0], totalblocks, 8 );
deltaDecode( &ep_rgb[0][1][0], totalblocks, 8 );
deltaDecode( &ep_rgb[1][0][0], totalblocks, 8 );
deltaDecode( &ep_rgb[1][1][0], totalblocks, 8 );
deltaDecode( &indices_rgb[0], totalblocks*4, 8 );
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
indices_a = &ep_a[1][totalblocks];
deltaDecode( &ep_a[0][0], totalblocks, 8 );
deltaDecode( &ep_a[1][0], totalblocks, 8 );
deltaDecode( &indices_a[0], totalblocks*6, 8 );
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
blockbc1->c0[0] = ep_rgb[0][0][blockIndex];
blockbc1->c0[1] = ep_rgb[0][1][blockIndex];
blockbc1->c1[0] = ep_rgb[1][0][blockIndex];
blockbc1->c1[1] = ep_rgb[1][1][blockIndex];
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( all );
free( hdr );
}
void compress_bc1and3_z( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > data;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int pos = data.size();
data.resize( pos + blockw*blockh*blockSize );
memcpy( &data[pos], initData[ml].pSysMem, blockw*blockh*blockSize );
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
fwrite_compressed( &data[0], data.size(), f );
fclose( f );
}
void decompress_bc1and3_z( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *all = (unsigned char *)decompress( totalsize, &hdr[1], len - sizeof(*hdr) );
{
int loc = 0;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
memcpy( (void*)initData[ml].pSysMem, &all[loc], (blockw * blockh) * blockSize );
loc += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
free( hdr );
free( all );
}
void compress_bc1and3_zz( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > data;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int pos = data.size();
data.resize( pos + blockw*blockh*blockSize );
memcpy( &data[pos], initData[ml].pSysMem, blockw*blockh*blockSize );
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
fwrite_compressed_zz( &data[0], data.size(), f );
fclose( f );
}
void decompress_bc1and3_zz( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
int totalsize = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
totalsize += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *all = (unsigned char *)decompress_zz( totalsize, &hdr[1], len - sizeof(*hdr) );
{
int loc = 0;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
memcpy( (void*)initData[ml].pSysMem, &all[loc], (blockw * blockh) * blockSize );
loc += (blockw * blockh) * blockSize;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
free( hdr );
free( all );
}
void rcEncode( rc_context *enc, rc_model *model, unsigned char *stream, int num )
{
for (int i=0; i<num; i++)
{
rc_encode_symbol (enc, model, stream[i]);
}
}
void rcDecode( rc_context *enc, rc_model *model, unsigned char *stream, int num )
{
for (int i=0; i<num; i++)
{
stream[i] = rc_decode_symbol (enc, model );
}
}
#if 0
void compress_bc1and3_i2( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData )
{
const int predictionbits[4] = { 5, 6, 5, 8 };
std::vector< unsigned char > ep_r[2];
std::vector< unsigned char > ep_g[2];
std::vector< unsigned char > ep_b[2];
std::vector< unsigned char > ep_a[2];
std::vector< unsigned char > indices_rgb;
std::vector< unsigned char > indices_a;
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
unsigned short colour0 = blockbc1->c0[0] + blockbc1->c0[1] * 256;
unsigned short colour1 = blockbc1->c1[0] + blockbc1->c1[1] * 256;
unsigned char r[2], g[2], b[2];
r[0] = (colour0 >> ( 5 + 6 )) & ((1<<5)-1);
g[0] = (colour0 >> ( 5 )) & ((1<<6)-1);
b[0] = (colour0 >> ( 0 )) & ((1<<5)-1);
r[1] = (colour1 >> ( 5 + 6 )) & ((1<<5)-1);
g[1] = (colour1 >> ( 5 )) & ((1<<6)-1);
b[1] = (colour1 >> ( 0 )) & ((1<<5)-1);
ep_r[0].push_back( r[0] );
ep_g[0].push_back( g[0] );
ep_b[0].push_back( b[0] );
ep_r[1].push_back( r[1] );
ep_g[1].push_back( g[1] );
ep_b[1].push_back( b[1] );
unsigned int bits = blockbc1->bits[0] + 256 * ((int)blockbc1->bits[1] + 256 * ((int)blockbc1->bits[2] + 256 * (int)blockbc1->bits[3]));
int indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (2*(4*i+j))) & 3;
}
}
indices_rgb.push_back( (indices[0+0][0+0]<<0) | (indices[0+0][0+1]<<2) | (indices[0+1][0+0]<<4) | (indices[0+1][0+1]<<6) );
indices_rgb.push_back( (indices[0+0][2+0]<<0) | (indices[0+0][2+1]<<2) | (indices[0+1][2+0]<<4) | (indices[0+1][2+1]<<6) );
indices_rgb.push_back( (indices[2+0][0+0]<<0) | (indices[2+0][0+1]<<2) | (indices[2+1][0+0]<<4) | (indices[2+1][0+1]<<6) );
indices_rgb.push_back( (indices[2+0][2+0]<<0) | (indices[2+0][2+1]<<2) | (indices[2+1][2+0]<<4) | (indices[2+1][2+1]<<6) );
}
if ( blockbc3a )
{
ep_a[0].push_back( blockbc3a->a[0] );
ep_a[1].push_back( blockbc3a->a[1] );
unsigned __int64 bits = blockbc3a->bits[0] + 256 * ((unsigned __int64)blockbc3a->bits[1] +
256 * ((unsigned __int64)blockbc3a->bits[2] +
256 * ((unsigned __int64)blockbc3a->bits[3] +
256 * ((unsigned __int64)blockbc3a->bits[4] +
256 * ((unsigned __int64)blockbc3a->bits[5]
)))));
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (3*(4*i+j))) & 7;
}
}
unsigned __int64 out_bits = 0;
out_bits |= (indices[0+0][0+0] << 0) | (indices[0+0][0+1] << 3) | (indices[0+1][0+0] << 6) | (indices[0+1][0+1] << 9);
out_bits |= (indices[0+0][2+0] << 12) | (indices[0+0][2+1] << 15) | (indices[0+1][2+0] << 18) | (indices[0+1][2+1] << 21);
out_bits |= (indices[2+0][0+0] << 24) | (indices[2+0][0+1] << 27) | (indices[2+1][0+0] << 30) | (indices[2+1][0+1] << 33);
out_bits |= (indices[2+0][2+0] << 36) | (indices[2+0][2+1] << 39) | (indices[2+1][2+0] << 42) | (indices[2+1][2+1] << 45);
indices_a.push_back( (out_bits>>0) & 0xff );
indices_a.push_back( (out_bits>>8) & 0xff );
indices_a.push_back( (out_bits>>16) & 0xff );
indices_a.push_back( (out_bits>>24) & 0xff );
indices_a.push_back( (out_bits>>32) & 0xff );
indices_a.push_back( (out_bits>>40) & 0xff );
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
deltaEncode( &ep_r[0][0], ep_r[0].size(), 5 );
deltaEncode( &ep_r[1][0], ep_r[1].size(), 5 );
deltaEncode( &ep_g[0][0], ep_g[0].size(), 6 );
deltaEncode( &ep_g[1][0], ep_g[1].size(), 6 );
deltaEncode( &ep_b[0][0], ep_b[0].size(), 5 );
deltaEncode( &ep_b[1][0], ep_b[1].size(), 5 );
if ( ep_a[0].size() )
deltaEncode( &ep_a[0][0], ep_a[0].size(), 8 );
if ( ep_a[1].size() )
deltaEncode( &ep_a[1][0], ep_a[1].size(), 8 );
FILE *f = fopen( filename, "wb" );
fwrite( &desc, 1, sizeof(DDSLoadDesc), f );
rc_context rcEnc;
rc_encoder_init( &rcEnc, f );
rc_model rc_m_r, rc_m_g, rc_m_b, rc_m_a;
rc_model rc_m_indices_rgb, rc_m_indices_a;
rc_model_init( &rc_m_r, 1<<5, NULL, 1 );
rc_model_init( &rc_m_g, 1<<6, NULL, 1 );
rc_model_init( &rc_m_b, 1<<5, NULL, 1 );
rc_model_init( &rc_m_a, 1<<8, NULL, 1 );
rc_model_init( &rc_m_indices_rgb, 1<<8, NULL, 1 );
rc_model_init( &rc_m_indices_a, 1<<8, NULL, 1 );
if ( ep_r[0].size() )
rcEncode( &rcEnc, &rc_m_r, &ep_r[0][0], ep_r[0].size() );
if ( ep_r[1].size() )
rcEncode( &rcEnc, &rc_m_r, &ep_r[1][0], ep_r[1].size() );
if ( ep_g[0].size() )
rcEncode( &rcEnc, &rc_m_g, &ep_g[0][0], ep_g[0].size() );
if ( ep_g[1].size() )
rcEncode( &rcEnc, &rc_m_g, &ep_g[1][0], ep_g[1].size() );
if ( ep_b[0].size() )
rcEncode( &rcEnc, &rc_m_b, &ep_b[0][0], ep_b[0].size() );
if ( ep_b[1].size() )
rcEncode( &rcEnc, &rc_m_b, &ep_b[1][0], ep_b[1].size() );
if ( indices_rgb.size() )
rcEncode( &rcEnc, &rc_m_indices_rgb, &indices_rgb[0], indices_rgb.size() );
if ( ep_a[0].size() )
rcEncode( &rcEnc, &rc_m_a, &ep_a[0][0], ep_a[0].size() );
if ( ep_a[1].size() )
rcEncode( &rcEnc, &rc_m_a, &ep_a[1][0], ep_a[1].size() );
if ( indices_a.size() )
rcEncode( &rcEnc, &rc_m_indices_a, &indices_a[0], indices_a.size() );
rc_encoder_done (&rcEnc);
rc_model_done( &rc_m_r );
rc_model_done( &rc_m_g );
rc_model_done( &rc_m_b );
rc_model_done( &rc_m_a );
rc_model_done( &rc_m_indices_rgb );
rc_model_done( &rc_m_indices_a );
fclose( f );
}
void decompress_bc1and3_i2( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
int totalblocks = 0;
{
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
totalblocks += blockw * blockh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
unsigned char *ep_r[2];
unsigned char *ep_g[2];
unsigned char *ep_b[2];
unsigned char *ep_a[2];
unsigned char *indices_rgb;
unsigned char *indices_a;
ep_r[0] = (unsigned char*)&hdr[1];
ep_r[1] = &ep_r[0][totalblocks];
ep_g[0] = &ep_r[1][totalblocks];
ep_g[1] = &ep_g[0][totalblocks];
ep_b[0] = &ep_g[1][totalblocks];
ep_b[1] = &ep_b[0][totalblocks];
indices_rgb = &ep_b[1][totalblocks];
deltaDecode( &ep_r[0][0], totalblocks, 5 );
deltaDecode( &ep_r[1][0], totalblocks, 5 );
deltaDecode( &ep_g[0][0], totalblocks, 6 );
deltaDecode( &ep_g[1][0], totalblocks, 6 );
deltaDecode( &ep_b[0][0], totalblocks, 5 );
deltaDecode( &ep_b[1][0], totalblocks, 5 );
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
ep_a[0] = &indices_rgb[totalblocks*4];
ep_a[1] = &ep_a[0][totalblocks];
deltaDecode( &ep_a[0][0], totalblocks, 8 );
deltaDecode( &ep_a[1][0], totalblocks, 8 );
indices_a = &ep_a[1][totalblocks];
}
else
{
ep_a[0] = 0;
ep_a[1] = 0;
indices_a = 0;
}
int curw = desc.width;
int curh = desc.height;
int blockIndex = 0;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isdxt1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isdxt1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
if ( blockbc1 )
{
unsigned short colour0 = (ep_r[0][blockIndex]) << (5+6) |
(ep_g[0][blockIndex]) << (5) |
(ep_b[0][blockIndex]);
unsigned short colour1 = (ep_r[1][blockIndex]) << (5+6) |
(ep_g[1][blockIndex]) << (5) |
(ep_b[1][blockIndex]);
blockbc1->c0[0] = colour0 & 0xff;
blockbc1->c0[1] = colour0 / 256;
blockbc1->c1[0] = colour1 & 0xff;
blockbc1->c1[1] = colour1 / 256;
unsigned int bits = indices_rgb[blockIndex*4+0] + 256 * ((unsigned int)indices_rgb[blockIndex*4+1] + 256 * ((unsigned int)indices_rgb[blockIndex*4+2] + 256 * (unsigned int)indices_rgb[blockIndex*4+3]));
static int remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
int indices[4][4];
unsigned int out_bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*2)) & 3;
out_bits |= indices[i][j] << (2*(4*i+j));
}
}
blockbc1->bits[0] = (out_bits>>0) & 0xff;
blockbc1->bits[1] = (out_bits>>8) & 0xff;
blockbc1->bits[2] = (out_bits>>16) & 0xff;
blockbc1->bits[3] = (out_bits>>24) & 0xff;
}
if ( blockbc3a )
{
blockbc3a->a[0] = ep_a[0][blockIndex];
blockbc3a->a[1] = ep_a[1][blockIndex];
unsigned __int64 bits = indices_a[blockIndex*6+0] + 256 * ((unsigned __int64)indices_a[blockIndex*6+1] +
256 * ((unsigned __int64)indices_a[blockIndex*6+2] +
256 * ((unsigned __int64)indices_a[blockIndex*6+3] +
256 * ((unsigned __int64)indices_a[blockIndex*6+4] +
256 * ((unsigned __int64)indices_a[blockIndex*6+5]
)))));
static unsigned __int64 remap[4][4] =
{
{ 0, 1, 4, 5 },
{ 2, 3, 6, 7 },
{ 8, 9, 12, 13 },
{ 10, 11, 14, 15 },
};
unsigned __int64 out_bits = 0;
unsigned __int64 indices[4][4];
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
indices[i][j] = (bits >> (remap[i][j]*3)) & 7;
out_bits |= (unsigned __int64)indices[i][j] << (3*(4*i+j));
}
}
blockbc3a->bits[0] = (out_bits>>0) & 0xff;
blockbc3a->bits[1] = (out_bits>>8) & 0xff;
blockbc3a->bits[2] = (out_bits>>16) & 0xff;
blockbc3a->bits[3] = (out_bits>>24) & 0xff;
blockbc3a->bits[4] = (out_bits>>32) & 0xff;
blockbc3a->bits[5] = (out_bits>>40) & 0xff;
}
blockIndex++;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
free( hdr );
}
#endif
void decompress_bc1_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
unsigned char decompressed[ 4096 * 8 * 3 ];
unsigned char imgchunks[2][(4096/4) * 2 * 3];
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
assert( desc.width <= 4096 );
rc_context rciindicesEnc;
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] );
rc_model rciindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rciindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rciindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rciindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rciindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rcTestModel;
rc_model_init( &rcTestModel, 256, NULL, 1 );
rc_model rccolmodel[6][2][3];
int initialfreq[256*2];
for (int j=0; j<2; j++)
{
for (int c=0; c<3; c++)
{
int bits = c == 1 ? 6 : 5;
for (int i = 0; i<((1<<bits)*2)+1; i++)
{
initialfreq[i] = 1+((1<<bits)/(((i+1)/2)+1));
}
rc_model_init( &rccolmodel[0][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[1][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[2][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[3][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[4][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
rc_model_init( &rccolmodel[5][j][c], ((1<<bits)*2)+1, initialfreq, 1 );
}
}
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * sizeof(dxtrgbblock) );
initData[ml].SysMemPitch = blockw * sizeof(dxtrgbblock);
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
crnlib::timer t;
t.start();
curw = desc.width;
curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxtrgbblock *blocks = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
{
int upy = (y-1);
int leftx = (x-1);
int upindex = ((upy&1) * blockw + x) * 3;
int leftindex = ((y&1) * blockw + leftx) * 3;
int diagindex = ((upy&1) * blockw + leftx) * 3;
int curindex = ((y&1) * blockw + x) * 3;
for (int r=0; r<2; r++)
{
int error = 0;
for (int c=0; c<3; c++)
{
int up = (upy >= 0) ? imgchunks[r][upindex+c] : 0;
int left = (leftx >= 0) ? imgchunks[r][leftindex+c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex+c] : 0;
int bits = (c == 1) ? 6 : 5;
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
predict += error;
if ( predict < 0 )
{
predict = 0;
}
if ( predict >= (1<<bits) )
{
predict = (1<<bits)-1;
}
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]);
int diff = UnZigZag( zzdiff );
int actual = predict - diff;
error = -diff;
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits)));
imgchunks[r][curindex+c] = actual;
}
}
unsigned short colour0 = (imgchunks[0][curindex+0]>>3) << (5+6) |
(imgchunks[0][curindex+1]>>2) << (5) |
(imgchunks[0][curindex+2]>>3);
unsigned short colour1 = (imgchunks[1][curindex+0]>>3) << (5+6) |
(imgchunks[1][curindex+1]>>2) << (5) |
(imgchunks[1][curindex+2]>>3);
blocks[x].c0[0] = colour0 & 0xff;
blocks[x].c0[1] = colour0 / 256;
blocks[x].c1[0] = colour1 & 0xff;
blocks[x].c1[1] = colour1 / 256;
}
unsigned short colour0 = blocks[x].c0[0] + blocks[x].c0[1] * 256;
unsigned short colour1 = blocks[x].c1[0] + blocks[x].c1[1] * 256;
unsigned char blockrgb[4][3];
extractRGB565( blockrgb[0], colour0 );
extractRGB565( blockrgb[1], colour1 );
if ( (colour0 > colour1) || !isdxt1 )
{
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
} else
{
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
}
#if 1
int errorR = 0;
int errorG = 0;
int errorB = 0;
int indices[4][4];
unsigned int bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zero[] = { 0,0,0 };
int upy = (y*4+i-1);
int leftx = (x*4+j-1);
int upindex = ((upy&7) * (blockw*4) + (x*4+j)) * 3;
int leftindex = (((y*4+i)&7) * (blockw*4) +leftx) * 3;
int diagindex = ((upy&7) * (blockw*4) + leftx) * 3;
int curindex = (((y*4+i)&7) * (blockw*4) + (x*4+j)) * 3;
unsigned char * left = leftx >= 0 ? &decompressed[leftindex] : zero;
unsigned char * up = upy >= 0 ? &decompressed[upindex] : left;
unsigned char * diag = (upy >= 0 && leftx >= 0) ? &decompressed[diagindex] : up;
int methodr, methodg, methodb;
int pr = predictGreen( up[0], left[0], diag[0], methodr );
int pg = predictGreen( up[1], left[1], diag[1], methodg );
int pb = predictGreen( up[2], left[2], diag[2], methodb );
int pindex = findClosestG( blockrgb, pg );
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
predictR += errorR;
predictG += errorG;
predictB += errorB;
int pindex2 = findClosestRGB( blockrgb, pr, pg, pb );
int pindex3 = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = methodg;
method = ((methodR*3 + methodG)*3 + methodB);
assert( method < (3*3*3) );
pindex = pindex3;
/*
int method;
int pg = predictGreen( up[1], left[1], diag[1], method );
int pindex = findClosestG( blockrgb, pg );*/
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rciindicesModel[method][pindex]);
bits |= actualIndex << (2*(4*i+j));
float diffr = ((float)blockrgb[actualIndex][0] - (float)blockrgb[pindex][0]);
float diffg = ((float)blockrgb[actualIndex][1] - (float)blockrgb[pindex][1]);
float diffb = ((float)blockrgb[actualIndex][2] - (float)blockrgb[pindex][2]);
//errorR = diffr;//blockrgb[actualIndex][0] - predictR;
//errorG = diffg;//blockrgb[actualIndex][1] - predictG;
//errorB = diffb;//blockrgb[actualIndex][2] - predictB;
//if ( i || j )
//{
// errorR = blockrgb[actualIndex][0] - predictR;
// errorG = blockrgb[actualIndex][1] - predictG;
// errorB = blockrgb[actualIndex][2] - predictB;
//}
indices[i][j] = actualIndex;
decompressed[curindex+0] = blockrgb[indices[i][j]][0];
decompressed[curindex+1] = blockrgb[indices[i][j]][1];
decompressed[curindex+2] = blockrgb[indices[i][j]][2];
}
}
blocks[x].bits[0] = bits & 0xff;
blocks[x].bits[1] = (bits>>8) & 0xff;
blocks[x].bits[2] = (bits>>16) & 0xff;
blocks[x].bits[3] = (bits>>24) & 0xff;
#else
blocks[x].bits[0] = rc_decode_symbol( &rciindicesEnc, &rcTestModel );
blocks[x].bits[1] = rc_decode_symbol( &rciindicesEnc, &rcTestModel );
blocks[x].bits[2] = rc_decode_symbol( &rciindicesEnc, &rcTestModel );
blocks[x].bits[3] = rc_decode_symbol( &rciindicesEnc, &rcTestModel );
#endif
int rll = rc_decode_symbol( &rciindicesEnc, &rcrllModel );
int index = ((y&1) * blockw + x)*3;
for (int r=0; r<rll; r++)
{
memcpy( &blocks[x+r+1], &blocks[x], sizeof(dxtrgbblock) );
memcpy( &imgchunks[0][index+(r+1)*3], &imgchunks[0][index+0], 3 );
memcpy( &imgchunks[1][index+(r+1)*3], &imgchunks[1][index+0], 3 );
for (int j=0; j<4; j++)
{
int dstindex = (((y*4+j)&7) * (blockw*4) + (x+r+1)*4) * 3;
int curindex = (((y*4+j)&7) * (blockw*4) + (x*4)) * 3;
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*3 );
}
}
x += rll;
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
t.stop();
printf( "%d ms to decompress\n", t.get_elapsed_ms() );
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rciindicesModel[i][0]);
rc_model_done (&rciindicesModel[i][1]);
rc_model_done (&rciindicesModel[i][2]);
rc_model_done (&rciindicesModel[i][3]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<3; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
free( hdr );
}
void decompress_bc3_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
static rgba imgchunks[2][(4096/4) * 2 ] = {0};
static rgba decompressed[4096 * 8] = {0};
const int predictionbits[4] = { 5, 6, 5, 8 };
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
rc_context rciindicesEnc;
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] );
rc_model rc_c_iindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rc_a_iindicesModel[3][8];
for (int i=0; i<(3); i++)
{
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rccolmodel[6][2][4];
int initialfreq[256*2+1];
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
int bits = predictionbits[c];
for (int i=0; i<(1<<bits); i++)
{
int mid = (1<<bits)/2;
int dist = i < mid ? i : ((1<<bits)-i-1);
initialfreq[i] = ((1<<bits)/(dist+1))+1;
}
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 );
}
}
int curw = desc.width;
int curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isdxt1 = true;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * sizeof(dxt5block) );
initData[ml].SysMemPitch = blockw * sizeof(dxt5block);
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
curw = desc.width;
curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isbc1 = false;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
for (int y=0; y<blockh; y++)
{
dxt5block *blocks = (dxt5block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch);
for (int x=0; x<blockw; x++)
{
unsigned char blockrgb[4][3];
unsigned char blocka[8];
// block end point encode
{
int cury = (y) % 2;
int upy = (y-1) % 2;
int leftx = (x-1);
int upindex = (upy * blockw + x);
int leftindex = (cury * blockw + leftx);
int diagindex = (upy * blockw + leftx);
int curindex = (cury * blockw + x);
int error = 0;
for (int r=0; r<2; r++)
{
for (int c=0; c<4; c++)
{
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0;
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0;
int bits = predictionbits[c];
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
predict += error;
if ( predict < 0 )
predict = 0;
if ( predict >= (1<<bits) )
predict = (1<<bits)-1;
#if PARANOID
int testactualf = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testup == up );
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testleft == left );
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testdiag == diag );
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testmethod == method );
int testpredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testpredict == predict );
int testactual = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
#endif
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]);
#if PARANOID
int test = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( test == c );
#endif
int actual = clockAdd( predict, zzdiff, bits );
#if PARANOID
assert( testactual == actual );
#endif
int diff = predict - actual;
error = -diff;
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits)));
#if PARANOID
assert( testactualf == actual );
#endif
imgchunks[r][curindex].c[c] = actual;
}
}
unsigned short colour0 = ((unsigned short)(imgchunks[0][curindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[0][curindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[0][curindex].c[2]>>3));
unsigned short colour1 = ((unsigned short)(imgchunks[1][curindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[1][curindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[1][curindex].c[2]>>3));
blocks[x].rgb.c0[0] = colour0 & 0xff;
blocks[x].rgb.c0[1] = colour0 / 256;
blocks[x].rgb.c1[0] = colour1 & 0xff;
blocks[x].rgb.c1[1] = colour1 / 256;
blocks[x].a.a[0] = imgchunks[0][curindex].a;
blocks[x].a.a[1] = imgchunks[1][curindex].a;
extractRGB565( blockrgb[0], colour0 );
extractRGB565( blockrgb[1], colour1 );
if ( (colour0 > colour1) || !isbc1 )
{
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
} else
{
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
}
blocka[0] = blocks[x].a.a[0];
blocka[1] = blocks[x].a.a[1];
if ( blocka[0] > blocka[1] )
{
generate6AlphaSet( blocka, blocka[0], blocka[1] );
}
else
{
generate4AlphaSet( blocka, blocka[0], blocka[1] );
}
}
if ( 1 )
{
#if PARANOID
int testc00 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc01 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc10 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc11 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testc00 == blocks[x].rgb.c0[0] );
assert( testc01 == blocks[x].rgb.c0[1] );
assert( testc10 == blocks[x].rgb.c1[0] );
assert( testc11 == blocks[x].rgb.c1[1] );
#endif
unsigned int bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros;
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = ((methodR * 3 + methodG)*3 + methodB);
assert( method < (3*3*3) );
#if PARANOID
int testUpR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testUpR == up[0] );
int testLeftR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testLeftR == left[0] );
int testDiagR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testDiagR == diag[0] );
int testMethodR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testMethodR == methodR );
int testPredictR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testPredictR == predictR );
int testMethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testMethod == method );
int testPredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testPredict == pindex );
#endif
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex] );
#if PARANOID
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testi == i );
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testj == j );
int testr = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testg = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testb = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testr == blockrgb[actualIndex][0] );
assert( testg == blockrgb[actualIndex][1] );
assert( testb == blockrgb[actualIndex][2] );
#endif
bits |= actualIndex << (2*(4*i+j));
int curindex = (cury * (blockw*4) + (x*4+j));
decompressed[curindex].r = blockrgb[actualIndex][0];
decompressed[curindex].g = blockrgb[actualIndex][1];
decompressed[curindex].b = blockrgb[actualIndex][2];
}
}
blocks[x].rgb.bits[0] = bits & 0xff;
blocks[x].rgb.bits[1] = (bits>>8) & 0xff;
blocks[x].rgb.bits[2] = (bits>>16) & 0xff;
blocks[x].rgb.bits[3] = (bits>>24) & 0xff;
}
if ( 1 )
{
unsigned __int64 bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up;
int method;
int predict = jpeglsPredictor( up[3], left[3], diag[3], method );
int pindex = findClosestA( blocka, predict );
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex] );
bits |= (unsigned __int64)actualIndex << (3*(4*i+j));
int curindex = ((y*4+i) * (blockw*4) + (x*4+j));
decompressed[curindex].a = blocka[actualIndex];
}
}
blocks[x].a.bits[0] = bits & 0xff;
blocks[x].a.bits[1] = (bits>>8) & 0xff;
blocks[x].a.bits[2] = (bits>>16) & 0xff;
blocks[x].a.bits[3] = (bits>>24) & 0xff;
blocks[x].a.bits[4] = (bits>>32) & 0xff;
blocks[x].a.bits[5] = (bits>>40) & 0xff;
}
if ( 1 )
{
int index = (y * blockw + x);
int rll = rc_decode_symbol (&rciindicesEnc, &rcrllModel);
for (int r=0; r<rll; r++)
{
memcpy( &blocks[x+r+1], &blocks[x], sizeof(blocks[0]) );
memcpy( &imgchunks[0][index+(r+1)], &imgchunks[0][index+0], 4 );
memcpy( &imgchunks[1][index+(r+1)], &imgchunks[1][index+0], 4 );
for (int j=0; j<4; j++)
{
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4);
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4));
// int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4);
// int curindex = ((y*4+j) * (blockw*4) + (x*4));
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 );
}
}
x += rll;
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rc_c_iindicesModel[i][0]);
rc_model_done (&rc_c_iindicesModel[i][1]);
rc_model_done (&rc_c_iindicesModel[i][2]);
rc_model_done (&rc_c_iindicesModel[i][3]);
}
for (int i=0; i<(3); i++)
{
rc_model_done (&rc_a_iindicesModel[i][0]);
rc_model_done (&rc_a_iindicesModel[i][1]);
rc_model_done (&rc_a_iindicesModel[i][2]);
rc_model_done (&rc_a_iindicesModel[i][3]);
rc_model_done (&rc_a_iindicesModel[i][4]);
rc_model_done (&rc_a_iindicesModel[i][5]);
rc_model_done (&rc_a_iindicesModel[i][6]);
rc_model_done (&rc_a_iindicesModel[i][7]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
}
void decompress_bc1and3_lcct( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData )
{
rgba *imgchunks[2];//[(4096/4) * 2 ] = {0};
rgba *decompressed;//[4096 * 8] = {0};
const int predictionbits[4] = { 5, 6, 5, 8 };
int len;
DDSLoadDesc* hdr = (DDSLoadDesc*)readFile( filename, len );
desc = *hdr;
imgchunks[0] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 );
imgchunks[1] = (rgba*)malloc( sizeof(rgba) * desc.width * 2 );
decompressed = (rgba*)malloc( sizeof(rgba) * desc.width * 8 );
rc_context rciindicesEnc;
rc_decoder_init( &rciindicesEnc, (unsigned char*)&hdr[1] );
rc_model rc_c_iindicesModel[3*3*3][4];
for (int i=0; i<(3*3*3); i++)
{
rc_model_init( &rc_c_iindicesModel[i][0], 4, iFreq0, 1 );
rc_model_init( &rc_c_iindicesModel[i][1], 4, iFreq1, 1 );
rc_model_init( &rc_c_iindicesModel[i][2], 4, iFreq2, 1 );
rc_model_init( &rc_c_iindicesModel[i][3], 4, iFreq3, 1 );
}
rc_model rc_a_iindicesModel[3][8];
for (int i=0; i<(3); i++)
{
rc_model_init( &rc_a_iindicesModel[i][0], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][1], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][2], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][3], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][4], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][5], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][6], 8, NULL, 1 );
rc_model_init( &rc_a_iindicesModel[i][7], 8, NULL, 1 );
}
rc_model rcrllModel;
rc_model_init( &rcrllModel, 8, NULL, 1 );
rc_model rccolmodel[6][2][4];
int initialfreq[256*2+1];
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
int bits = predictionbits[c];
for (int i=0; i<(1<<bits); i++)
{
int mid = (1<<bits)/2;
int dist = i < mid ? i : ((1<<bits)-i-1);
initialfreq[i] = ((1<<bits)/(dist+1))+1;
}
rc_model_init( &rccolmodel[0][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[1][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[2][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[3][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[4][j][c], 1<<bits, NULL, 1 );
rc_model_init( &rccolmodel[5][j][c], 1<<bits, NULL, 1 );
}
}
int curw = desc.width;
int curh = desc.height;
curw = desc.width;
curh = desc.height;
for (int ml=0; ml<desc.mips; ml++)
{
bool isbc1 = (desc.format == DXGI_FORMAT_BC1_UNORM);
int blockSize = isbc1 ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
initData[ml].pSysMem = malloc( blockw * blockh * blockSize );
initData[ml].SysMemPitch = blockw * blockSize;
for (int y=0; y<blockh; y++)
{
for (int x=0; x<blockw; x++)
{
if ( x == 342 )
printf("");
dxtrgbblock *blockbc1;
bc3block *blockbc3a;
if ( isbc1 )
{
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc3a = NULL;
}
else
{
blockbc3a = (bc3block*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
blockbc1 = (dxtrgbblock*)((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize)+8);
}
unsigned char blockrgb[4][3];
unsigned char blocka[8];
int curblocky = (y) % 2;
int curblockindex = (curblocky * blockw + x);
// block end point encode
{
int numc = blockbc3a ? 4 : 3;
int upy = (y-1) % 2;
int leftx = (x-1);
int upindex = (upy * blockw + x);
int leftindex = (curblocky * blockw + leftx);
int diagindex = (upy * blockw + leftx);
int error = 0;
for (int r=0; r<2; r++)
{
for (int c=0; c<numc; c++)
{
int left = leftx >= 0 ? imgchunks[r][leftindex].c[c] : 0;
int up = upy >= 0 ? imgchunks[r][upindex].c[c] : 0;
int diag = (upy >= 0 && leftx >= 0) ? imgchunks[r][diagindex].c[c] : 0;
int bits = predictionbits[c];
up >>= (8-bits);
left >>= (8-bits);
diag >>= (8-bits);
int method;
int predict = jpeglsPredictor( up, left, diag, method );
predict += error;
if ( predict < 0 )
predict = 0;
if ( predict >= (1<<bits) )
predict = (1<<bits)-1;
#if PARANOID
int testactualf = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testup == up );
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testleft == left );
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testdiag == diag );
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testmethod == method );
int testpredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testpredict == predict );
int testactual = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
#endif
int zzdiff = rc_decode_symbol (&rciindicesEnc, &rccolmodel[method][r][c]);
#if PARANOID
int test = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( test == c );
#endif
int actual = clockAdd( predict, zzdiff, bits );
#if PARANOID
assert( testactual == actual );
#endif
int diff = predict - actual;
error = -diff;
actual = (actual << (8-bits)) | (actual >> (bits-(8-bits)));
#if PARANOID
assert( testactualf == actual );
#endif
imgchunks[r][curblockindex].c[c] = actual;
}
}
}
if ( blockbc1 )
{
unsigned short colour0 = ((unsigned short)(imgchunks[0][curblockindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[0][curblockindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[0][curblockindex].c[2]>>3));
unsigned short colour1 = ((unsigned short)(imgchunks[1][curblockindex].c[0]>>3) << (5+6)) |
((unsigned short)(imgchunks[1][curblockindex].c[1]>>2) << (5)) |
((unsigned short)(imgchunks[1][curblockindex].c[2]>>3));
blockbc1->c0[0] = colour0 & 0xff;
blockbc1->c0[1] = colour0 / 256;
blockbc1->c1[0] = colour1 & 0xff;
blockbc1->c1[1] = colour1 / 256;
extractRGB565( blockrgb[0], colour0 );
extractRGB565( blockrgb[1], colour1 );
if ( (colour0 > colour1) || (!isbc1) )
{
generate4ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
} else
{
generate3ColourSet( blockrgb[2], blockrgb[3], blockrgb[0], blockrgb[1] );
}
#if PARANOID
int testc00 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc01 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc10 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testc11 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testc00 == blockbc1->c0[0] );
assert( testc01 == blockbc1->c0[1] );
assert( testc10 == blockbc1->c1[0] );
assert( testc11 == blockbc1->c1[1] );
#endif
unsigned int bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : zeros;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : zeros;
int methodR, methodG, methodB ;
int predictR = jpeglsPredictor( up[0], left[0], diag[0], methodR );
int predictG = jpeglsPredictor( up[1], left[1], diag[1], methodG );
int predictB = jpeglsPredictor( up[2], left[2], diag[2], methodB );
int pindex = findClosestRGB( blockrgb, predictR, predictG, predictB );
int method = ((methodR * 3 + methodG)*3 + methodB);
assert( method < (3*3*3) );
#if PARANOID
int testUpR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testUpR == up[0] );
int testLeftR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testLeftR == left[0] );
int testDiagR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testDiagR == diag[0] );
int testMethodR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testMethodR == methodR );
int testPredictR = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testPredictR == predictR );
int testMethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testMethod == method );
int testPredict = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testPredict == pindex );
#endif
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_c_iindicesModel[method][pindex] );
#if PARANOID
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testi == i );
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testj == j );
int testr = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testg = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testb = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testr == blockrgb[actualIndex][0] );
assert( testg == blockrgb[actualIndex][1] );
assert( testb == blockrgb[actualIndex][2] );
#endif
bits |= actualIndex << (2*(4*i+j));
int curindex = (cury * (blockw*4) + (x*4+j));
decompressed[curindex].r = blockrgb[actualIndex][0];
decompressed[curindex].g = blockrgb[actualIndex][1];
decompressed[curindex].b = blockrgb[actualIndex][2];
}
}
blockbc1->bits[0] = bits & 0xff;
blockbc1->bits[1] = (bits>>8) & 0xff;
blockbc1->bits[2] = (bits>>16) & 0xff;
blockbc1->bits[3] = (bits>>24) & 0xff;
}
if ( blockbc3a )
{
#if PARANOID
int testa0 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testa1 = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testa0 == imgchunks[0][curblockindex].a );
assert( testa1 == imgchunks[1][curblockindex].a );
#endif
blockbc3a->a[0] = imgchunks[0][curblockindex].a;
blockbc3a->a[1] = imgchunks[1][curblockindex].a;
blocka[0] = imgchunks[0][curblockindex].a;
blocka[1] = imgchunks[1][curblockindex].a;
if ( blocka[0] > blocka[1] )
{
generate6AlphaSet( blocka, blocka[0], blocka[1] );
}
else
{
generate4AlphaSet( blocka, blocka[0], blocka[1] );
}
unsigned __int64 bits = 0;
for (int i=0; i<4; i++)
{
for (int j=0; j<4; j++)
{
unsigned char zeros[4] = { 0, 0, 0, 0 };
int cury = (y*4+i) % 8;
int upy = (y*4+i-1) % 8;
int leftx = (x*4+j-1);
int upindex = (upy * (blockw*4) + (x*4+j));
int leftindex = (cury * (blockw*4) +leftx);
int diagindex = (upy * (blockw*4) + leftx);
unsigned char* left = leftx >= 0 ? decompressed[leftindex].c : zeros;
unsigned char* up = upy >= 0 ? decompressed[upindex].c : left;
unsigned char* diag = (upy >= 0 && leftx >= 0) ? decompressed[diagindex].c : up;
int method;
int predict = jpeglsPredictor( up[3], left[3], diag[3], method );
int pindex = findClosestA( blocka, predict );
#if PARANOID
int testup = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testleft = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testdiag = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testmethod = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testpindex = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testup == up[3] );
assert( testleft == left[3] );
assert( testdiag == diag[3] );
assert( testmethod == method );
assert( testpindex == pindex );
#endif
int actualIndex = rc_decode_symbol (&rciindicesEnc, &rc_a_iindicesModel[method][pindex] );
#if PARANOID
int testi = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
int testj = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testi == i );
assert( testj == j );
#endif
bits |= (unsigned __int64)actualIndex << (3*(4*i+j));
int curindex = (cury * (blockw*4) + (x*4+j));
decompressed[curindex].a = blocka[actualIndex];
#if PARANOID
int testa = rc_decode_symbol (&rciindicesEnc, &rccolmodel[0][0][3]);
assert( testa == decompressed[curindex].a );
#endif
}
}
blockbc3a->bits[0] = bits & 0xff;
blockbc3a->bits[1] = (bits>>8) & 0xff;
blockbc3a->bits[2] = (bits>>16) & 0xff;
blockbc3a->bits[3] = (bits>>24) & 0xff;
blockbc3a->bits[4] = (bits>>32) & 0xff;
blockbc3a->bits[5] = (bits>>40) & 0xff;
}
if ( 1 )
{
int rll = rc_decode_symbol (&rciindicesEnc, &rcrllModel);
for (int r=0; r<rll; r++)
{
char *src = ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + (x * blockSize));
char *dst = ((char*)initData[ml].pSysMem + y * initData[ml].SysMemPitch + ((x+r+1) * blockSize));
memcpy( dst, src, blockSize );
memcpy( &imgchunks[0][curblockindex+(r+1)], &imgchunks[0][curblockindex+0], 4 );
memcpy( &imgchunks[1][curblockindex+(r+1)], &imgchunks[1][curblockindex+0], 4 );
for (int j=0; j<4; j++)
{
int dstindex = (((y*4+j)%8) * (blockw*4) + (x+r+1)*4);
int curindex = (((y*4+j)%8) * (blockw*4) + (x*4));
// int dstindex = ((y*4+j) * (blockw*4) + (x+r+1)*4);
// int curindex = ((y*4+j) * (blockw*4) + (x*4));
memcpy( &decompressed[dstindex], &decompressed[curindex], 4*4 );
}
}
x += rll;
}
}
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
for (int i=0; i<(3*3*3); i++)
{
rc_model_done (&rc_c_iindicesModel[i][0]);
rc_model_done (&rc_c_iindicesModel[i][1]);
rc_model_done (&rc_c_iindicesModel[i][2]);
rc_model_done (&rc_c_iindicesModel[i][3]);
}
for (int i=0; i<(3); i++)
{
rc_model_done (&rc_a_iindicesModel[i][0]);
rc_model_done (&rc_a_iindicesModel[i][1]);
rc_model_done (&rc_a_iindicesModel[i][2]);
rc_model_done (&rc_a_iindicesModel[i][3]);
rc_model_done (&rc_a_iindicesModel[i][4]);
rc_model_done (&rc_a_iindicesModel[i][5]);
rc_model_done (&rc_a_iindicesModel[i][6]);
rc_model_done (&rc_a_iindicesModel[i][7]);
}
for (int j=0; j<2; j++)
{
for (int c=0; c<4; c++)
{
rc_model_done( &rccolmodel[0][j][c] );
rc_model_done( &rccolmodel[1][j][c] );
rc_model_done( &rccolmodel[2][j][c] );
rc_model_done( &rccolmodel[3][j][c] );
rc_model_done( &rccolmodel[4][j][c] );
rc_model_done( &rccolmodel[5][j][c] );
}
}
free( imgchunks[0] );
free( imgchunks[1] );
free( decompressed );
}
static int fileSize( const char *filename )
{
FILE *f = fopen( filename, "rb" );
if ( f )
{
fseek( f, 0, SEEK_END );
int len = ftell( f );
fclose( f );
return len;
}
return 0;
}
#include <string>
#include <vector>
#include <io.h>
#include <algorithm>
char fixseparator( char c )
{
return ( c == '/' ) ? '\\' : c;
}
void findFiles( std::vector< std::string > &files, const char *pattern )
{
std::string path = pattern;
std::transform( path.begin(), path.end(), path.begin(), fixseparator );
std::string::size_type pos = path.find_last_of( '\\' );
if ( pos != std::string::npos )
{
path = path.substr( 0, pos );
}
else
{
path = ".\\";
}
_finddata_t fi;
intptr_t fh = _findfirst( pattern, &fi );
if ( fh != -1 )
{
do
{
files.push_back( path + "\\" + fi.name );
}
while ( _findnext( fh, &fi ) == 0 );
_findclose( fh );
}
}
void readlist( std::vector< std::string > &files, const char *listfile )
{
FILE *f = fopen( listfile, "rb" );
if ( f )
{
char line[1024];
while (fgets(line, sizeof(line), f ))
{
char *tok = strtok( line, "\n\r" );
if ( tok )
{
files.push_back( tok );
}
}
fclose( f );
}
}
void WriteDDS( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA *data )
{
FILE *f = fopen( filename, "wb" );
if ( f )
{
DWORD magic = DDS_MAGIC;
DDS_HEADER hdr = { 0 };
hdr.dwSize = sizeof(DDS_HEADER);
hdr.dwWidth = desc.width;
hdr.dwHeight = desc.height;
hdr.dwMipMapCount = desc.mips;
hdr.dwHeaderFlags = DDS_HEADER_FLAGS_TEXTURE | DDS_HEADER_FLAGS_MIPMAP;
hdr.dwSurfaceFlags = DDS_SURFACE_FLAGS_TEXTURE;
hdr.ddspf = (desc.format == DXGI_FORMAT_BC3_UNORM) ? DDSPF_DXT5 : DDSPF_DXT1;
fwrite( &magic, 1, sizeof(magic), f );
fwrite( &hdr, 1, sizeof(hdr), f );
int curw = desc.width;
int curh = desc.height;
int blockSize = (desc.format == DXGI_FORMAT_BC3_UNORM) ? 16 : 8;
for (int i=0; i<desc.mips; i++)
{
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int size = blockw * blockh * blockSize;
fwrite( data[i].pSysMem, 1, size, f );
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
fclose( f );
}
}
std::string GetFile( const char *filename )
{
std::string path = filename;
std::transform( path.begin(), path.end(), path.begin(), fixseparator );
std::string::size_type pos = path.find_last_of( '\\' );
if ( pos != std::string::npos )
{
path = path.substr( pos );
}
pos = path.find_last_of( '.' );
if ( pos != std::string::npos )
{
path = path.substr( 0, pos );
}
return path;
}
std::string GetDir( const char *filename )
{
std::string path = filename;
std::transform( path.begin(), path.end(), path.begin(), fixseparator );
std::string::size_type pos = path.find_last_of( '\\' );
if ( pos != std::string::npos )
{
path = path.substr( 0, pos );
}
return path;
}
typedef void (*compress_f)( const char *filename, const DDSLoadDesc &desc, const D3D11_SUBRESOURCE_DATA * initData );
typedef void (*decompress_f)( const char *filename, DDSLoadDesc &desc, D3D11_SUBRESOURCE_DATA * initData );
struct compressiontest
{
const char *name;
const char *ext;
compress_f comp;
decompress_f decomp;
};
compressiontest compression_methods[] =
{
{ "deflatezz", "_fmtzz.zz", compress_bc1and3_zz, decompress_bc1and3_zz },
{ "reorder+deflate", "_fmtz.rd", compress_bc1and3_i, decompress_bc1and3_i },
//{ "reorder3+deflatezz", "_fmtz.r3zz", compress_bc1and3_i3, decompress_bc1and3_i3 },
{ "reorder2+deflate", "_fmtz.r2d", compress_bc1and3_i2, decompress_bc1and3_i2 },
{ "reorder+delta+deflate", "_fmtrd.rdd", compress_bc1and3_id, decompress_bc1and3_id },
{ "reorder2+delta+deflate", "_fmtrd.r2dd", compress_bc1and3_i2d, decompress_bc1and3_i2d },
{ "deflate", "_fmtz.z", compress_bc1and3_z, decompress_bc1and3_z },
{ "LCT", "_fmtlct.lct", compress_bc1and3_lcct, decompress_bc1and3_lcct },
{ NULL, NULL, NULL, NULL },
};
int _tmain(int argc, _TCHAR* argv[])
{
FILE *rep = fopen( "report.csv", "wb" );
std::vector< std::string > files;
findFiles( files, argv[1] );
//readlist( files, argv[1] );
for ( unsigned int f=0; f<files.size(); f++)
{
printf( "%s:\n", files[f].c_str() );
int len;
void *m = readFile( files[f].c_str(), len );
if ( m == NULL )
{
continue;
}
DDSLoadDesc desc;
D3D11_SUBRESOURCE_DATA initData[20];
HRESULT hr = CreateDDSTextureFromMemory( initData, (BYTE*)m, len, &desc, false );
printf( "%d x %d : %d mips : %d\n", desc.width, desc.height, desc.mips, desc.format );
if ( desc.width < 4 && desc.height < 4 )
continue;
/* if ( desc.format == DXGI_FORMAT_BC1_UNORM )
{
//kmeanstest( desc, initData );
//std::string fileoutkm = files[f] + ".kmout.dds";
//WriteDDS( fileoutkm.c_str(), desc, initData );
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt";
compress_bc1_lcct( lltfile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
decompress_bc1_lcct( lltfile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
int fs = fileSize( lltfile.c_str() );
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * sizeof(dxtrgbblock) );
if ( res )
{
printf( "failed to decompress correctly\n");
}
//assert( res == 0 );
totalPixels += curw*curh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
free( (void*)initData2[i].pSysMem );
}
float bpp = (fs*8.f) / totalPixels;
printf( "%d bytes %f bpp\n", fs, bpp);
}
else*/
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 )
{
if ( rep )
{
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d",//, %d, %d, %.2f\n",
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3",
desc.width, desc.height, desc.mips );
//fs_src, fs_dst, bpp );
}
compressiontest *ct = compression_methods;
while ( ct->name )
{
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + std::string( ct->ext );
ct->comp( ifile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
ct->decomp( ifile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + std::string( ct->ext ) + ".dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
int fs_src = fileSize( fileout.c_str() );
int fs_dst = fileSize( ifile.c_str() );
{
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize );
if ( res )
{
printf( "failed to decompress correctly\n");
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
totalPixels += curw*curh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
free( (void*)initData2[i].pSysMem );
}
float bpp = (fs_dst*8.f) / totalPixels;
printf( "%d bytes %f bpp\n", fs_dst, bpp);
if ( rep )
{
fprintf( rep, ", %d, %d, %.2f",
fs_src, fs_dst, bpp );
}
ct++;
}
if ( rep )
{
fprintf( rep, "\n" );
}
}
else
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 )
{
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtz.z";
compress_bc1and3_z( ifile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
decompress_bc1and3_z( ifile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtz.dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
int fs_src = fileSize( fileout.c_str() );
int fs_dst = fileSize( ifile.c_str() );
{
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize );
if ( res )
{
printf( "failed to decompress correctly\n");
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
totalPixels += curw*curh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
free( (void*)initData2[i].pSysMem );
}
float bpp = (fs_dst*8.f) / totalPixels;
printf( "%d bytes %f bpp\n", fs_dst, bpp);
if ( rep )
{
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n",
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3",
desc.width, desc.height, desc.mips,
fs_src, fs_dst, bpp );
}
}
else
if ( (desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM) && 1 )
{
std::string ifile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmti.i";
compress_bc1and3_i( ifile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
decompress_bc1and3_i( ifile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmti.dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
int fs_src = fileSize( fileout.c_str() );
int fs_dst = fileSize( ifile.c_str() );
{
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize );
if ( res )
{
printf( "failed to decompress correctly\n");
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
totalPixels += curw*curh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
free( (void*)initData2[i].pSysMem );
}
float bpp = (fs_dst*8.f) / totalPixels;
printf( "%d bytes %f bpp\n", fs_dst, bpp);
if ( rep )
{
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n",
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3",
desc.width, desc.height, desc.mips,
fs_src, fs_dst, bpp );
}
}
else
if ( desc.format == DXGI_FORMAT_BC1_UNORM || desc.format == DXGI_FORMAT_BC3_UNORM )
{
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt";
compress_bc1and3_lcct( lltfile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
decompress_bc1and3_lcct( lltfile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
int fs_src = fileSize( fileout.c_str() );
int fs_dst = fileSize( lltfile.c_str() );
{
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
int blockSize = desc.format == DXGI_FORMAT_BC1_UNORM ? 8 : 16;
int blockw = (curw+3)/4;
int blockh = (curh+3)/4;
int res = memcmp( initData2[i].pSysMem, initData[i].pSysMem, blockw * blockh * blockSize );
if ( res )
{
printf( "failed to decompress correctly\n");
}
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
}
}
assert( desc.height == desc2.height );
assert( desc.width == desc2.width );
assert( desc.mips == desc2.mips );
int curw = desc.width;
int curh = desc.height;
int totalPixels = 0;
for (int i=0; i<desc2.mips; i++)
{
totalPixels += curw*curh;
curw = curw/2;
curh = curh/2;
if (curw == 0)
curw = 1;
if (curh == 0)
curh = 1;
free( (void*)initData2[i].pSysMem );
}
float bpp = (fs_dst*8.f) / totalPixels;
printf( "%d bytes %f bpp\n", fs_dst, bpp);
if ( rep )
{
fprintf( rep, "\"%s\", \"%s\", %d, %d, %d, %d, %d, %.2f\n",
files[f].c_str(), desc.format == DXGI_FORMAT_BC1_UNORM ? "bc1" : "bc3",
desc.width, desc.height, desc.mips,
fs_src, fs_dst, bpp );
}
}
else
if ( desc.format == DXGI_FORMAT_BC3_UNORM )
{
//kmeanstest( desc, initData );
//std::string fileoutkm = files[f] + ".kmout.dds";
//WriteDDS( fileoutkm.c_str(), desc, initData );
std::string lltfile = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.llt";
compress_bc3_lcct( lltfile.c_str(), desc, initData );
DDSLoadDesc desc2;
D3D11_SUBRESOURCE_DATA initData2[20];
decompress_bc3_lcct( lltfile.c_str(), desc2, initData2 );
std::string fileout = std::string( argv[2] ) + GetFile( files[f].c_str() ) + "__fmtlct.dds";
WriteDDS( fileout.c_str(), desc2, initData2 );
}
free( m );
}
if ( rep )
{
fclose( rep );
}
return 0;
}
// simplehttp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include "json.h"
#include <time.h>
#include <map>
#include <string>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN (512*1024)
#define DEFAULT_PORT "27015"
std::map< std::string, std::string > traininfo;
void dumpmap( const char *filename )
{
FILE *f = fopen( filename, "wb" );
if ( f == NULL )
{
return;
}
std::map< std::string, std::string >::const_iterator b = traininfo.begin();
while ( b != traininfo.end() )
{
fprintf( f, "\"%s\",\"%s\"\n", b->first.c_str(), b->second.c_str() );
b++;
}
fclose( f );
}
std::string ParseString( char *&cursor )
{
bool inquote = false;
std::string out;
while ( *cursor )
{
if ( inquote )
{
if ( cursor[0] == '"' )
{
cursor++;
break;
}
else
{
out.push_back( cursor[0] );
}
}
else
{
if ( cursor[0] == '"' )
{
cursor++;
inquote = true;
continue;
}
else
if ( cursor[0] == ',' )
{
out.push_back( cursor[0] );
cursor++;
break;
}
else
{
out.push_back( cursor[0] );
}
}
cursor++;
}
return out;
}
void parsecsv( const char *filename )
{
FILE *f = fopen( filename, "rb" );
if ( f == NULL )
{
return;
}
char line[2048];
while( fgets( line, sizeof(line), f ) )
{
char *cursor = line;
std::string key = ParseString( cursor );
std::string comma = ParseString( cursor );
std::string value = ParseString( cursor );
traininfo[key] = value;
}
fclose( f );
}
std::string::size_type find_previous( std::string const &str, std::string const &needle, std::string::size_type pos )
{
if ( pos == std::string::npos )
return std::string::npos;
while ( pos >= 0 )
{
if ( str.substr( pos, needle.size() ) == needle )
return pos;
pos--;
}
return std::string::npos;
}
std::string::size_type matching_div( std::string const &str, std::string::size_type pos )
{
int level = 1;
while ( level )
{
std::string::size_type sdiv = str.find( "<div", pos+1 );
std::string::size_type ediv = str.find( "</div", pos+1 );
if ( sdiv < ediv )
{
level++;
pos = sdiv;
}
else
{
level--;
pos = ediv;
}
if ( pos > str.size() )
{
pos = std::string::npos;
break;
}
}
return pos;
}
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char *sendbufs[1] = { "GET http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes HTTP/1.1\n"
"Host: www.theguardian.com\n"
"Connection: close\n"
"User-Agent: Web-sniffer/1.0.46 (+http://web-sniffer.net/)\n"
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\n"
"Cache-Control: no-cache\n"
"Accept-Language: de,en;q=0.7,en-us;q=0.3\n"
"\n"};
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes";
//std::string loc = "http://www.theguardian.com/lifeandstyle/2011/sep/16/sweet-potato-figs-tuna-fishcake-recipes";
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/08/roast-lamb-cherry-strawberry-recipes";
//std::string loc = "http://www.theguardian.com/lifeandstyle/2013/sep/06/yotam-ottolenghi-brunch-recipes";
std::string loc = "http://www.theguardian.com/lifeandstyle/2013/aug/23/hugh-fearnley-whittingstall-garlic-recipes";
static char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
FILE *f = fopen( "hugh_recipes.html", "wb" );
FILE *contentsf = fopen( "hugh_contents.txt", "wb" );
fprintf( f, "<meta charset=\"utf-8\" />\n" );
int sectionid = 0;
do
{
//iResult = getaddrinfo("www.theguardian.com", "80", &hints, &result);
iResult = getaddrinfo("185.31.16.184", "80", &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
for (int index=0; index<1; index++)
{
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
printf( "%s\n", loc.c_str() );
std::string request = "GET " + loc + " HTTP/1.1\n"
"Host: www.theguardian.com\n"
"Connection: close\n"
"User-Agent: Web-sniffer/1.0.46 (+http://web-sniffer.net/)\n"
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7\n"
"Cache-Control: no-cache\n"
"Accept-Language: de,en;q=0.7,en-us;q=0.3\n"
"\n";
// Send an initial buffer
iResult = send( ConnectSocket, request.c_str(), request.size(), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
std::string output;
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
{
recvbuf[iResult] = 0;
output += recvbuf;
}
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
closesocket(ConnectSocket);
//<meta property="og:description" content="
//std::string::size_type title_start = output.find( "<title>" ) + 7;
//std::string::size_type title_end = output.find( "</title>" );
std::string::size_type title_start = output.find( "\"", output.find( "content", output.find( "property=\"og:title\"" ) ) )+1;
std::string::size_type title_end = output.find( "\"", title_start );
std::string title = output.substr( title_start, title_end-title_start );
if ( title.find( "Yotam Ottlenghi's" ) == 0 )
{
title = title.substr( sizeof("Yotam Ottlenghi's" ) );
}
if ( title.find( "Yotam Ottolenghi's" ) == 0 )
{
title = title.substr( sizeof("Yotam Ottolenghi's" ) );
}
if ( title.find( "The new vegetarian:" ) == 0 )
{
title = title.substr( sizeof("The new vegetarian:" ) );
}
if ( title == "The new vegetarian" || title == "Yotam Ottolenghi" )
{
title_start = output.find( "\"", output.find( "content", output.find( "property=\"og:description\"" ) ) )+1;
title_end = output.find( "\"", title_start );
title = output.substr( title_start, title_end-title_start );
}
std::string::size_type article_start = output.find( "article-wrapper" );
if ( article_start == std::string::npos )
{
Sleep( 10000 );
continue;
}
std::string::size_type article_end = matching_div( output, article_start );
std::string article = output.substr( article_start, article_end-article_start );
std::string::size_type Previous_start = output.find( "Previous" );
if ( Previous_start == std::string::npos )
return 0;
Previous_start = find_previous( output, "<a", Previous_start );
std::string::size_type href_start = output.find( "http", Previous_start );
std::string::size_type href_end = output.find( "\"", href_start );
std::string href = output.substr( href_start, href_end-href_start );
loc = href;
fprintf( contentsf, "<a href=\"#section%d\">%s</a><br>\n", sectionid, title.c_str() );
fprintf( f, "<section>\n<h1 id=\"#section%d\">%s</h1>\n<div id=\"%s\n</div></section>\n\n\n", sectionid, title.c_str(), article.c_str() );
fflush( contentsf );
fflush( f );
sectionid++;
}
freeaddrinfo(result);
//Sleep( 1000 + ( 5 + rand() % 5 ) );
} while ( true );
WSACleanup();
return 0;
}
typedef char LEXERCHAR;
enum
{
LT_Int,
LT_Float,
LT_String,
LT_QuotedString,
LT_EOF,
};
struct LexerToken
{
const LEXERCHAR *start;
int length;
int type;
int i;
float f;
};
struct LexerState
{
const LEXERCHAR *text;
const LEXERCHAR *end;
const LEXERCHAR *cursor;
};
enum
{
LS_OK,
LS_EOF,
};
inline static LEXERCHAR lexerNextChar( LexerState *state )
{
if ( state->cursor >= (state->end-1) )
return LEXERCHAR(0);
return state->cursor[1];
}
inline static LEXERCHAR lexerCurChar( LexerState *state )
{
if ( state->cursor >= state->end )
return LEXERCHAR(0);
return state->cursor[0];
}
static bool lexerIsAny( LEXERCHAR c, LEXERCHAR *chars )
{
while ( *chars )
{
if ( c == *chars )
return true;
chars++;
}
return false;
}
bool lexerIsEof( LexerState *state )
{
return state->cursor >= state->end;
}
static bool lexerIsDigit( LEXERCHAR c )
{
return (c>=LEXERCHAR('0') && c<=LEXERCHAR('9'));
}
static bool lexerIsAlpha( LEXERCHAR c )
{
return ((c>=LEXERCHAR('a') && c<=LEXERCHAR('z'))) || ((c>=LEXERCHAR('A') && c<=LEXERCHAR('Z'))) || lexerIsAny( c, "_" );
}
static bool lexerIsAlphaOrDigit( LEXERCHAR c )
{
return lexerIsAlpha(c) || lexerIsDigit(c);
}
static bool lexerIsOctalDigit( LEXERCHAR c )
{
return c >= LEXERCHAR('0') && c <= LEXERCHAR('7');
}
static bool lexerIsHexDigit( LEXERCHAR c )
{
return (c >= LEXERCHAR('0') && c <= LEXERCHAR('9')) ||
(c >= LEXERCHAR('a') && c <= LEXERCHAR('f')) ||
(c >= LEXERCHAR('A') && c <= LEXERCHAR('F'));
}
static bool lexerIsBinDigit( LEXERCHAR c )
{
return c >= LEXERCHAR('0') && c <= LEXERCHAR('1');
}
static bool lexerSkipWS( LexerState *state )
{
const LEXERCHAR *start = state->cursor;
while ( state->cursor < state->end && lexerIsAny( lexerCurChar(state), " \t\n\r" ) )
state->cursor++;
return state->cursor > start;
}
static void lexerSkipMultiLineComment( LexerState *state )
{
while ( state->cursor < state->end )
{
if ( lexerCurChar(state) == LEXERCHAR('*') && lexerNextChar(state) == LEXERCHAR('/') )
{
state->cursor+=2;
return;
}
state->cursor++;
}
}
static void lexerSkipSingleLineComment( LexerState *state )
{
while ( state->cursor < state->end )
{
if ( lexerCurChar(state) == LEXERCHAR('\n') )
{
state->cursor++;
return;
}
state->cursor++;
}
}
static int maxExponent = 511; /* Largest possible base 10 exponent. Any
* exponent larger than this will already
* produce underflow or overflow, so there's
* no need to worry about additional digits.
*/
static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
10., /* is 10^2^i. Used to convert decimal */
100., /* exponents into floating-point numbers. */
1.0e4,
1.0e8,
1.0e16,
1.0e32,
1.0e64,
1.0e128,
1.0e256
};
/*
*----------------------------------------------------------------------
*
* strtod --
*
* This procedure converts a floating-point number from an ASCII
* decimal representation to internal double-precision format.
*
* Results:
* The return value is the double-precision floating-point
* representation of the characters in string. If endPtr isn't
* NULL, then *endPtr is filled in with the address of the
* next character after the last one that was part of the
* floating-point number.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
double lexerStrtod(const char *string, const char *end)
{
int sign, expSign = 0;
double fraction, dblExp, *d;
register const char *p;
register int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
* part. Under normal circumstatnces, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
* large negative exponent could cause an
* unnecessary overflow on I alone). In this
* case, fracExp is incremented one for each
* dropped digit. */
int mantSize; /* Number of digits in mantissa. */
int decPt; /* Number of mantissa digits BEFORE decimal
* point. */
const char *pExp; /* Temporarily holds location of exponent
* in string. */
/*
* Strip off leading blanks and check for a sign.
*/
p = string;
if (*p == '-')
{
sign = 1;
p += 1;
} else
{
if (*p == '+')
{
p += 1;
}
sign = 0;
}
/*
* Count the number of digits in the mantissa (including the decimal
* point), and also locate the decimal point.
*/
decPt = -1;
for (mantSize = 0; ; mantSize += 1)
{
if ( p >= end )
break;
c = *p;
if (!isdigit(c))
{
if ((c != '.') || (decPt >= 0))
{
break;
}
decPt = mantSize;
}
p += 1;
}
/*
* Now suck up the digits in the mantissa. Use two integers to
* collect 9 digits each (this is faster than using floating-point).
* If the mantissa has more than 18 digits, ignore the extras, since
* they can't affect the value anyway.
*/
pExp = p;
p -= mantSize;
if (decPt < 0)
{
decPt = mantSize;
} else
{
mantSize -= 1; /* One of the digits was the point. */
}
if (mantSize > 18)
{
fracExp = decPt - 18;
mantSize = 18;
} else
{
fracExp = decPt - mantSize;
}
if (mantSize == 0)
{
fraction = 0.0;
p = string;
goto done;
} else
{
int frac1, frac2;
frac1 = 0;
for ( ; mantSize > 9; mantSize -= 1)
{
if ( p >= end )
break;
c = *p;
p += 1;
if (c == '.')
{
if ( p >= end )
break;
c = *p;
p += 1;
}
frac1 = 10*frac1 + (c - '0');
}
frac2 = 0;
for (; mantSize > 0; mantSize -= 1)
{
if ( p >= end )
break;
c = *p;
p += 1;
if (c == '.')
{
if ( p >= end )
break;
c = *p;
p += 1;
}
frac2 = 10*frac2 + (c - '0');
}
fraction = (1.0e9 * frac1) + frac2;
}
/*
* Skim off the exponent.
*/
p = pExp;
if (p<end && ((*p == 'E') || (*p == 'e')))
{
p += 1;
if (p<end && *p == '-')
{
expSign = 1;
p += 1;
} else
{
if (p<end && *p == '+')
{
p += 1;
}
expSign = 0;
}
if (p<end && !isdigit(LEXERCHAR(*p)))
{
p = pExp;
goto done;
}
while (p<end && isdigit(LEXERCHAR(*p)))
{
exp = exp * 10 + (*p - '0');
p += 1;
}
}
if (expSign)
{
exp = fracExp - exp;
} else {
exp = fracExp + exp;
}
/*
* Generate a floating-point number that represents the exponent.
* Do this by processing the exponent one bit at a time to combine
* many powers of 2 of 10. Then combine the exponent with the
* fraction.
*/
if (exp < 0)
{
expSign = 1;
exp = -exp;
} else
{
expSign = 0;
}
if (exp > maxExponent)
{
exp = maxExponent;
errno = ERANGE;
}
dblExp = 1.0;
for (d = powersOf10; exp != 0; exp >>= 1, d += 1)
{
if (exp & 01)
{
dblExp *= *d;
}
}
if (expSign)
{
fraction /= dblExp;
} else
{
fraction *= dblExp;
}
done:
if (sign)
{
return -fraction;
}
return fraction;
}
static bool lexerGetNumber( LexerToken *token, LexerState *state )
{
if ( !lexerIsDigit( lexerCurChar(state) ) )
return false;
token->type = LT_Int;
if ( lexerCurChar(state) == LEXERCHAR('0') )
{
if ( lexerIsAny( lexerNextChar(state), "xX" ) )
{
state->cursor += 2;
int i = 0;
while ( lexerIsHexDigit( lexerCurChar(state) ) )
{
i *= 16;
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('9') )
i += lexerCurChar(state) - LEXERCHAR('0');
if ( lexerCurChar(state) >= LEXERCHAR('a') && lexerCurChar(state) <= LEXERCHAR('f') )
i += (lexerCurChar(state) - LEXERCHAR('a')) + 10;
if ( lexerCurChar(state) >= LEXERCHAR('A') && lexerCurChar(state) <= LEXERCHAR('F') )
i += (lexerCurChar(state) - LEXERCHAR('A')) + 10;
state->cursor++;
}
token->length = state->cursor - token->start;
token->i = i;
token->f = i;
return true;
}
if ( lexerIsAny( lexerNextChar(state), "bB" ) )
{
state->cursor += 2;
int i = 0;
while ( lexerIsBinDigit( lexerCurChar(state) ) )
{
i *= 2;
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('1') )
i += lexerCurChar(state) - LEXERCHAR('0');
state->cursor++;
}
token->length = state->cursor - token->start;
token->i = i;
token->f = i;
return true;
}
if ( lexerIsOctalDigit( lexerNextChar(state) ) )
{
int i = 0;
while ( lexerIsOctalDigit( lexerCurChar(state) ) )
{
i *= 8;
if ( lexerCurChar(state) >= LEXERCHAR('0') && lexerCurChar(state) <= LEXERCHAR('7') )
i += lexerCurChar(state) - LEXERCHAR('0');
state->cursor++;
}
token->length = state->cursor - token->start;
token->i = i;
token->f = i;
return true;
}
if ( lexerNextChar(state) != '.' )
{
token->i = 0;
token->f = 0;
state->cursor++;
token->length = state->cursor - token->start;
return true;
}
}
int i = 0;
while ( lexerIsDigit( lexerCurChar(state) ) )
{
i*=10;
i += lexerCurChar(state) - LEXERCHAR('0');
state->cursor++;
}
token->i = i;
token->f = i;
if ( lexerCurChar(state) == LEXERCHAR('.') )
{
token->type = LT_Float;
state->cursor++;
while ( lexerIsDigit( lexerCurChar(state) ) )
{
state->cursor++;
}
if ( lexerIsAny( lexerCurChar(state), "eE" ) )
{
token->type = LT_Float;
state->cursor++;
if ( lexerCurChar(state) == LEXERCHAR('-') )
{
state->cursor++;
}
while ( lexerIsDigit( lexerCurChar(state) ) )
{
state->cursor++;
}
}
token->f = lexerStrtod( token->start, state->cursor );
token->i = token->f;
}
token->length = state->cursor - token->start;
return true;
}
int lexerGetToken( LexerToken *token, LexerState *state )
{
if ( lexerIsEof( state ) )
{
token->start = NULL;
token->length = 0;
token->type = LT_EOF;
return LS_EOF;
}
while ( 1 )
{
if ( lexerSkipWS( state ) )
continue;
if ( lexerCurChar( state ) == LEXERCHAR( '/' ) && lexerNextChar( state ) == LEXERCHAR( '*' ) )
{
lexerSkipMultiLineComment( state );
continue;
}
if ( lexerCurChar( state ) == LEXERCHAR( '/' ) && lexerNextChar( state ) == LEXERCHAR( '/' ) )
{
lexerSkipSingleLineComment( state );
continue;
}
break;
}
if ( lexerCurChar( state ) == LEXERCHAR( '+' ) || lexerCurChar( state ) == LEXERCHAR( '-' ) )
{
token->start = state->cursor;
token->length = 1;
state->cursor++;
if ( lexerGetNumber( token, state ) )
{
return LS_OK;
}
else
{
token->type = LT_String;
return LS_OK;
}
}
token->start = state->cursor;
token->type = LT_String;
if ( lexerGetNumber( token, state ) )
{
return LS_OK;
}
else
if ( lexerCurChar(state) == LEXERCHAR('\"') )
{
state->cursor++;
token->start = state->cursor;
token->type = LT_QuotedString;
while ( lexerCurChar(state) != LEXERCHAR('\"') )
{
state->cursor++;
}
token->length = state->cursor - token->start;
state->cursor++;
return LS_OK;
}
else
if ( lexerCurChar(state) == LEXERCHAR('$') && lexerIsAlpha( lexerNextChar(state) ) )
{
token->start = state->cursor;
token->type = LT_String;
state->cursor++;
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) )
{
state->cursor++;
}
token->length = state->cursor - token->start;
return LS_OK;
}
else
if ( lexerCurChar(state) == LEXERCHAR('%') && lexerIsAlpha( lexerNextChar(state) ) )
{
token->start = state->cursor;
token->type = LT_String;
state->cursor++;
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) )
{
state->cursor++;
}
token->length = state->cursor - token->start;
return LS_OK;
}
else
if ( lexerIsAlpha( lexerCurChar(state) ) )
{
token->start = state->cursor;
token->type = LT_String;
state->cursor++;
while ( lexerIsAlphaOrDigit( lexerCurChar(state) ) )
{
state->cursor++;
}
token->length = state->cursor - token->start;
return LS_OK;
}
else
{
token->start = state->cursor;
token->type = LT_String;
state->cursor++;
token->length = state->cursor - token->start;
return LS_OK;
}
}
int lexerGetLineNumber( LexerState *state )
{
int line = 0;
const LEXERCHAR *c = state->text;
while ( c < state->cursor )
{
line += (*c == LEXERCHAR('\n')) ? 1 : 0;
c++;
}
return line;
}
// simplehttp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include "json.h"
#include <time.h>
#include <map>
#include <string>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
#define DEFAULT_BUFLEN (512*1024)
#define DEFAULT_PORT "27015"
std::map< std::string, std::string > traininfo;
void dumpmap( const char *filename )
{
FILE *f = fopen( filename, "wb" );
if ( f == NULL )
{
return;
}
std::map< std::string, std::string >::const_iterator b = traininfo.begin();
while ( b != traininfo.end() )
{
fprintf( f, "\"%s\",\"%s\"\n", b->first.c_str(), b->second.c_str() );
b++;
}
fclose( f );
}
std::string ParseString( char *&cursor )
{
bool inquote = false;
std::string out;
while ( *cursor )
{
if ( inquote )
{
if ( cursor[0] == '"' )
{
cursor++;
break;
}
else
{
out.push_back( cursor[0] );
}
}
else
{
if ( cursor[0] == '"' )
{
cursor++;
inquote = true;
continue;
}
else
if ( cursor[0] == ',' )
{
out.push_back( cursor[0] );
cursor++;
break;
}
else
{
out.push_back( cursor[0] );
}
}
cursor++;
}
return out;
}
void parsecsv( const char *filename )
{
FILE *f = fopen( filename, "rb" );
if ( f == NULL )
{
return;
}
char line[2048];
while( fgets( line, sizeof(line), f ) )
{
char *cursor = line;
std::string key = ParseString( cursor );
std::string comma = ParseString( cursor );
std::string value = ParseString( cursor );
traininfo[key] = value;
}
fclose( f );
}
int __cdecl main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
// char *sendbufs[2] = { "GET http://ojp.nationalrail.co.uk/service/ldb/liveTrainsJson?departing=false&liveTrainsFrom=VIC&liveTrainsTo=WMA&serviceId=\n\n",
// "GET http://ojp.nationalrail.co.uk/service/ldb/liveTrainsJson?departing=false&liveTrainsFrom=WMA&liveTrainsTo=VIC&serviceId=\n\n" };
char *sendbufs[2] = { "GET http://connect.garmin.com/proxy/activity-service-1.1/gpx/activity/267265456?full=true", "GET http://connect.garmin.com/proxy/activity-service-1.1/gpx/activity/267265456?full=true" };
static char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
{
SOCKET Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (Socket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(38300);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.S_un.S_un_b.s_b1 = 127;
SockAddr.sin_addr.S_un.S_un_b.s_b2 = 0;
SockAddr.sin_addr.S_un.S_un_b.s_b3 = 0;
SockAddr.sin_addr.S_un.S_un_b.s_b4 = 1;
// Connect to server.
iResult = connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr));
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
return -1;
}
int flag = 1;
int result = setsockopt(ConnectSocket, /* socket affected */
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(char *) &flag, /* the cast is historical cruft */
sizeof(int)); /* length of option value */
//setsockopt( ConnectSocket, SOL_SOCKET, so_sendbuf
char *buffer = new char [1280*800*4];
char *bufferBlack = new char [1280*800*4];
memset( buffer, 0xff, 1280*800*4 );
memset( bufferBlack, 0, 1280*800*4 );
int alt = 0;
while ( 1 )
{
int nDataLength=recv(Socket,buffer,1000,0);
if ( buffer < 0 )
break;
//buffer[nDataLength] = 0;
int out = send(Socket,alt ? buffer : bufferBlack,1280*800*4,0);
alt = 1-alt;
printf( "%d\n", out );
}
return 0;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
SYSTEMTIME lastct;
GetLocalTime( &lastct );
lastct.wDayOfWeek--;
parsecsv( "trains.csv" );
do
{
SYSTEMTIME ct;
GetLocalTime( &ct );
if ( lastct.wDayOfWeek != ct.wDayOfWeek )
{
char backup[256];
sprintf( backup, "trains_%04d%02d%02d.csv", lastct.wYear, lastct.wMonth, lastct.wDay );
CopyFileA( "trains.csv", backup, TRUE );
}
lastct = ct;
if ( ct.wDayOfWeek < 1 || ct.wDayOfWeek > 5 )
{
//Sleep( 5 * 60 * 1000 );
//continue;
}
if ( !((ct.wHour >= 5 && ct.wHour < 8 ) || (ct.wHour >= 13 && ct.wHour <20)) )
{
//Sleep( 5 * 60 * 1000 );
//continue;
}
// Resolve the server address and port
//iResult = getaddrinfo("ojp.nationalrail.co.uk", "80", &hints, &result);
iResult = getaddrinfo("connect.garmin.com", "80", &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
for (int index=0; index<2; index++)
{
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
iResult = send( ConnectSocket, sendbufs[index], (int)strlen(sendbufs[index]), 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
recvbuf[iResult] = 0;
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
if ( recvbuflen )
{
json_value *jv = json_parse( recvbuf );
if ( jv )
{
json_value const &trains = (*jv)["trains"];
char timefmt[128];
sprintf( timefmt, "%04d%02d%02d", ct.wYear, ct.wMonth, ct.wDay );
for (unsigned int i=0; i<trains.u.array.length; i++)
{
json_value const &train = trains[i];
json_value const &flags = train[0];
json_value const &duetime = train[1];
json_value const &origin = train[2];
json_value const &delay = train[3];
std::string trainId = std::string(timefmt) + std::string(":") + std::string( duetime ) + std::string(":") + std::string( origin );
std::string d = std::string( flags ) + std::string( " : " ) + std::string( delay );
traininfo[trainId] = d;
}
json_value_free( jv );
}
printf("");
}
dumpmap( "trains.csv" );
// cleanup
closesocket(ConnectSocket);
}
freeaddrinfo(result);
Sleep( 1000 * 60 * ( 5 + rand() % 5 ) );
} while ( true );
WSACleanup();
return 0;
}
// mybc7.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define STB_DXT_IMPLEMENTATION
#include "stb_dxt.h"
#include "stb_image.h"
#include <algorithm>
#include "crn_win32_timer.h"
static int shapes_two[64*16] =
{
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1,
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1,
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1,
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1,
0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1,
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1,
0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1,
0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1,
1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0,
0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1,
0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1,
0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0,
0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1,
1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0,
0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0,
1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1,
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1,
1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1,
1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1,
1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1,
1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0,
0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1,
1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0,
1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0,
1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1,
0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
};
static int shapes_three[64*16] =
{
0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 2, 2,
0, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 0, 0, 2, 2,
0, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1, 1, 0, 0, 1, 1,
2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 1, 1, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1,
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2, 0, 0, 1, 1,
1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
1, 1, 2, 2, 0, 0, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 1, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2,
0, 1, 1, 2, 0, 1, 2, 2, 0, 0, 1, 1, 0, 0, 1, 1,
0, 1, 1, 2, 0, 1, 2, 2, 0, 1, 1, 2, 2, 0, 0, 1,
0, 1, 1, 2, 0, 1, 2, 2, 1, 1, 2, 2, 2, 2, 0, 0,
0, 1, 1, 2, 0, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 0,
0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2,
0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 2, 2,
0, 1, 1, 2, 2, 0, 0, 1, 1, 1, 2, 2, 0, 0, 2, 2,
1, 1, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, 1, 1, 1, 1,
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0,
0, 2, 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 2, 1, 0,
0, 2, 2, 2, 2, 2, 2, 1, 0, 1, 2, 2, 2, 2, 1, 0,
0, 1, 2, 2, 0, 0, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0,
0, 1, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 0, 1, 1, 0,
0, 0, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1,
0, 0, 0, 0, 2, 2, 2, 2, 0, 1, 1, 0, 1, 2, 2, 1,
0, 0, 2, 2, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
1, 1, 0, 2, 0, 1, 1, 0, 0, 1, 2, 2, 2, 0, 0, 0,
1, 1, 0, 2, 2, 0, 0, 2, 0, 1, 2, 2, 2, 2, 1, 1,
0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1, 2, 2, 2, 1,
0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 1, 1, 0, 1, 2, 0,
0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 1, 2, 0, 1, 2, 0,
1, 1, 2, 2, 0, 0, 1, 2, 0, 0, 2, 2, 0, 1, 2, 0,
1, 2, 2, 2, 0, 0, 1, 1, 0, 2, 2, 2, 0, 1, 2, 0,
0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 1,
1, 1, 1, 1, 1, 2, 0, 1, 2, 0, 1, 2, 2, 2, 0, 0,
2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 0, 1, 1, 1, 2, 2,
0, 0, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 0, 1, 1,
0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 2, 2,
1, 1, 2, 2, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 2, 2,
2, 2, 0, 0, 2, 2, 2, 2, 2, 1, 2, 1, 0, 0, 2, 2,
0, 0, 1, 1, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2,
0, 0, 2, 2, 0, 2, 2, 0, 0, 1, 0, 1, 0, 0, 0, 0,
0, 0, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1,
0, 0, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 1, 2, 1,
0, 0, 1, 1, 1, 2, 2, 1, 0, 1, 0, 1, 2, 1, 2, 1,
0, 1, 0, 1, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0,
0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
0, 1, 0, 1, 0, 2, 2, 2, 0, 0, 0, 2, 2, 1, 1, 2,
2, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
0, 2, 2, 2, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 2, 0, 1, 1, 0, 2, 1, 1, 2,
0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 1, 1, 2,
0, 1, 1, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0,
2, 2, 2, 2, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0,
2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 1, 1, 2,
0, 0, 0, 2, 0, 2, 2, 2, 0, 1, 0, 1, 0, 1, 1, 1,
0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 1,
0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1,
0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
};
#define REGION(s,x,y,si) s[((si)&3)*4+((si)>>2)*64+(x)+(y)*16]
static int shapeindex_to_compressed_indices_3[64*3] =
{
0, 3,15, 0, 3, 8, 0,15, 8, 0,15, 3,
0, 8,15, 0, 3,15, 0,15, 3, 0,15, 8,
0, 8,15, 0, 8,15, 0, 6,15, 0, 6,15,
0, 6,15, 0, 5,15, 0, 3,15, 0, 3, 8,
0, 3,15, 0, 3, 8, 0, 8,15, 0,15, 3,
0, 3,15, 0, 3, 8, 0, 6,15, 0,10, 8,
0, 5, 3, 0, 8,15, 0, 8, 6, 0, 6,10,
0, 8,15, 0, 5,15, 0,15,10, 0,15, 8,
0, 8,15, 0,15, 3, 0, 3,15, 0, 5,10,
0, 6,10, 0,10, 8, 0, 8, 9, 0,15,10,
0,15, 6, 0, 3,15, 0,15, 8, 0, 5,15,
0,15, 3, 0,15, 6, 0,15, 6, 0,15, 8,
0, 3,15, 0,15, 3, 0, 5,15, 0, 5,15,
0, 5,15, 0, 8,15, 0, 5,15, 0,10,15,
0, 5,15, 0,10,15, 0, 8,15, 0,13,15,
0,15, 3, 0,12,15, 0, 3,15, 0, 3, 8
};
static int shapeindex_to_compressed_indices_2[64*3] =
{
0,15,0, 0,15,0, 0,15,0, 0,15,0,
0,15,0, 0,15,0, 0,15,0, 0,15,0,
0,15,0, 0,15,0, 0,15,0, 0,15,0,
0,15,0, 0,15,0, 0,15,0, 0,15,0,
0,15,0, 0, 2,0, 0, 8,0, 0, 2,0,
0, 2,0, 0, 8,0, 0, 8,0, 0,15,0,
0, 2,0, 0, 8,0, 0, 2,0, 0, 2,0,
0, 8,0, 0, 8,0, 0, 2,0, 0, 2,0,
0,15,0, 0,15,0, 0, 6,0, 0, 8,0,
0, 2,0, 0, 8,0, 0,15,0, 0,15,0,
0, 2,0, 0, 8,0, 0, 2,0, 0, 2,0,
0, 2,0, 0,15,0, 0,15,0, 0, 6,0,
0, 6,0, 0, 2,0, 0, 6,0, 0, 8,0,
0,15,0, 0,15,0, 0, 2,0, 0, 2,0,
0,15,0, 0,15,0, 0,15,0, 0,15,0,
0,15,0, 0, 2,0, 0, 2,0, 0,15,0
};
#define SHAPEINDEX_TO_COMPRESSED_INDICES(s,si,region) s[(si)*3+(region)]
static void stb__FromNBit(unsigned char *out, unsigned int v, int bits)
{
int rv = (v >> (bits*2)) & ((1<<bits)-1);
int gv = (v >> (bits*1)) & ((1<<bits)-1);
int bv = (v >> (bits*0)) & ((1<<bits)-1);
out[0] = (rv<<(8-bits))|(rv>>(bits-(8-bits)));
out[1] = (gv<<(8-bits))|(gv>>(bits-(8-bits)));
out[2] = (bv<<(8-bits))|(bv>>(bits-(8-bits)));
out[3] = 0;
}
static unsigned int stb__AsNBit(int r, int g, int b, int bits)
{
return (stb__Mul8Bit(r,((1<<bits)-1)) << (bits*2)) + (stb__Mul8Bit(g,((1<<bits)-1)) << (bits*1)) + stb__Mul8Bit(b,((1<<bits)-1));
}
static void stb__OptimizeColorsBlock(unsigned char *block, unsigned int pmax32[3], unsigned int pmin32[3], int *shapes, int shapeIndex, int regions, int bits, int *reorder, int numChannels )
{
static const int nIterPower = 4;
int mind[3] = {0x7fffffff,0x7fffffff,0x7fffffff};
int maxd[3] = {-0x7fffffff,-0x7fffffff,-0x7fffffff};
unsigned char *minp[3], *maxp[3];
double magn[3];
int v_r[3],v_g[3],v_b[3],v_a[3];
float covf[3][10],vfr[3],vfg[3],vfb[3],vfa[3];
// determine color distribution
int cov[3][10];
int mu[3][4],min[3][4],max[3][4];
int ch,i,iter;
for(ch=0;ch<numChannels;ch++)
{
const unsigned char *bp = ((const unsigned char *) block) + reorder[ch];
int muv[3] = {0,0,0};
int minv[3] = {256,256,256};
int maxv[3] = {0,0,0};
for(i=0;i<64;i+=4)
{
int r = REGION(shapes,((i/4)%4),((i/4)/4),shapeIndex);
muv[r] += bp[i];
if (bp[i] < minv[r]) minv[r] = bp[i];
else if (bp[i] > maxv[r]) maxv[r] = bp[i];
}
for (int r=0; r<regions; r++)
{
mu[r][ch] = (muv[r] + 8) >> 4;
min[r][ch] = minv[r];
max[r][ch] = maxv[r];
}
}
// determine covariance matrix
for (int r=0; r<regions; r++)
for (i=0;i<10;i++)
cov[r][i] = 0;
for (i=0;i<16;i++)
{
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex);
int r = block[i*4+reorder[0]] - mu[rgn][0];
int g = block[i*4+reorder[1]] - mu[rgn][1];
int b = block[i*4+reorder[2]] - mu[rgn][2];
int a = block[i*4+reorder[3]] - mu[rgn][3];
cov[rgn][0] += r*r;
cov[rgn][1] += r*g;
cov[rgn][2] += r*b;
cov[rgn][3] += r*a;
cov[rgn][4] += g*g;
cov[rgn][5] += g*b;
cov[rgn][6] += g*a;
cov[rgn][7] += b*b;
cov[rgn][8] += b*a;
cov[rgn][9] += a*a;
}
if ( numChannels != 4 )
{
for (int r=0; r<regions; r++)
{
cov[r][3] = 0;
cov[r][6] = 0;
cov[r][8] = 0;
cov[r][9] = 0;
}
}
// convert covariance matrix to float, find principal axis via power iter
for (int r=0; r<regions; r++)
for(i=0;i<10;i++)
covf[r][i] = cov[r][i] / 255.0f;
for (int r=0; r<regions; r++)
{
vfr[r] = (float) (max[r][0] - min[r][0]);
vfg[r] = (float) (max[r][1] - min[r][1]);
vfb[r] = (float) (max[r][2] - min[r][2]);
vfa[r] = (float) (max[r][3] - min[r][3]);
}
for (int rgn=0; rgn<regions; rgn++)
{
for(iter=0;iter<nIterPower;iter++)
{
float r = vfr[rgn]*covf[rgn][0] + vfg[rgn]*covf[rgn][1] + vfb[rgn]*covf[rgn][2] + vfa[rgn]*covf[rgn][3];
float g = vfr[rgn]*covf[rgn][1] + vfg[rgn]*covf[rgn][4] + vfb[rgn]*covf[rgn][5] + vfa[rgn]*covf[rgn][6];
float b = vfr[rgn]*covf[rgn][2] + vfg[rgn]*covf[rgn][5] + vfb[rgn]*covf[rgn][7] + vfa[rgn]*covf[rgn][8];
float a = vfr[rgn]*covf[rgn][3] + vfg[rgn]*covf[rgn][6] + vfb[rgn]*covf[rgn][8] + vfa[rgn]*covf[rgn][9];
vfr[rgn] = r;
vfg[rgn] = g;
vfb[rgn] = b;
vfa[rgn] = (numChannels != 4) ? 0.f : a;
}
magn[rgn] = fabs(vfr[rgn]);
if (fabs(vfg[rgn]) > magn[rgn]) magn[rgn] = fabs(vfg[rgn]);
if (fabs(vfb[rgn]) > magn[rgn]) magn[rgn] = fabs(vfb[rgn]);
if (fabs(vfa[rgn]) > magn[rgn]) magn[rgn] = fabs(vfa[rgn]);
if(magn[rgn] < 4.0f) { // too small, default to luminance
v_r[rgn] = 299; // JPEG YCbCr luma coefs, scaled by 1000.
v_g[rgn] = 587;
v_b[rgn] = 114;
v_a[rgn] = (numChannels != 4) ? 0 : 255;
} else {
magn[rgn] = 512.0 / magn[rgn];
v_r[rgn] = (int) (vfr[rgn] * magn[rgn]);
v_g[rgn] = (int) (vfg[rgn] * magn[rgn]);
v_b[rgn] = (int) (vfb[rgn] * magn[rgn]);
v_a[rgn] = (numChannels != 4) ? 0 : (int) (vfa[rgn] * magn[rgn]);
}
}
// Pick colors at extreme points
for(i=0;i<16;i++)
{
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex);
int dot = block[i*4+reorder[0]]*v_r[rgn] + block[i*4+reorder[1]]*v_g[rgn] + block[i*4+reorder[2]]*v_b[rgn] + block[i*4+reorder[3]]*v_a[rgn];
if (dot < mind[rgn]) {
mind[rgn] = dot;
minp[rgn] = block+i*4;
}
if (dot > maxd[rgn]) {
maxd[rgn] = dot;
maxp[rgn] = block+i*4;
}
}
for (int rgn=0; rgn<regions; rgn++)
{
pmax32[rgn] = stb__AsNBit(maxp[rgn][reorder[0]],maxp[rgn][reorder[1]],maxp[rgn][reorder[2]],bits);
pmin32[rgn] = stb__AsNBit(minp[rgn][reorder[0]],minp[rgn][reorder[1]],minp[rgn][reorder[2]],bits);
}
}
void grabTile( unsigned char *tile, unsigned char *image, int x, int y, int w, int h, int n )
{
for (int oy=0; oy<4; oy++)
{
int iy = y+oy;
if ( iy >= h )
iy = h-1;
for (int ox=0; ox<4; ox++)
{
int ix = x+ox;
if ( ix >= w )
ix = w-1;
for (int c=0; c<4; c++)
{
if ( c < n )
{
*tile++ = image[(iy*w+ix)*n+c];
}
else
{
*tile++ = 255;
}
}
}
}
}
static int stb__Lerp( int a, int b, int nom, int denom )
{
return a + stb__Mul8Bit(b-a, (nom*255)/denom);
}
static inline int clampi( int v, int mn, int mx )
{
return v<mn ? mn : v > mx ? mx : v;
}
#include <assert.h>
void stb__MatchIndices( int indices[16], unsigned char const interp_colours[3][8][4], int *remapindices, int numIndices, int regions, int *shapes, int shapeIndex, unsigned char const tile[4*4*4] )
{
int dirr[3];
int dirg[3];
int dirb[3];
for (int rgn=0; rgn<regions; rgn++)
{
dirr[rgn] = interp_colours[rgn][1][0] - interp_colours[rgn][0][0];
dirg[rgn] = interp_colours[rgn][1][1] - interp_colours[rgn][0][1];
dirb[rgn] = interp_colours[rgn][1][2] - interp_colours[rgn][0][2];
}
int dots[16];
for (int i=0; i<16; i++)
{
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex);
dots[i] = tile[i*4+0]*dirr[rgn] + tile[i*4+1]*dirg[rgn] + tile[i*4+2]*dirb[rgn];
}
int stops[3][8];
for (int rgn=0; rgn<regions; rgn++)
{
for (int i=0; i<numIndices; i++)
{
stops[rgn][i] = interp_colours[rgn][i][0]*dirr[rgn] + interp_colours[rgn][i][1]*dirg[rgn] + interp_colours[rgn][i][2]*dirb[rgn];
}
}
for (int i=0; i<16; i++)
{
int rgn = REGION(shapes,(i%4),(i/4),shapeIndex);
int totalDist = abs(stops[rgn][1] - stops[rgn][0]);
int dist = abs(dots[i] - stops[rgn][0]);
indices[i] = totalDist ? remapindices[clampi((numIndices*dist+(numIndices/2))/totalDist, 0, numIndices)] : 0;;
}
}
class BitPacker
{
int bitPos;
unsigned char *bytes;
public:
BitPacker( void *data ) : bitPos(0), bytes( (unsigned char*)data )
{
}
inline void WriteBit( bool t )
{
int bytePos = bitPos / 8;
int bit = t ? (1<<(bitPos%8)) : 0;
bytes[bytePos] = (bytes[bytePos]&(~(1<<(bitPos%8)))) | bit;
bitPos++;
}
inline void WriteBits( unsigned int v, int num )
{
#if 1
int bytePos = bitPos / 8;
while ( num )
{
int emptyBits = 8 - (bitPos%8);
int offset = (bitPos%8);
if ( emptyBits > num )
emptyBits = num;
int mask = ((1<<emptyBits)-1) << offset;
bytes[bytePos] = (bytes[bytePos]&(~mask)) | ((v<<offset) & mask);
v >>= emptyBits;
num -= emptyBits;
bitPos += emptyBits;
bytePos++;
}
#else
for (int i=0; i<num; i++)
{
WriteBit( v & (1<<i) ? true : false );
}
#endif
}
};
void stb__SwapIndices( int indices[16], int indicesBits, unsigned char interp_colours[3][8][4], int *compressed, int *shape, int regions, int shapeIndex )
{
int highBit = 1<<(indicesBits-1);
int highestIndex = (1<<(indicesBits))-1;
bool flip[3] = { false, false, false };
bool needToFlip = false;
for (int rgn=0; rgn<regions; rgn++)
{
int index = SHAPEINDEX_TO_COMPRESSED_INDICES(compressed,shapeIndex,rgn);
if ( indices[index] & highBit )
{
flip[rgn] = true;
needToFlip = true;
std::swap( interp_colours[rgn][0][0], interp_colours[rgn][1][0] );
std::swap( interp_colours[rgn][0][1], interp_colours[rgn][1][1] );
std::swap( interp_colours[rgn][0][2], interp_colours[rgn][1][2] );
std::swap( interp_colours[rgn][0][3], interp_colours[rgn][1][3] );
}
}
if ( needToFlip )
{
for (int i=0; i<16; i++)
{
int rgn = REGION(shape,(i%4),(i/4),shapeIndex);
if ( flip[rgn] )
{
indices[i] = highestIndex - indices[i];
}
}
}
}
void compress_mode0( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex )
{
unsigned int pmax32[3];
unsigned int pmin32[3];
int reorder[] = { 0, 1, 2, 3 };
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_three, shapeIndex, 3, 4, reorder, 3 );
unsigned char interp_colours[3][8][4];
stb__FromNBit( interp_colours[0][0], pmax32[0], 4 );
stb__FromNBit( interp_colours[1][0], pmax32[1], 4 );
stb__FromNBit( interp_colours[2][0], pmax32[2], 4 );
stb__FromNBit( interp_colours[0][1], pmin32[0], 4 );
stb__FromNBit( interp_colours[1][1], pmin32[1], 4 );
stb__FromNBit( interp_colours[2][1], pmin32[2], 4 );
for (int r=0; r<3; r++)
{
for (int i=0; i<6; i++)
{
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 7 );
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 7 );
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 7 );
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 7 );
}
}
int indices[16];
int remapindices[8] = { 0, 2, 3, 4, 5, 6, 7, 1 };
stb__MatchIndices( indices, interp_colours, remapindices, 8, 3, shapes_three, shapeIndex, tile );
stb__SwapIndices( indices, 3, interp_colours, shapeindex_to_compressed_indices_3, shapes_three, 3, shapeIndex );
BitPacker packer( output );
packer.WriteBit( true ); // mode 0
packer.WriteBits( shapeIndex, 4 ); // shape
// r
packer.WriteBits( interp_colours[0][0][0]>>4, 4 );
packer.WriteBits( interp_colours[0][1][0]>>4, 4 );
packer.WriteBits( interp_colours[1][0][0]>>4, 4 );
packer.WriteBits( interp_colours[1][1][0]>>4, 4 );
packer.WriteBits( interp_colours[2][0][0]>>4, 4 );
packer.WriteBits( interp_colours[2][1][0]>>4, 4 );
// g
packer.WriteBits( interp_colours[0][0][1]>>4, 4 );
packer.WriteBits( interp_colours[0][1][1]>>4, 4 );
packer.WriteBits( interp_colours[1][0][1]>>4, 4 );
packer.WriteBits( interp_colours[1][1][1]>>4, 4 );
packer.WriteBits( interp_colours[2][0][1]>>4, 4 );
packer.WriteBits( interp_colours[2][1][1]>>4, 4 );
// b
packer.WriteBits( interp_colours[0][0][2]>>4, 4 );
packer.WriteBits( interp_colours[0][1][2]>>4, 4 );
packer.WriteBits( interp_colours[1][0][2]>>4, 4 );
packer.WriteBits( interp_colours[1][1][2]>>4, 4 );
packer.WriteBits( interp_colours[2][0][2]>>4, 4 );
packer.WriteBits( interp_colours[2][1][2]>>4, 4 );
// last bits
packer.WriteBits( 0, 6 );
for (int i=0; i<16; i++)
{
int rgn = REGION(shapes_three,(i%4),(i/4),0);
bool first = false;
for (int j=0; j<3; j++)
{
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_3,shapeIndex,j) == i);
}
packer.WriteBits( indices[i], first ? 2 : 3 );
}
}
void compress_mode1( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex )
{
unsigned int pmax32[3];
unsigned int pmin32[3];
int reorder[] = { 0, 1, 2, 3 };
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_two, shapeIndex, 2, 6, reorder, 3 );
unsigned char interp_colours[3][8][4];
stb__FromNBit( interp_colours[0][0], pmax32[0], 6 );
stb__FromNBit( interp_colours[1][0], pmax32[1], 6 );
stb__FromNBit( interp_colours[0][1], pmin32[0], 6 );
stb__FromNBit( interp_colours[1][1], pmin32[1], 6 );
for (int r=0; r<2; r++)
{
for (int i=0; i<6; i++)
{
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 7 );
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 7 );
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 7 );
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 7 );
}
}
int indices[16];
int remapindices[8] = { 0, 2, 3, 4, 5, 6, 7, 1 };
stb__MatchIndices( indices, interp_colours, remapindices, 8, 2, shapes_two, shapeIndex, tile );
stb__SwapIndices( indices, 3, interp_colours, shapeindex_to_compressed_indices_2, shapes_two, 2, shapeIndex );
BitPacker packer( output );
packer.WriteBit( false );
packer.WriteBit( true ); // mode 01
packer.WriteBits( shapeIndex, 6 ); // shape
// r
packer.WriteBits( interp_colours[0][0][0]>>2, 6 );
packer.WriteBits( interp_colours[0][1][0]>>2, 6 );
packer.WriteBits( interp_colours[1][0][0]>>2, 6 );
packer.WriteBits( interp_colours[1][1][0]>>2, 6 );
// g
packer.WriteBits( interp_colours[0][0][1]>>2, 6 );
packer.WriteBits( interp_colours[0][1][1]>>2, 6 );
packer.WriteBits( interp_colours[1][0][1]>>2, 6 );
packer.WriteBits( interp_colours[1][1][1]>>2, 6 );
// b
packer.WriteBits( interp_colours[0][0][2]>>2, 6 );
packer.WriteBits( interp_colours[0][1][2]>>2, 6 );
packer.WriteBits( interp_colours[1][0][2]>>2, 6 );
packer.WriteBits( interp_colours[1][1][2]>>2, 6 );
// last bits
packer.WriteBits( 0, 2 );
for (int i=0; i<16; i++)
{
int rgn = REGION(shapes_two,(i%4),(i/4),0);
bool first = false;
for (int j=0; j<2; j++)
{
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_2,shapeIndex,j) == i);
}
packer.WriteBits( indices[i], first ? 2 : 3 );
}
}
void compress_mode2( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex )
{
unsigned int pmax32[3];
unsigned int pmin32[3];
int reorder[] = { 0, 1, 2, 3 };
stb__OptimizeColorsBlock( tile, pmax32, pmin32, shapes_three, shapeIndex, 3, 5, reorder, 3 );
unsigned char interp_colours[3][8][4];
stb__FromNBit( interp_colours[0][0], pmax32[0], 5 );
stb__FromNBit( interp_colours[1][0], pmax32[1], 5 );
stb__FromNBit( interp_colours[2][0], pmax32[2], 5 );
stb__FromNBit( interp_colours[0][1], pmin32[0], 5 );
stb__FromNBit( interp_colours[1][1], pmin32[1], 5 );
stb__FromNBit( interp_colours[2][1], pmin32[2], 5 );
for (int r=0; r<2; r++)
{
for (int i=0; i<2; i++)
{
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, 3 );
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, 3 );
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, 3 );
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, 3 );
}
}
int indices[16];
int remapindices[4] = { 0, 2, 3, 1 };
stb__MatchIndices( indices, interp_colours, remapindices, 4, 3, shapes_three, shapeIndex, tile );
stb__SwapIndices( indices, 2, interp_colours, shapeindex_to_compressed_indices_3, shapes_three, 3, shapeIndex );
BitPacker packer( output );
packer.WriteBit( false );
packer.WriteBit( false );
packer.WriteBit( true ); // mode 001
packer.WriteBits( shapeIndex, 6 ); // shape
// r
packer.WriteBits( interp_colours[0][0][0]>>2, 5 );
packer.WriteBits( interp_colours[0][1][0]>>2, 5 );
packer.WriteBits( interp_colours[1][0][0]>>2, 5 );
packer.WriteBits( interp_colours[1][1][0]>>2, 5 );
packer.WriteBits( interp_colours[2][0][0]>>2, 5 );
packer.WriteBits( interp_colours[2][1][0]>>2, 5 );
// g
packer.WriteBits( interp_colours[0][0][1]>>2, 5 );
packer.WriteBits( interp_colours[0][1][1]>>2, 5 );
packer.WriteBits( interp_colours[1][0][1]>>2, 5 );
packer.WriteBits( interp_colours[1][1][1]>>2, 5 );
packer.WriteBits( interp_colours[2][0][1]>>2, 5 );
packer.WriteBits( interp_colours[2][1][1]>>2, 5 );
// b
packer.WriteBits( interp_colours[0][0][2]>>2, 5 );
packer.WriteBits( interp_colours[0][1][2]>>2, 5 );
packer.WriteBits( interp_colours[1][0][2]>>2, 5 );
packer.WriteBits( interp_colours[1][1][2]>>2, 5 );
packer.WriteBits( interp_colours[2][0][2]>>2, 5 );
packer.WriteBits( interp_colours[2][1][2]>>2, 5 );
for (int i=0; i<16; i++)
{
int rgn = REGION(shapes_three,(i%4),(i/4),0);
bool first = false;
for (int j=0; j<3; j++)
{
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(shapeindex_to_compressed_indices_3,shapeIndex,j) == i);
}
packer.WriteBits( indices[i], first ? 1 : 2 );
}
}
struct compress_info
{
int block;
int blockBits;
int *shape;
int *shapeindex_to_compressed_indices;
int numShapes;
int shapeBits;
int numPbits;
int endPointBits;
int indexBits;
};
void compress_mode_generic( unsigned char output[16], unsigned char tile[4*4*4], int shapeIndex, compress_info *info )
{
unsigned int pmax32[3];
unsigned int pmin32[3];
int reorder[] = { 0, 1, 2, 3 };
stb__OptimizeColorsBlock( tile, pmax32, pmin32, info->shape, shapeIndex, info->numShapes, info->endPointBits, reorder, 3 );
unsigned char interp_colours[3][8][4];
for (int i=0; i<info->numShapes; i++)
{
stb__FromNBit( interp_colours[i][0], pmax32[i], info->endPointBits );
stb__FromNBit( interp_colours[i][1], pmin32[i], info->endPointBits );
}
int numIndices = 1<<info->indexBits;
for (int r=0; r<info->numShapes; r++)
{
for (int i=0; i<numIndices; i++)
{
interp_colours[r][i+2][0] = stb__Lerp( interp_colours[r][0][0], interp_colours[r][1][0], i+1, numIndices );
interp_colours[r][i+2][1] = stb__Lerp( interp_colours[r][0][1], interp_colours[r][1][1], i+1, numIndices );
interp_colours[r][i+2][2] = stb__Lerp( interp_colours[r][0][2], interp_colours[r][1][2], i+1, numIndices );
interp_colours[r][i+2][3] = stb__Lerp( interp_colours[r][0][3], interp_colours[r][1][3], i+1, numIndices );
}
}
int indices[16];
int remapindices_2[8] = { 0, 2, 3, 1 };
int remapindices_3[8] = { 0, 2, 3, 4, 5, 6, 7, 1 };
int *remapindices = NULL;
if ( numIndices == 2 )
remapindices = remapindices_2;
if ( numIndices == 3 )
remapindices = remapindices_3;
stb__MatchIndices( indices, interp_colours, remapindices, numIndices, info->numShapes, info->shape, shapeIndex, tile );
stb__SwapIndices( indices, info->indexBits, interp_colours, info->shapeindex_to_compressed_indices, info->shape, info->numShapes, shapeIndex );
BitPacker packer( output );
packer.WriteBits( info->block, info->blockBits ); // mode
packer.WriteBits( shapeIndex, info->shapeBits ); // shape
// r
for (int r=0; r<info->numShapes; r++)
{
packer.WriteBits( interp_colours[r][0][0]>>(8-info->endPointBits), info->endPointBits );
packer.WriteBits( interp_colours[r][1][0]>>(8-info->endPointBits), info->endPointBits );
}
// g
for (int r=0; r<info->numShapes; r++)
{
packer.WriteBits( interp_colours[r][0][1]>>(8-info->endPointBits), info->endPointBits );
packer.WriteBits( interp_colours[r][1][1]>>(8-info->endPointBits), info->endPointBits );
}
// b
for (int r=0; r<info->numShapes; r++)
{
packer.WriteBits( interp_colours[r][0][2]>>(8-info->endPointBits), info->endPointBits );
packer.WriteBits( interp_colours[r][1][2]>>(8-info->endPointBits), info->endPointBits );
}
// last bits
if ( info->numPbits )
packer.WriteBits( 0, info->numPbits );
for (int i=0; i<16; i++)
{
int rgn = REGION(info->shape,(i%4),(i/4),0);
bool first = false;
for (int j=0; j<info->numShapes; j++)
{
first |= (SHAPEINDEX_TO_COMPRESSED_INDICES(info->shapeindex_to_compressed_indices,shapeIndex,j) == i);
}
packer.WriteBits( indices[i], first ? (info->indexBits-1) : info->indexBits );
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int w,h,n;
unsigned char *data = stbi_load("hun-dirt-color_input.png", &w, &h, &n, 0);
int mips = 1;
int format = 0;
FILE *f = fopen( "c:\\bc7.tex", "wb" );
fwrite( &w, 4, 1, f );
fwrite( &h, 4, 1, f );
fwrite( &mips, 4, 1, f );
fwrite( &format, 4, 1, f );
unsigned char *blocks = (unsigned char*)malloc( (w/4) * (h/4) * 16 );
unsigned char *blocks_cursor = blocks;
crnlib::timer t;
t.start();
for (int y=0; y<h; y+=4)
{
for (int x=0; x<w; x+=4)
{
unsigned char tile[4*4*4];
grabTile( tile, data, x, y, w, h, n );
if ( format == 0 )
{
compress_mode3( blocks_cursor, tile, 1 );
blocks_cursor+=16;
}
else
{
stb_compress_dxt_block( blocks_cursor, tile, 0, 0 );
blocks_cursor+=8;
}
}
}
t.stop();
int ms = t.get_elapsed_ms();
fwrite( blocks, (w/4) * (h/4) * (format == 0 ? 16 : 8), 1, f );
fclose( f );
printf( "%d\n", ms );
// 1
// 16 + 64 + 64 + 64 + 8 + 4 + 1 + 64 = 285
return 0;
}
// opengex.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <vector>
#include <list>
#include <string>
#include <map>
#include <assert.h>
#include "lexer.h"
//#include "stb_c_lexer.h"
struct structure
{
LexerToken name;
virtual ~structure() {}
};
struct datatype : public structure
{
int stride;
};
template <class T>
struct typeddatatype : public datatype
{
std::vector<T> items;
};
struct prop
{
//std::string ident;
LexerToken ident;
virtual ~prop() {}
};
template <class T>
struct typedprop : public prop
{
T data;
};
struct identifier : public structure
{
LexerToken ident;
// std::string ident;
std::vector< prop* > props;
std::vector< structure* > children;
};
struct reflink
{
LexerToken name;
//std::string name;
structure *ref;
};
void readtextfile( std::string &out, const std::string &filename )
{
FILE *f = fopen( filename.c_str(), "rb" );
if ( !f )
return;
fseek( f, 0, SEEK_END );
int len = ftell( f );
fseek( f, 0, SEEK_SET );
out.resize( len );
fread( &out[0], 1, len, f );
fclose( f );
}
#if 0
void skipws( std::string const &script, std::string::size_type &cursor )
{
cursor = script.find_first_not_of( " \t\n\r", cursor );
}
void skiplinecomment( std::string const &script, std::string::size_type &cursor )
{
cursor = script.find_first_of( "\n", cursor );
}
void skipmultilinecomment( std::string const &script, std::string::size_type &cursor )
{
cursor = script.find( "*/", cursor );
if ( cursor != std::string::npos )
cursor += 2;
if ( cursor >= script.size() )
cursor = std::string::npos;
}
std::string getquotedstring( std::string const &script, std::string::size_type &cursor )
{
std::string::size_type start = cursor;
cursor++;
if ( cursor >= script.size() )
{
cursor = std::string::npos;
return "";
}
while ( 1 )
{
cursor = script.find_first_of( '\"', cursor );
if ( cursor == std::string::npos )
{
return script.substr( start );
}
if ( cursor && script[cursor-1]=='\\' )
{
cursor++;
if ( cursor >= script.size() )
{
cursor = std::string::npos;
return "";
}
continue;
}
cursor++;
if ( cursor >= script.size() )
cursor = std::string::npos;
if ( cursor == std::string::npos )
return script.substr( start );
else
return script.substr( start, cursor - start );
}
}
const char *s_SpecialMultiTokens[] =
{
"===", "==",
"!==", "!=",
"<<=", "<="
">>=", ">=",
"&&", "&=",
"|=", "||",
"^=",
"[[",
"]]",
NULL
};
int getspecialtoken( std::string const &script, std::string::size_type &cursor )
{
if ( script[cursor] == '+' && (script[cursor+1] == '.' || (script[cursor+1] >= '0' && script[cursor+1]<='9')) )
{
std::string::size_type end = script.find_first_not_of( "+.0123456789", cursor );
if ( script[end]=='e' )
{
end = script.find_first_not_of( "-+0123456789", end+1 );
}
return end - cursor;
}
if ( script[cursor] == '-' && (script[cursor+1] == '.' || (script[cursor+1] >= '0' && script[cursor+1]<='9')) )
{
std::string::size_type end = script.find_first_not_of( "-.0123456789", cursor );
if ( script[end]=='e' )
{
end = script.find_first_not_of( "-+0123456789", end+1 );
}
return end - cursor;
}
if ( script[cursor] >= '0' && script[cursor]<='9' )
{
std::string::size_type end = script.find_first_not_of( "-.0123456789", cursor );
if ( script[end]=='e' )
{
end = script.find_first_not_of( "-+0123456789", end+1 );
}
return end - cursor;
}
for ( int item = 0; s_SpecialMultiTokens[item]; item++ )
{
const char *special = s_SpecialMultiTokens[item];
std::string::size_type cur = cursor;
int len = 0;
while ( *special )
{
if ( *special != script[cur] )
{
len = 0;
break;
}
cur++;
if ( cur >= script.size() )
{
len = 0;
break;
}
len++;
special++;
}
if ( len )
return len;
}
return 1;
}
std::string gettoken( std::string const &script, std::string::size_type &cursor )
{
while ( 1 )
{
if ( cursor == std::string::npos )
return "";
skipws( script, cursor );
if ( cursor == std::string::npos )
return "";
if ( cursor < (script.size()-1) )
{
if ( script[cursor] == '/' && script[cursor+1] == '/' )
{
skiplinecomment( script, cursor );
continue;
}
else
if ( script[cursor] == '/' && script[cursor+1] == '*' )
{
skipmultilinecomment( script, cursor );
continue;
}
}
if ( script[cursor] == '\"' )
{
return getquotedstring( script, cursor );
}
std::string::size_type end = script.find_first_of( "^&!<>()[]{};,*+=-/\"' \t\n\r", cursor );
if ( end == cursor )
{
if ( (cursor+1) >= script.size() )
{
cursor = std::string::npos;
return std::string( 1, script[end] );
}
else
{
int l = getspecialtoken( script, cursor );
cursor += l;
if ( cursor >= script.size() )
cursor = std::string::npos;
return script.substr( end, l );
}
}
std::string::size_type start = cursor;
if ( script[start] >= '0' && script[start] <= '9' )
{
if ( script[end-1] == 'e' )
{
end = script.find_first_not_of( "-+0123456789", end );
printf("");
}
}
cursor = end;
if ( end == std::string::npos )
return script.substr( start );
else
return script.substr( start, end - start );
}
}
#if 0
static std::string tostring(stb_lexer *lexer)
{
char tempbuffer[256];
switch (lexer->token) {
case CLEX_id : return lexer->string; break;
case CLEX_eq : return "=="; break;
case CLEX_noteq : return "!="; break;
case CLEX_lesseq : return "<="; break;
case CLEX_greatereq : return ">="; break;
case CLEX_andand : return "&&"; break;
case CLEX_oror : return "||"; break;
case CLEX_shl : return "<<"; break;
case CLEX_shr : return ">>"; break;
case CLEX_plusplus : return "++"; break;
case CLEX_minusminus: return "--"; break;
case CLEX_arrow : return "->"; break;
case CLEX_andeq : return "&="; break;
case CLEX_oreq : return "|="; break;
case CLEX_xoreq : return "^="; break;
case CLEX_pluseq : return "+="; break;
case CLEX_minuseq : return "-="; break;
case CLEX_muleq : return "*="; break;
case CLEX_diveq : return "/="; break;
case CLEX_modeq : return "%%="; break;
case CLEX_shleq : return "<<="; break;
case CLEX_shreq : return ">>="; break;
case CLEX_eqarrow : return "=>"; break;
case CLEX_dqstring : return std::string("\"") + lexer->string + std::string("\""); break;
case CLEX_sqstring : return std::string("'") + lexer->string + std::string("'"); break;
case CLEX_charlit : return std::string("'") + lexer->string + std::string("'"); break;
case CLEX_intlit : { sprintf(tempbuffer,"%ld", lexer->int_number); return tempbuffer; } break;
case CLEX_floatlit : { sprintf(tempbuffer,"%g", lexer->real_number); return tempbuffer; } break;
default:
if (lexer->token >= 0 && lexer->token < 256)
{
tempbuffer[0] = lexer->token;
tempbuffer[1] = 0;
return tempbuffer;
}
else {
printf("<<<UNKNOWN TOKEN %ld >>>\n", lexer->token);
}
break;
}
return "";
}
#endif
#endif
struct ParseInfo
{
std::string const &script;
std::string::size_type cursor;
//int tokenType;
std::string token;
LexerToken tok;
//stb_lexer lexer;
//char string_store[16*1024];
LexerState lex;
ParseInfo( std::string const &s, std::string::size_type c = 0 ) : script(s), cursor(c)
{
lex.cursor = script.c_str();
lex.text = script.c_str();
lex.end = script.c_str() + script.length();
//stb_c_lexer_init(&lexer, s.c_str(), s.c_str()+s.size(), string_store, sizeof(string_store));
}
void GetSym()
{
if ( lexerGetToken( &tok, &lex ) == LS_OK )
{
token.assign( tok.start, tok.length );
}
else
{
tok.start="";
token = "";
}
}
bool Accept(std::string const & s)
{
if (s == token)
{
GetSym();
return true;
}
return false;
}
bool Expect(std::string const & s)
{
if (Accept(s))
return 1;
int line = 0;
std::string::size_type p = 0;
while ( p < cursor )
{
line += (script[p] == '\n') ? 1 : 0;
p++;
}
line = lexerGetLineNumber( &lex );
assert( 0 );
//error("expect: unexpected symbol");
return 0;
}
void Token( std::string &str )
{
std::swap( str, token );
GetSym();
}
void Token( LexerToken &t )
{
t = tok;
GetSym();
}
int TokenAtoi()
{
int i = tok.i;
GetSym();
return i;
}
float TokenAtof()
{
float f = tok.f;
GetSym();
return f;
}
bool End()
{
return lexerIsEof( &lex );//cursor == std::string::npos || cursor >= script.size();//tokenType == CLEX_eof;
}
};
template <class T>
bool ParseDecimalLiteral( T &i, std::string const &v, int ofs = 0 )
{
i = 0;
for (unsigned int j=ofs; j<v.size(); j++)
{
i*=T(10);
if ( v[j]>='0' && v[j]<='9' )
i+=v[j]-'0';
else
return false;
}
return true;
}
template <class T>
bool ParseHexLiteral( T &i, std::string const &v )
{
if ( v.size() < 2 || !(v[0] != '0' && (v[1] != 'x' || v[1] != 'X')) )
return false;
i = 0;
for (unsigned int j=2; j<v.size(); j++)
{
i*=T(2);
if ( v[j]>='0' && v[j]<='9' )
{
i+=v[j]-'0';
} else
if ( v[j]>='a' && v[j]<='f' )
{
i+=(v[j]-'a')+10;
} else
if ( v[j]>='A' && v[j]<='F' )
{
i+=(v[j]-'A')+10;
} else
return false;
}
return true;
}
template <class T>
bool ParseBinaryLiteral( T &i, std::string const &v )
{
if ( v.size() < 2 || !(v[0] != '0' && (v[1] != 'c' || v[1] != 'B')) )
return false;
i = 0;
for (unsigned int j=2; j<v.size(); j++)
{
i*=T(2);
if ( v[j]>='0' && v[j]<='1' )
{
i+=v[j]-'0';
} else
return false;
}
return true;
}
template <class T>
bool ParseCharLiteral( T &i, std::string const &v )
{
if ( v.size() < 2 || !(v[0] != '\'') )
return false;
i = 0;
assert(0);
return true;
}
template <class T>
bool ParseIntegerLiteral( T&i, std::string const &v )
{
bool negate = (v[0] == '-');
int ofs = 0;
if ( v[0] == '+' || v[0] == '-' )
ofs++;
if ( ParseDecimalLiteral<T>( i, v, ofs ) ||
ParseHexLiteral<T>( i, v ) ||
ParseBinaryLiteral<T>( i, v ) ||
ParseCharLiteral<T>( i, v ) )
{
return true;
}
return false;
}
bool ParseBoolLiteral( bool &i, std::string const &v )
{
if ( v == "true" )
{
i=true;
return true;
}
if ( v == "false" )
{
i=false;
return true;
}
return false;
}
bool ParseFloatLiteral( float &i, std::string const &v )
{
if ( v == "true" )
{
i=true;
return true;
}
if ( v == "false" )
{
i=false;
return true;
}
return false;
}
template <class T>
struct ParseTypeHelper
{
bool operator()( T &item, ParseInfo &pinfo );
};
template <>
struct ParseTypeHelper<bool>
{
bool operator()( bool &item, ParseInfo &pinfo )
{
if ( pinfo.Accept( "true" ) )
{
item = true;
}
else if ( pinfo.Accept( "false" ) )
{
item = false;
}
else
assert(0);
return true;
}
};
template <>
struct ParseTypeHelper<char>
{
bool operator()( char &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<short>
{
bool operator()( short &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<int>
{
bool operator()( int &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<__int64>
{
bool operator()( __int64 &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<unsigned char>
{
bool operator()( unsigned char &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<unsigned short>
{
bool operator()( unsigned short &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<unsigned int>
{
bool operator()( unsigned int &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<unsigned __int64>
{
bool operator()( unsigned __int64 &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtoi();
return true;
}
};
template <>
struct ParseTypeHelper<float>
{
bool operator()( float &item, ParseInfo &pinfo )
{
if ( pinfo.token.size() >= 2 && pinfo.token[0] == '0' && (pinfo.token[1] == 'x' || pinfo.token[1] == 'X') )
{
union
{
float f;
unsigned int i;
} conv;
conv.i = pinfo.TokenAtoi();
item = conv.f;
}
else
if ( pinfo.token.size() >= 2 && pinfo.token[0] == '0' && (pinfo.token[1] == 'b' || pinfo.token[1] == 'B') )
{
union
{
float f;
unsigned int i;
} conv;
conv.i = pinfo.TokenAtoi();
item = conv.f;
}
else
{
item = (float)pinfo.TokenAtof();
}
return true;
}
};
template <>
struct ParseTypeHelper<double>
{
bool operator()( double &item, ParseInfo &pinfo )
{
item = pinfo.TokenAtof();
return true;
}
};
template <>
struct ParseTypeHelper<std::string>
{
bool operator()( std::string &item, ParseInfo &pinfo )
{
pinfo.Token( item );
return true;
}
};
template <>
struct ParseTypeHelper<reflink>
{
bool operator()( reflink &item, ParseInfo &pinfo )
{
pinfo.Token( item.name );
item.ref = NULL;
return true;
}
};
template<class T>
void ParseType( std::vector<T> &out, ParseInfo &pinfo, int stride )
{
ParseTypeHelper<T> helper;
T item;
helper( item, pinfo );
out.push_back( item );
for (int i=1; i<stride; i++)
{
pinfo.Expect(",");
helper( item, pinfo );
out.push_back( item );
}
}
template<class T>
structure *ParseTypedDataType( ParseInfo &pinfo )
{
typeddatatype<T> *dataType = new typeddatatype<T>;
dataType->stride = 1;
if ( pinfo.Accept( "[" ) )
{
dataType->stride = pinfo.TokenAtoi();
pinfo.Expect( "]" );
}
if ( !pinfo.Accept( "{" ) )
{
pinfo.Token( dataType->name );
pinfo.Expect( "{" );
}
if ( dataType->stride > 1 )
{
pinfo.Expect( "{" );
ParseType( dataType->items, pinfo, dataType->stride );
pinfo.Expect( "}" );
while ( pinfo.Accept( "," ) )
{
pinfo.Expect( "{" );
ParseType( dataType->items, pinfo, dataType->stride );
pinfo.Expect( "}" );
}
}
else
{
ParseType( dataType->items, pinfo, dataType->stride );
while ( pinfo.Accept( "," ) )
{
ParseType( dataType->items, pinfo, dataType->stride );
}
}
pinfo.Expect( "}" );
return dataType;
}
structure *ParseDataType( ParseInfo &pinfo )
{
if ( pinfo.Accept( "bool" ) )
{
return ParseTypedDataType<bool>( pinfo );
} else
if ( pinfo.Accept( "int8" ) )
{
return ParseTypedDataType<char>( pinfo );
} else
if ( pinfo.Accept( "int16" ) )
{
return ParseTypedDataType<short>( pinfo );
} else
if ( pinfo.Accept( "int32" ) )
{
return ParseTypedDataType<int>( pinfo );
} else
if ( pinfo.Accept( "int64" ) )
{
return ParseTypedDataType<__int64>( pinfo );
} else
if ( pinfo.Accept( "unsigned_int8" ) )
{
return ParseTypedDataType<unsigned char>( pinfo );
} else
if ( pinfo.Accept( "unsigned_int16" ) )
{
return ParseTypedDataType<unsigned char>( pinfo );
} else
if ( pinfo.Accept( "unsigned_int32" ) )
{
return ParseTypedDataType<unsigned char>( pinfo );
} else
if ( pinfo.Accept( "unsigned_int64" ) )
{
return ParseTypedDataType<unsigned char>( pinfo );
} else
if ( pinfo.Accept( "float" ) )
{
return ParseTypedDataType<float>( pinfo );
} else
if ( pinfo.Accept( "double" ) )
{
return ParseTypedDataType<double>( pinfo );
} else
if ( pinfo.Accept( "string" ) )
{
return ParseTypedDataType<std::string>( pinfo );
} else
if ( pinfo.Accept( "ref" ) )
{
return ParseTypedDataType<reflink>( pinfo );
} else
{
return NULL;
}
}
prop *ParseProperty( ParseInfo &pinfo )
{
//std::string id;
LexerToken id;
pinfo.Token( id );
pinfo.Expect( "=" );
LexerToken val;
pinfo.Token( val );
if ( strncmp( val.start, "true", val.length ) == 0 )//== "true" || val == "false" )
{
typedprop<bool> *p = new typedprop<bool>;
p->ident = id;
p->data = true;
return p;
} else
if ( strncmp( val.start, "false", val.length ) == 0 )//== "true" || val == "false" )
{
typedprop<bool> *p = new typedprop<bool>;
p->ident = id;
p->data = false;
return p;
} else
if ( val.start[0] == '%' || val.start[0] == '$' )
{
typedprop<reflink> *p = new typedprop<reflink>;
p->ident = id;
p->data.name = val;
return p;
} else
if ( val.type == LT_Float ) //val.find( '.' ) != std::string::npos && val.find_first_not_of( "0123456789.-" ) == std::string::npos )
{
typedprop<float> *p = new typedprop<float>;
p->ident = id;
p->data = val.f;//(float)atof(val.c_str());
return p;
} else
if ( val.type == LT_Int )//val.find_first_not_of( "-0123456789" ) == std::string::npos )
{
typedprop<int> *p = new typedprop<int>;
p->ident = id;
p->data = val.i;//atoi(val.c_str());
return p;
}
structure *s = ParseDataType( pinfo );
if ( s )
{
typedprop<structure*> *p = new typedprop<structure*>;
p->ident = id;
p->data = s;
return p;
}
else
{
//typedprop<std::string> *p = new typedprop<std::string>;
typedprop<LexerToken> *p = new typedprop<LexerToken>;
p->ident = id;
p->data = val;
return p;
}
assert(0);
return NULL;
}
structure *ParseStructure( ParseInfo &pinfo );
structure *ParseIdentifier( ParseInfo &pinfo )
{
identifier *id = new identifier;
pinfo.Token( id->ident );
id->name.start = NULL;
if ( pinfo.token[0] == '$' )
{
pinfo.Token(id->name);
} else
if ( pinfo.token[0] == '%' )
{
pinfo.Token(id->name);
}
if ( pinfo.Accept( "(" ) )
{
if ( !pinfo.Accept( ")" ) )
{
id->props.push_back( ParseProperty( pinfo ) );
while ( pinfo.Accept( "," ) )
{
id->props.push_back( ParseProperty( pinfo ) );
}
pinfo.Expect( ")" );
}
}
pinfo.Expect( "{" );
while ( !pinfo.Accept( "}" ) )
{
id->children.push_back( ParseStructure( pinfo ) );
}
return id;
}
structure *ParseStructure( ParseInfo &pinfo )
{
structure *dataType = ParseDataType( pinfo );
if ( dataType )
return dataType;
structure *id = ParseIdentifier( pinfo );
if ( id )
return id;
assert(0);
return NULL;
}
structure *ParseDoc( std::string const &doc )
{
identifier *docID = new identifier;
ParseInfo pinfo( doc );
pinfo.GetSym();
while ( !pinfo.End() )
{
docID->children.push_back( ParseStructure( pinfo ) );
}
return docID;
}
void GenerateLinks( std::map<std::string,structure*> &reflinks, structure *root )
{
#if 0
if ( root->name.start )
reflinks[root->name] = root;
identifier *id = dynamic_cast<identifier*>( root );
if ( id )
{
for (unsigned int i=0; i<id->props.size(); i++)
{
typedprop<structure*> *s = dynamic_cast<typedprop<structure*>*>( id->props[i] );
if ( s )
{
GenerateLinks( reflinks, s->data );
}
}
for (unsigned int i=0; i<id->children.size(); i++)
{
GenerateLinks( reflinks, id->children[i] );
}
}
#endif
}
void Link( structure *root, std::map<std::string,structure*> const &reflinks )
{
#if 0
typeddatatype<reflink> *tolink = dynamic_cast<typeddatatype<reflink> *>( root );
if ( tolink )
{
for (unsigned int i=0; i<tolink->items.size(); i++)
{
std::map<std::string,structure*>::const_iterator f = reflinks.find( tolink->items[i].name );
if ( f != reflinks.cend() )
tolink->items[i].ref = f->second;
}
}
identifier *id = dynamic_cast<identifier*>( root );
if ( id )
{
for (unsigned int i=0; i<id->props.size(); i++)
{
typedprop<reflink> *tolink = dynamic_cast<typedprop<reflink> *>( id->props[i] );
if ( tolink )
{
std::map<std::string,structure*>::const_iterator f = reflinks.find( tolink->data.name );
if ( f != reflinks.cend() )
tolink->data.ref = f->second;
}
typedprop<structure*> *s = dynamic_cast<typedprop<structure*>*>( id->props[i] );
if ( s )
{
Link( s->data, reflinks );
}
}
for (unsigned int i=0; i<id->children.size(); i++)
{
Link( id->children[i], reflinks );
}
}
#endif
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string doc;
readtextfile( doc, "anim.ogex" );
const char *test = "123 1.234 1.234e90 1.234e-90 aA 0xafg 0b10111";
LexerState lex;
lex.cursor = test;
lex.text = test;
lex.end = test + strlen(test);
LexerToken tok;
while ( lexerGetToken( &tok, &lex ) == LS_OK )
{
}
structure *s = ParseDoc( doc );
std::map<std::string,structure*> reflinks;
GenerateLinks( reflinks, s );
Link( s, reflinks );
return 0;
}
// pose.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <math.h>
#include <float.h>
#include "escapi.h"
#include "stb_image_write.h"
template<typename R>
struct dual
{
R x;
R e;
dual() : x(0.f), e(0.f) {}
dual(R x0, R e0 = R(0)) : x(x0), e(e0) {}
};
template<typename R>
inline dual<R> operator-(const dual<R> &a)
{
return dual<R>(-a.x, -a.e);
}
template<typename R>
inline dual<R> operator+(const dual<R> &a, const dual<R> &b)
{
return dual<R>(a.x + b.x, a.e + b.e);
}
template<typename R>
inline dual<R> operator-(const dual<R> &a, const dual<R> &b)
{
return dual<R>(a.x - b.x, a.e - b.e);
}
template<typename R>
inline dual<R> operator*(const dual<R> &a, const dual<R> &b)
{
return dual<R>(a.x * b.x, a.x * b.e + a.e * b.x);
}
template<typename R>
inline dual<R> operator/(const dual<R> &a, const dual<R> &b)
{
return dual<R>(a.x / b.x, (a.x * b.e - a.e * b.x) / (b.x * b.x));
}
template<typename R>
inline dual<R> sin(const dual<R> &a)
{
return dual<R>(sin(a.x), a.e * cos(a.x));
}
template<typename R>
inline dual<R> cos(const dual<R> &a)
{
return dual<R>(cos(a.x), -a.e * sin(a.x));
}
template<typename R>
inline dual<R> tan(const dual<R> &a)
{
R sec = R(1) / cos(a.x); // needs divide by zero check
return dual<R>(tan(a.x), -a.e * sec * sec);
}
struct err_s
{
float dir[4][3];
float dist[3+3+3+3];
};
template <class T>
T len( const T p0[3], const T p1[3] )
{
T d[3] = { p1[0]-p0[0], p1[1]-p0[1], p1[2]-p0[2] };
return sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);
}
template <class T>
void cp(T o[3], const T i0[3], const T i1[3])
{
o[0] = i0[1]*i1[2] - i0[2]*i1[1];
o[1] = i0[2]*i1[0] - i0[0]*i1[2];
o[2] = i0[0]*i1[1] - i0[1]*i1[0];
}
template <class T>
T dot(const T i0[3], const T i1[3])
{
return i0[0]*i1[0] + i0[1]*i1[1] + i0[2]*i1[2];
}
template <class T>
void sub(T o[3], const T i0[3], const T i1[3])
{
o[0] = i0[0] - i1[0];
o[1] = i0[1] - i1[1];
o[2] = i0[2] - i1[2];
}
template <class T>
void add(T o[3], const T i0[3], const T i1[3])
{
o[0] = i0[0] + i1[0];
o[1] = i0[1] + i1[1];
o[2] = i0[2] + i1[2];
}
template <class T>
void normalise( T n[3] )
{
float ool = 1.f/sqrtf( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] );
n[0] *= ool;
n[1] *= ool;
n[2] *= ool;
}
template <class T>
T err( void *data, T *v )
{
err_s *e = (err_s*)data;
T toterr = 0.f;
int index = 0;
T p[4][3] =
{
{ e->dir[0][0]*v[0], e->dir[0][1]*v[0], e->dir[0][2]*v[0] },
{ e->dir[1][0]*v[1], e->dir[1][1]*v[1], e->dir[1][2]*v[1] },
{ e->dir[2][0]*v[2], e->dir[2][1]*v[2], e->dir[2][2]*v[2] },
{ e->dir[3][0]*v[3], e->dir[3][1]*v[3], e->dir[3][2]*v[3] }
};
T d10[3], d20[3], c[3];
sub( d10, p[1], p[0] );
sub( d20, p[2], p[0] );
cp( c, d10, d20 );
normalise( c );
T d30[3];
sub( d30, p[3], p[0] );
T d = dot( d30, c );
toterr = toterr + d*d;
for (int i=0; i<4; i++)
{
T *pi = p[i];
for (int j=i+1; j<4; j++)
{
T *pj = p[j];
T l = len( pi, pj );
toterr = toterr + (l-e->dist[index])*(l-e->dist[index]);
index++;
}
}
return toterr;
}
#if 1
template <class T>
T derr( int &index, void *data, T *v, T delta )
{
index = -1;
float maxErr = 0.f;
for (int i=0; i<4; i++)
{
T dvmn[4] = { v[0], v[1], v[2], v[3] };
T dvmx[4] = { v[0], v[1], v[2], v[3] };
dvmn[i] = dvmn[i] - delta;
dvmx[i] = dvmx[i] + delta;
float de = (err( data, dvmx ) - err( data, dvmn )) / (delta*2.f);
if ( fabsf( de ) > fabsf( maxErr ) )
{
index = i;
maxErr = de;
}
}
return maxErr;
}
#else
dual<float> derr( int &index, void *data, dual<float> *v )
{
index = -1;
float maxErr = 0.f;
for (int i=0; i<4; i++)
{
dual<float> dv[4] = { v[0], v[1], v[2], v[3] };
dvmx[i] = dvmx[i] + delta;
float de = (err( data, dvmx ) - err( data, dvmn )) / (delta*2.f);
if ( fabsf( de ) > fabsf( maxErr ) )
{
index = i;
maxErr = de;
}
}
return maxErr;
}
#endif
#include <Windows.h>
struct bgra
{
unsigned char b, g, r, a;
};
void filtergreen( bgra *buffer, int width, int height )
{
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
int index = y*width+x;
bgra *pix = &buffer[index];
if ( pix->g > pix->b && pix->g > pix->r )
{
pix->r = 0;
pix->b = 0;
} else
{
pix->r = 0;
pix->g = 0;
pix->b = 0;
}
}
}
}
int count( bgra *buffer, int l, int t, int r, int b, int w, int h )
{
int c = 0;
for (int y=t; y<=b; y++)
{
if ( y < 0 || y >= h )
continue;
for (int x=l; x<=r; x++)
{
if ( x < 0 || x >= w )
continue;
int index = y*w+x;
bgra *pix = &buffer[index];
if ( (pix->r || pix->g || pix->b) )
c++;
}
}
return c;
}
void filtersmallclumps( bgra *out, bgra *buffer, int width, int height, int r, int s )
{
for (int y=0; y<height; y++)
{
for (int x=0; x<width; x++)
{
int c = count( buffer, x-r, y-r, x+r, y+r, width, height );
int index = y*width+x;
bgra *i = &buffer[index];
bgra *o = &out[index];
if ( c < s )
{
o->r = 0;
o->g = 0;
o->b = 0;
o->a = i->a;
} else
{
*o = *i;
}
}
}
}
#if 0
theta_d = sqrt(xd(1,:).^2 + xd(2,:).^2);
theta = theta_d; % initial guess
for kk=1:20,
theta = theta_d ./ (1 + k(1)*theta.^2 + k(2)*theta.^4);
end;
xd = x * ( 1 + k0*r*r + k1*r*r*r*r);
r = x*x+y*y;
x = xd / (1+k0*r + k1*r*r);
y = yd / (1+k0*r + k1*r*r);
#endif
void calcundistort( float &x, float &y, float xd, float yd, float k1, float k2 )
{
x = xd;
y = yd;
int it = 100;
while (it--)
{
float r = x*x+y*y;
x = xd / (1+k1*r + k2*r*r);
y = yd / (1+k1*r + k2*r*r);
}
}
void calcdistort( float &xd, float &yd, float x, float y, float k1, float k2 )
{
float r = x*x+y*y;
xd = x * (1+k1*r + k2*r*r);
yd = y * (1+k1*r + k2*r*r);
}
float lens[] = {
0.f,0.0f, 914.f, 578.f,
1.f,0.0f, 799.f, 578.f,
2.f,0.0f, 679.f, 578.f,
3.f,0.0f, 555.f, 578.f,
4.f,0.0f, 425.f, 578.f,
5.f,0.0f, 296.f, 578.f,
1.f,0.5f, 798.f, 524.f,
2.f,1.5f, 676.f, 405.f,
3.f,2.5f, 544.f, 281.f,
4.f,3.5f, 411.f, 149.f,
0.f,0.5f, 914.f, 520.f,
0.f,1.5f, 914.f, 405.f,
0.f,2.5f, 914.f, 281.f,
0.f,3.5f, 914.f, 144.f
};
float lenserr( float vec[2] )
{
float mid[] = {914.f, 578.f};
float len = 618.f;
float grid = 5.f;
float toterr = 0.f;
for (int i=0; i<14; i++)
{
float *l = &lens[i*4];
float xd, yd;
calcdistort( xd, yd, -l[0]/grid, -l[1]/grid, vec[0], vec[1] );
float tx = (l[2]-mid[0]) / len;
float ty = (l[3]-mid[1]) / len;
//calcundistort( fx, fy, tx, ty, vec[0], vec[1] );
float dx = tx-xd;
float dy = ty-yd;
//float dx = l[0]-fx;
//float dy = l[1]-fy;
float err = (dx*dx)+(dy*dy);
toterr += err;
}
return toterr;
}
// [0] -0.081594504 float
// [1] 0.080084130 float
float distortionFactor(float radius)
{
//float mCoefficients[2] = { 250.0F, 50000.0F };
float mCoefficients[2] = { 0.1526f, 0.01953125f };
float rSq = radius * radius;
return 1.0F + mCoefficients[0] * rSq + mCoefficients[1] * rSq * rSq;
}
float lenserr2( float vec[2], float lensvec[2] )
{
float mid[] = {914.f, 578.f};
float len = 618.f;
float grid = 5.f;
float toterr = 0.f;
for (int i=0; i<14; i++)
{
float *l = &lens[i*4];
float xd, yd;
calcdistort( xd, yd, -l[0]/grid, -l[1]/grid, vec[0], vec[1] );
float fx, fy;
calcdistort( fx, fy, xd, yd, lensvec[0], lensvec[1] );//-0.081594504f, 0.080084130f );
float tx = -l[0]/grid;//(l[2]-mid[0]) / len;
float ty = -l[1]/grid;//(l[3]-mid[1]) / len;
//calcundistort( fx, fy, tx, ty, vec[0], vec[1] );
float dx = tx-fx;
float dy = ty-fy;
//float dx = l[0]-fx;
//float dy = l[1]-fy;
float err = (dx*dx)+(dy*dy);
toterr += err;
}
return toterr;
}
int _tmain(int argc, _TCHAR* argv[])
{
float lensp[2] = {0.f,0.f};
{
int it = 100000;
while ( it-- )
{
float maxde = 0.f;
int besti = -1;
for (int i=0; i<2; i++)
{
float v[2] = {lensp[0], lensp[1]};
v[i] = lensp[i] - 0.01f;
float err0 = lenserr( v );
v[i] = lensp[i] + 0.01f;
float err1 = lenserr( v );
float de = (err1 - err0)/(2.f*0.01f);
//printf("%f: %f %f\n", de, err0, err1);
if ( fabsf(de) > fabsf(maxde) )
{
besti = i;
maxde = de;
}
}
if ( besti == -1 )
break;
lensp[besti] -= maxde * 0.01f;
}
lenserr(lensp);
printf("");
}
{
float p[2] = {0.f,0.f};
int it = 100000;
while ( it-- )
{
float maxde = 0.f;
int besti = -1;
for (int i=0; i<2; i++)
{
float v[2] = {p[0], p[1]};
v[i] = p[i] - 0.01f;
float err0 = lenserr2( v, lensp );
v[i] = p[i] + 0.01f;
float err1 = lenserr2( v, lensp );
float de = (err1 - err0)/(2.f*0.01f);
//printf("%f: %f %f\n", de, err0, err1);
if ( fabsf(de) > fabsf(maxde) )
{
besti = i;
maxde = de;
}
}
if ( besti == -1 )
break;
p[besti] -= maxde * 0.001f;
}
lenserr2(p, lensp);
//float df = distortionFactor(0.025f);//
float df = distortionFactor(1.f);//
float r = 1.f * 1.f;
float f = 1.f + p[0]*r + p[1]*r*r;
printf("%f %f", df, f);
//0.025F;
printf("");
}
{
for (int y=0; y<=10; y++)
{
for (int x=0; x<=10; x++)
{
float dx = (x-5.f)/5.f;
float dy = (y-5.f)/5.f;
float fx, fy;
calcundistort(fx,fy,dx,dy,0.22f, 0.24f);
calcdistort( dx,dy,fx, fy,0.22f, 0.24f);
printf( "%f, %f, %f, %f\n", fx, fy, dx, dy );
}
}
}
struct SimpleCapParams capture;
int c = setupESCAPI();
capture.mWidth = 640;
capture.mHeight = 480;
capture.mTargetBuf = new int[capture.mWidth*capture.mHeight];
int device = 0;
if ( c )
{
initCapture(device,&capture);
doCapture(device);
}
err_s e =
{
{
{ 0.f, 0.25f, 1.f },
{ -0.25f, 0.25f, 1.f },
{ -0.25f, -0.25f, 1.f },
{ 0.f, -0.25f, 1.f },
},
{
1.f, sqrtf(2.f), 1.f,
1.f, sqrtf(2.f),
1.f,
},
};
if ( c )
{
while ( 1 )
{
if (isCaptureDone(device))
{
// copy process more
// ..and ask for more
bgra *buffer = (bgra*)capture.mTargetBuf;
filtergreen( buffer, capture.mWidth, capture.mHeight );
bgra *f0 = new bgra[capture.mWidth * capture.mHeight];
filtersmallclumps( f0, buffer, capture.mWidth, capture.mHeight, 3, 5*5 );
stbi_write_png( "test0.png", capture.mWidth, capture.mHeight, 4, capture.mTargetBuf, capture.mWidth*4 );
stbi_write_png( "test1.png", capture.mWidth, capture.mHeight, 4, f0, capture.mWidth*4 );
doCapture(device);
}
Sleep( 1000 );
}
}
float d[4] = {3.f,3.f,3.f,3.f};
for (int i=0; i<10000; i++)
{
int index;
float t = derr( index, &e, d, 0.001f );
if ( index == -1 || fabsf(t) < 0.001f )
break;
printf( "%d %f\n", i, t );
d[index] += -t * 0.1f;
}
float ce = err( &e, d );
return 0;
}
#if 0
Img img0: DETECTED
Img img1: DETECTED
Img img2: DETECTED
Img img3: DETECTED
Img img4: DETECTED
Img img5: DETECTED
Img img6: DETECTED
7 valid images.
Img: img0: (x,y,z,yaw,pitch,roll)=(-0.1099,0.1909,0.4340,-176.30deg,-2.42deg,-170.08deg)
Img: img1: (x,y,z,yaw,pitch,roll)=(0.0527,-0.1730,0.3133,4.88deg,17.43deg,-146.16deg)
Img: img2: (x,y,z,yaw,pitch,roll)=(0.0271,0.2538,0.3655,174.58deg,-24.45deg,-151.71deg)
Img: img3: (x,y,z,yaw,pitch,roll)=(-0.1241,-0.1758,0.4540,-21.76deg,3.68deg,-154.57deg)
Img: img4: (x,y,z,yaw,pitch,roll)=(-0.0215,-0.3273,0.2617,3.82deg,5.31deg,-126.41deg)
Img: img5: (x,y,z,yaw,pitch,roll)=(-0.1485,0.2013,0.4338,-178.09deg,-0.69deg,-168.80deg)
Img: img6: (x,y,z,yaw,pitch,roll)=(-0.0567,0.2439,0.4136,-179.49deg,-4.89deg,-163.12deg)
[CAMERA_PARAMS]
resolution=[640 480]
cx=385.79400
cy=280.94590
fx=817.38841
fy=768.73963
dist=[6.950765e-002 -2.527250e-001 -1.659663e-004 2.404563e-002 0.000000e+000]
Average err. of reprojection: 0.945455 pixels
#endif
// runanalysis.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <float.h>
#include <time.h>
#include "pugixml.hpp"
#include <map>
#include <string>
#include <vector>
#include <io.h>
#include <algorithm>
#include "stb_truetype.h"
#include "stb_image_write.h"
#include <string>
char ttf_buffer[1<<20];
unsigned char temp_bitmap[512*512];
stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
void my_stbtt_initfont(void)
{
fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
stbtt_BakeFontBitmap((unsigned char*)ttf_buffer,0, 16.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
}
struct stbtt_aligned_quadint
{
int s0, t0, w, h;
float adv;
float xoff;
float yoff;
};
void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, stbtt_aligned_quadint *q)
{
stbtt_bakedchar *b = chardata + char_index;
q->xoff = b->xoff;
q->yoff = b->yoff;
q->s0 = b->x0;
q->t0 = b->y0;
q->w = b->x1 - b->x0;
q->h = b->y1 - b->y0;
q->adv = b->xadvance;
}
class image2d
{
unsigned int *m_abgr;
int width;
int height;
public:
image2d( int w, int h ) : width(w), height(h)
{
m_abgr = new unsigned int[ w * h ];
}
image2d() : m_abgr(NULL), width(0), height(0)
{
}
void setsize( int w, int h )
{
delete []m_abgr;
m_abgr = new unsigned int[ w * h ];
width = w;
height = h;
}
void write( const char *filename )
{
stbi_write_png( filename, width, height, 4, m_abgr, width * 4 );
}
void putpixel( int x, int y, unsigned int abgr )
{
if ( x >= 0 && y >= 0 && x < width && y < height )
{
int alpha = abgr >> 24;
int sb = (abgr>>16) & 0xff;
int sg = (abgr>>8) & 0xff;
int sr = (abgr>>0) & 0xff;
unsigned int dest = m_abgr[ y * width + x ];
int db = (dest>>16) & 0xff;
int dg = (dest>>8) & 0xff;
int dr = (dest>>0) & 0xff;
int fb = (alpha * sb + (255-alpha) * db)/255;
int fg = (alpha * sg + (255-alpha) * dg)/255;
int fr = (alpha * sr + (255-alpha) * dr)/255;
m_abgr[ y * width + x ] = (alpha << 24) | (fb<<16) | (fg<<8) | fr;
}
}
void line( int x0, int y0, int x1, int y1, unsigned int abgr )
{
int dx = x1-x0;
int dy = y1-y0;
int adx = abs( dx );
int ady = abs( dy );
if ( adx == 0 && ady == 0 )
{
putpixel( x0, y0, abgr );
} else
if ( adx > ady )
{
int dir = dx > 0 ? 1 : -1;
for (int x=0; x<=adx; x++)
{
int y = (dy*x)/(adx);
putpixel( x0+x*dir, y0+y, abgr );
}
}
else
{
int dir = dy > 0 ? 1 : -1;
for (int y=0; y<=ady; y++)
{
int x = (dx*y)/(ady);
putpixel( x0+x, y0+y*dir, abgr );
}
}
}
void print(float tx, float ty, const char *text, unsigned int abgr, int rotate )
{
while (*text) {
if (*text >= 32 && *text < 128) {
stbtt_aligned_quadint q;
stbtt_GetBakedQuad(cdata, 512,512, *text-32, &q);
for (int y=0; y<q.h; y++)
{
for (int x=0; x<q.w; x++)
{
int v = temp_bitmap[ (q.t0+y)*512 + (q.s0+x)];
if ( v )
{
if ( rotate )
{
putpixel( tx-(q.yoff+y), ty+q.xoff+x, abgr|(v<<24) );
} else
{
putpixel( tx+q.xoff+x, ty+q.yoff+y, abgr|(v<<24) );
}
}
}
}
if ( rotate )
{
ty += q.adv;
} else
{
tx += q.adv;
}
}
++text;
}
}
void clear( unsigned int abgr )
{
for (int i=0; i<width*height; i++)
{
m_abgr[i] = abgr;
}
}
void linegraph( float *value, int stride, int num, unsigned int abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f )
{
for (int i=1; i<num; i++)
{
float *last = (float*)((unsigned char*)value + ( (i-1)*stride ));
float *cur = (float*)((unsigned char*)value + ( i*stride ));
line( (i-1) * xscale + xoff, (*last) * yscale + yoff, i*xscale + xoff, (*cur) * yscale + yoff, abgr );
}
}
void bargraph( float *value, int stride, int num, unsigned int abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f )
{
for (int i=0; i<num; i++)
{
float *cur = (float*)((unsigned char*)value + ( i*stride ));
int x0 = (int)((i) * xscale + xoff);
int x1 = (int)((i+1) * xscale + xoff);
for (int j=x0; j<x1; j++)
{
line( j, yoff, j, (*cur) * yscale + yoff, abgr );
}
}
}
void splitgraph( float *value, int numsplits, int stride, int num, unsigned int *abgr, float xscale = 1.f, float yscale = 1.f, float xoff = 0.f, float yoff = 0.f )
{
for (int i=0; i<num; i++)
{
float *cur = (float*)((unsigned char*)value + ( i*stride ));
float tot = 0.f;
for (int j=0; j<numsplits; j++)
{
tot += cur[j];
}
float last = 0.f;
float run = 0.f;
for (int j=0; j<numsplits; j++)
{
run += cur[j];
line( i * xscale + xoff, (last/tot) * 100.f * yscale + yoff, i*xscale + xoff, (run/tot) * 100.f * yscale + yoff, abgr[j] );
last = run;
}
}
}
void xaxis( std::string *names, int stride, int num, unsigned int abgr, int skip, int y, float xscale = 1.f, float xoff = 0.f )
{
for (int i=0; i<num; i+=skip)
{
std::string *cur = (std::string*)((unsigned char*)names + ( i*stride ));
print( i*xscale+xoff, y, cur->c_str(), abgr, 1 );
}
}
};
struct ehack_s
{
const char *date;
int timeM;
int intensity;
};
ehack_s ehack[] =
{
{ "2012-11-24", 50, 80 }, // event
{ "2012-11-24", 90, 70 }, // event
{ "2012-11-24", 25, 80 }, // event
{ "2012-12-28", 60, 80 }, // ct
{ "2012-12-29", 60, 80 }, // ct
{ "2012-12-31", 60, 80 }, // ct
{ "2013-01-04", 60, 80 }, // ct
{ "2013-01-13", 45, 70 }, // bike
{ "2013-01-13", 30, 80 }, // ct
{ "2013-01-20", 30, 80 }, // ct
{ "2013-01-26", 53, 90 }, // event
{ "2013-01-26", 75, 80 }, // event
{ "2013-01-26", 27, 90 }, // event
{ NULL },
};
struct speedToEffort_s
{
float speed;
int effort;
};
const speedToEffort_s speedToEffort_orig[] =
{
{ 0.f, 0 },
{ 1.f, 20 }, // 1
{ 8.f, 40 }, // 3
{ 11.f, 50 }, // 4
{ 11.75f, 60 }, // 5
{ 12.25f, 70 }, // 6
{ 13.f, 80 }, // 7
{ 14.7f, 100 }, // 8
{ 15.8f, 120 }, // 9
{ FLT_MAX, 140 }, // 10
};
const speedToEffort_s speedToEffort[] =
{
{ 0.f, 0 },
{ 1.f, 20 }, // 1
{ 8.f, 40 }, // 3
{ 11.f, 50 }, // 4
{ 11.75f, 60 }, // 5
{ 12.25f, 70 }, // 6
{ 13.f, 80 }, // 7
{ 14.1f, 100 }, // 8
{ 15.0f, 120 }, // 9
{ FLT_MAX, 140 }, // 10
};
const speedToEffort_s speedToEffort_high[] =
{
{ 0.f, 0 },
{ 1.f, 20 }, // 1
{ 8.f, 50 }, // 3
{ 11.f, 60 }, // 4
{ 11.75f, 70 }, // 5
{ 12.25f, 80 }, // 6
{ 13.f, 100 }, // 7
{ 14.7f, 120 }, // 8
{ 15.8f, 140 }, // 9
{ FLT_MAX, 140 }, // 10
};
const int speedToEffortNum = sizeof(speedToEffort) / sizeof(speedToEffort[0]);
char *readtextfile( const char *filename, int pad )
{
FILE *f = fopen( filename, "rb" );
if ( f )
{
fseek( f, 0, SEEK_END );
int l = ftell( f );
fseek( f, 0, SEEK_SET );
char *mem = (char*)malloc( l + 1 + 16 );
mem[l] = 0;
fread( mem, 1, l, f );
fclose( f );
return mem;
}
return NULL;
}
int determineEffort( float kmh )
{
for (int i=0; i<speedToEffortNum; i++)
{
if ( kmh < speedToEffort[i+1].speed )
{
return speedToEffort[i].effort;
}
}
return 0;
}
float calculateTSS( float kmh, float sec )
{
return sec / 3600.f * determineEffort( kmh );
}
void fixupbadelement( char *text )
{
char *f = strstr( text, "<nodes>" );
if ( f )
{
f = strstr( f+1, "<nodes>" );
if ( f )
{
strcpy( f, "</nodes>" );
}
}
}
__time32_t dateToInt( __time32_t &week, std::string &strDate, const char *dstr )
{
//2012-12-19
int y, m, d;
if ( sscanf( dstr, "%04d-%02d-%02dT", &y, &m, &d ) )
{
tm t;
memset( &t, 0, sizeof(t) );
t.tm_year = y - 1900;
t.tm_mday = d - 1;
t.tm_mon = m - 1;
__time32_t res = _mktime32( &t );
if ( res < 0 )
printf("");
char buffer[64];
sprintf( buffer, "%04d-%02d-%02d", y, m, d );
strDate = buffer;
week = res - 86400 * t.tm_wday;
return res;
}
else
{
strDate = "";
return 0;
}
}
struct alt_s
{
float time;
float alt;
};
float calculateGrade( float time, float kph, std::vector<alt_s> const &altSamples )
{
static int cacheI = 0;
if ( cacheI >= altSamples.size() )
cacheI = 0;
int i = 0;
if ( cacheI && time > altSamples[cacheI-1].time )
{
i = cacheI;
}
for (; i<altSamples.size(); i++)
{
if ( time < altSamples[i].time )
{
if ( i > 2 && i < (altSamples.size()-2) )
{
cacheI = i;
float vertChange = altSamples[i+2].alt - altSamples[i-2].alt;
float deltaTime = altSamples[i+2].time - altSamples[i-2].time;
float deltaDist = (kph * 1000.f) / (60.f*60.f) * deltaTime;
float grade = deltaDist > 0.f ? vertChange / deltaDist : 0.f;
if ( grade > 0.1f )
grade = 0.1f;
if ( grade < -0.1f )
grade = -0.1f;
return grade * 100.f;
}
else
{
return 0.f;
}
}
}
return 0.f;
}
inline float maxf( float a, float b )
{
return a>b ? a : b;
}
float gradeAdjustedPace( float time, float kph, std::vector<alt_s> const &altSamples )
{
float grade = calculateGrade( time, kph, altSamples );
if ( grade >= 0.f )
{
return maxf( 0.f, kph / ( 1.f - grade * 0.03f ) );
}
else
{
return maxf( 0.f, kph / ( 1.f - grade * 0.03f * 0.5f ) );
}
}
bool calculateTSS( float &tss, float &totalSec, float &effortArea, __time32_t &date, __time32_t &week, std::string &strDate, float *areas, const char *filename )
{
tss = 0.f;
totalSec = 0.f;
effortArea = 0.f;
char *text = readtextfile( filename, 16 );
if ( text == NULL )
return false;
fixupbadelement( text );
pugi::xml_document doc;
if ( doc.load_buffer( text, strlen(text) ) )
{
int totalSamples = 0;
int samplesAbove100 = 0;
int duration = doc.child("nodes").child("activity").child("duration").text().as_int();
std::vector<alt_s> altSamples;
for ( pugi::xml_node node = doc.child("nodes").child("activity").child("geo").child("waypoints").child("node"); node; node = node.next_sibling( "node" ) )
{
alt_s a;
a.alt = node.child("ele").text().as_float();
a.time = 0.f;
altSamples.push_back( a );
}
for (unsigned int i=0; i<altSamples.size(); i++)
{
altSamples[i].time = ((i * duration)/1000.f)/(altSamples.size()-1);
}
pugi::xml_node time = doc.child("nodes").child("activity").child("startTimeUtc");
date = dateToInt( week, strDate, time.text().as_string() );
pugi::xml_node history = doc.child("nodes").child("activity").child("history");
for ( pugi::xml_node node = history.child( "node" ); node; node = node.next_sibling( "node" ) )
{
if ( strstr( node.child( "type" ).text().as_string(), "SPEED" ) )
{
float interval = node.child( "intervalMetric" ).text().as_float();
float lastKPH = 0.f;
for ( pugi::xml_node vnode = node.child( "values" ).child("node"); vnode; vnode = vnode.next_sibling( "node" ) )
{
float kph = vnode.text().as_float();
if ( kph == 0.f )
{
kph = lastKPH;
}
if ( kph > 0.f )
{
if ( determineEffort( kph ) >= 100 )
{
samplesAbove100 ++;
}
areas[determineEffort( kph )/10] += interval/60.f;
//float grade = calculateGrade( totalSec, kph, altSamples );
//float adjustedKPH = gradeAdjustedPace( totalSec, kph, altSamples );
//printf( "effort %d\n", );
tss += calculateTSS( gradeAdjustedPace( totalSec, kph, altSamples ), interval );
totalSec += interval;
lastKPH = kph;
totalSamples ++;
}
}
}
}
if ( totalSamples )
{
effortArea = (float)samplesAbove100 / totalSamples;
}
//printf( "TSS %.2f TIME %.1f min\n", tss, totalSec/60.f );
free( text );
return true;
}
else
{
free( text );
return false;
}
}
bool calculateTSS( float &tss, float &totalSec, float &effortArea, __time32_t &date, __time32_t &week, std::string &strDate, float *areas, ehack_s &hack )
{
tss = 0.f;
totalSec = 0.f;
effortArea = 0.f;
{
int samplesAbove100 = 0;
date = dateToInt( week, strDate, hack.date );
float interval = hack.timeM * 60.f;
if ( hack.intensity >= 100 )
{
samplesAbove100 ++;
}
areas[hack.intensity/10] += interval/60.f;
tss += hack.intensity * interval / (60.f*60.f);
totalSec += interval;
effortArea = (float)samplesAbove100;
return true;
}
}
char fixseparator( char c )
{
return ( c == '/' ) ? '\\' : c;
}
void findFiles( std::vector< std::string > &files, const char *pattern )
{
std::string path = pattern;
std::transform( path.begin(), path.end(), path.begin(), fixseparator );
std::string::size_type pos = path.find_last_of( '\\' );
if ( pos != std::string::npos )
{
path = path.substr( 0, pos );
}
else
{
path = ".\\";
}
_finddata_t fi;
intptr_t fh = _findfirst( pattern, &fi );
if ( fh != -1 )
{
do
{
files.push_back( path + "\\" + fi.name );
}
while ( _findnext( fh, &fi ) == 0 );
_findclose( fh );
}
}
struct dailyscore_s
{
float totalTSS;
float totalSec;
float effortAreaSec;
std::string date;
float areas[15];
dailyscore_s() : totalTSS(0.f), totalSec(0.f), effortAreaSec(0.f) { memset( areas, 0, sizeof(areas) );}
};
struct graphscore_s
{
float totalTSS;
float totalSec;
std::string date;
float areas[15];
float ctl;
float atl;
float tsb;
};
int maxi( int a, int b )
{
return (a>b) ? a : b;
}
int mini( int a, int b )
{
return (a<b) ? a : b;
}
void genscores( const char *statscsv, const char *statsdat, std::map< __time32_t, dailyscore_s > const &scores, int deltaDays, __time32_t curtime )
{
image2d ctlatlGraph;
float CTLy = 0.f;
float ATLy = 0.f;
float MINy = 0.f;
float AREAy = 0.f;
int count = 1;
std::map<__time32_t, dailyscore_s >::const_iterator it = scores.cbegin();
__time32_t curTime = it->first;
it = scores.cend();
it--;
__time32_t endTime = it->first;
FILE *dat = fopen( statsdat, "wb" );
FILE *csv = fopen( statscsv, "wb" );
if ( csv )
fprintf( csv, "\"DATE\",\"CTL\",\"ATL\",\"TSB\",\"TSS\",\"MIN\",\"MIN/av\",\"PCNT\",\"PCNT/av\",\"z0\",\"z1\",\"z2\",\"z3\",\"z4\",\"z5\",\"z6\",\"z7\",\"z8\",\"z9\",\"z10\",\"z11\",\"z12\",\"z13\",\"z14\"\n" );
int index = 0;
std::vector< graphscore_s > graphData;
for ( ;curTime <= curtime/*endTime*/; curTime+=(86400*deltaDays), count++ )//it != dailyscore.cend() )
{
it = scores.find( curTime );
float CTL;
float ATL;
float PCNT;
float TSS;
float MIN;
float AREA;
float totalMin;
float areas[15];
if ( it == scores.end() )
{
CTL = CTLy + (0.f - CTLy) / mini( (42/deltaDays), count );
ATL = ATLy + (0.f - ATLy) / mini( (7/deltaDays), count );
MIN = MINy + (0.f - MINy) / mini( (7/deltaDays), count );
AREA = AREAy + (0.f - AREAy) / mini( (7/deltaDays), count );
PCNT = 0.f;
TSS = 0.f;
totalMin = 0.f;
memset( areas, 0, sizeof(areas) );
}
else
{
CTL = CTLy + (it->second.totalTSS - CTLy) / mini( (42/deltaDays), count );
ATL = ATLy + (it->second.totalTSS - ATLy) / mini( (7/deltaDays), count );
MIN = MINy + ((it->second.totalSec / 60.f) - MINy) / mini( (7/deltaDays), count );
PCNT = 100.f*it->second.effortAreaSec/it->second.totalSec;
AREA = AREAy + (PCNT - AREAy) / mini( (7/deltaDays), count );
TSS = it->second.totalTSS;
totalMin = it->second.totalSec / 60.f;
memcpy( areas, it->second.areas, sizeof(areas) );
}
char outtime[256];
__time32_t t = curTime + 86400;
strftime( outtime, sizeof(outtime), "%a %Y-%m-%d", _localtime32( &t ) );
float TSB = CTL - ATL;
graphscore_s gs;
memcpy( gs.areas, areas, sizeof(gs.areas) );
gs.ctl = CTL/(float)deltaDays;
gs.atl = ATL/(float)deltaDays;
gs.tsb = TSB/(float)deltaDays;
gs.date = outtime;
graphData.push_back( gs );
if ( csv )
{
fprintf( csv, "\"%s\",%.1f,%.2f,%.2f,%.2f,%.1f,%.1f,%.2f,%.2f", outtime, CTL, ATL, TSB, TSS, totalMin, MIN, PCNT, AREAy );
for (int j=0; j<15; j++)
fprintf( csv, ",%1.f", areas[j] );
fprintf( csv, "\n" );
}
if ( dat )
{
fprintf( dat, "%s %d %.1f %.2f %.2f %.2f %.1f %.1f %.2f,%.2f", outtime, index, CTL, ATL, TSB, TSS, totalMin, MIN, PCNT, AREAy );
for (int j=0; j<15; j++)
fprintf( dat, ",%1.f", areas[j] );
fprintf( dat, "\n" );
}
printf( "\"%s\",%.1f,%.2f,%.2f,%.2f,%.2f,%.1f,%.1f,%.2f,%.2f", outtime, CTL, ATL, TSB, TSS/totalMin, TSS, totalMin, MIN, PCNT, AREAy );
for (int j=0; j<15; j++)
printf( ",%1.f", areas[j] );
printf( "\n" );
CTLy = CTL;
ATLy = ATL;
MINy = MIN;
AREAy = AREA;
index++;
}
if ( csv )
fclose( csv );
if ( dat )
fclose( dat );
int height = 250;
int graphAxis = height - 100;
int textAxis = height - 100;
ctlatlGraph.setsize( graphData.size() * 2, height );
ctlatlGraph.bargraph( &graphData[0].tsb, sizeof(graphscore_s), graphData.size(), 0xff00ff00, 2.f, -1.f, 0.f, graphAxis/2 );
ctlatlGraph.linegraph( &graphData[0].ctl, sizeof(graphscore_s), graphData.size(), 0xff0000ff, 2.f, -1.f, 0.f, graphAxis );
ctlatlGraph.linegraph( &graphData[0].atl, sizeof(graphscore_s), graphData.size(), 0xffff0000, 2.f, -1.f, 0.f, graphAxis );
ctlatlGraph.xaxis( &graphData[0].date, sizeof(graphscore_s), graphData.size(), 0x00ffffffff, graphData.size()/40, textAxis, 2.f );
ctlatlGraph.write( "ctl.png" );
}
int _tmain(int argc, _TCHAR* argv[])
{
my_stbtt_initfont();
std::vector<std::string> files;
findFiles( files, argv[1] );
std::map< __time32_t, dailyscore_s > dailyscore;
std::map< __time32_t, dailyscore_s > weeklyscore;
tm curtime;
_getsystime( &curtime );
__time32_t curtimeValue = _mktime32( &curtime );
ehack_s *cur = ehack;
while ( cur->date )
{
float tss, sec, ea;
__time32_t date;
__time32_t week;
std::string strDate;
float areas[15];
memset( areas, 0, sizeof(areas) );
if ( calculateTSS( tss, sec, ea, date, week, strDate, areas, *cur ) )
{
{
dailyscore_s &ds = dailyscore[date];
ds.totalTSS += tss;
ds.totalSec += sec;
ds.effortAreaSec += ea * sec;
ds.date = strDate;
for (int j=0; j<15; j++)
{
ds.areas[j] += areas[j];
}
}
{
dailyscore_s &ws = weeklyscore[week];
ws.totalTSS += tss;
ws.totalSec += sec;
ws.effortAreaSec += ea * sec;
ws.date = strDate;
for (int j=0; j<15; j++)
{
ws.areas[j] += areas[j];
}
}
}
cur++;
}
for (unsigned int i=0; i<files.size(); i++)
{
float tss, sec, ea;
__time32_t date;
__time32_t week;
std::string strDate;
float areas[15];
memset( areas, 0, sizeof(areas) );
if ( calculateTSS( tss, sec, ea, date, week, strDate, areas, files[i].c_str() ) )
{
{
dailyscore_s &ds = dailyscore[date];
ds.totalTSS += tss;
ds.totalSec += sec;
ds.effortAreaSec += ea * sec;
ds.date = strDate;
for (int j=0; j<15; j++)
{
ds.areas[j] += areas[j];
}
}
{
dailyscore_s &ws = weeklyscore[week];
ws.totalTSS += tss;
ws.totalSec += sec;
ws.effortAreaSec += ea * sec;
ws.date = strDate;
for (int j=0; j<15; j++)
{
ws.areas[j] += areas[j];
}
}
}
}
float CTLy = 0.f;
float ATLy = 0.f;
float MINy = 0.f;
float AREAy = 0.f;
int count = 1;
std::map<__time32_t, dailyscore_s >::const_iterator it = dailyscore.cbegin();
__time32_t curTime = it->first;
it = dailyscore.cend();
it--;
__time32_t endTime = it->first;
genscores( "stats_day.csv", "stats_day.dat", dailyscore, 1, curtimeValue );
genscores( "stats_wk.csv", "stats_wk.dat", weeklyscore, 7, curtimeValue );
return 0;
}
// serialisation.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string.h>
#include <vector>
#define SERIALISE_TYPEINFO(THISCLASS,PARENTCLASS) \
typedef THISCLASS ThisClass; \
typedef PARENTCLASS SuperClass; \
\
struct Creator \
{ \
const char *(*name_f)(); \
ThisClass *(*creator_f)(); \
Creator *next; \
}; \
\
static Creator *s_subClassCreators; \
\
virtual const char *className() \
{ \
return #THISCLASS; \
} \
static const char *staticClassName() \
{ \
return #THISCLASS; \
} \
template <class C> \
static C* staticCreator() \
{ \
return new ThisClass; \
} \
static ThisClass* create( const char *name ) \
{ \
ThisClass::Creator *curCreator = ThisClass::s_subClassCreators; \
while ( curCreator ) \
{ \
if ( strcmp( curCreator->name_f(), name ) == 0 ) \
{ \
return curCreator->creator_f(); \
} \
curCreator = curCreator->next; \
} \
return NULL; \
} \
static void registerCreator( const char *(*name_f)(), ThisClass *(*creator_f)() ) \
{ \
ThisClass::Creator *creator = new ThisClass::Creator; \
creator->name_f = name_f; \
creator->creator_f = creator_f; \
creator->next = ThisClass::s_subClassCreators; \
ThisClass::s_subClassCreators = creator; \
}
#define SERIALISE_TYPEINFO_INST(THISCLASS,PARENTCLASS) \
THISCLASS::Creator *THISCLASS::s_subClassCreators = NULL;
#define SERIALISE_NVP(a) #a, a
#include <string>
class Serialiser
{
public:
enum
{
FILTER_WRITEDATA = 1,
FILTER_VISITTOKEN = 2,
FILTER_WRITEENTER = 4,
};
virtual bool IsLoad() = 0;
virtual std::string GetClassType() = 0;
virtual void SetClassType( const char *type ) = 0;
virtual void Enter( const char *name ) = 0;
virtual void Serialise( const char *name, float &v ) = 0;
virtual void Serialise( const char *name, int &v ) = 0;
virtual void Serialise( const char *name, unsigned int &v ) = 0;
virtual void Serialise( const char *name, float *v, int num ) = 0;
virtual void Serialise( const char *name, int *v, int num ) = 0;
virtual void Serialise( const char *name, unsigned int *v, int num ) = 0;
virtual void Exit( const char *name ) = 0;
virtual bool VisitToken( void *&visitToken, void *&ptr ) = 0;
virtual void Visited( void *visitToken, void *ptr ) = 0;
virtual void FilterEnter( unsigned int mask ) { }
virtual unsigned int FilterWrite() { return FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER; }
virtual void FilterExit( unsigned int mask ) { }
};
void SERIALISE( Serialiser &s, const char *name, float &c )
{
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) )
return;
s.Serialise( name, c );
}
void SERIALISE( Serialiser &s, const char *name, int &c )
{
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) )
return;
s.Serialise( name, c );
}
void SERIALISE( Serialiser &s, const char *name, unsigned int &c )
{
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) )
return;
s.Serialise( name, c );
}
template <class C>
void SERIALISE( Serialiser &s, const char *name, std::vector<C> &c )
{
if ( !(s.FilterWrite() & Serialiser::FILTER_WRITEDATA) )
return;
s.Enter( name );
unsigned int num = c.size();
s.Serialise( "count", num );
c.resize( num );
for (unsigned int i=0; i<num; i++)
{
SERIALISE( s, "entry", c[i] );
}
s.Exit( name );
}
template <class C>
void SERIALISE( Serialiser &s, const char *name, C* &c, unsigned int filterMask = 0 )
{
s.FilterEnter( filterMask );
unsigned int validToOutput = s.FilterWrite();
void* visitToken;
if ( validToOutput & Serialiser::FILTER_VISITTOKEN )
{
if ( s.VisitToken( visitToken, (void*&)c ) )
{
s.FilterExit( filterMask );
return;
}
}
if ( validToOutput & Serialiser::FILTER_WRITEDATA )
{
if ( s.IsLoad() )
{
std::string className = s.GetClassType();
if ( className.empty() )
{
c = NULL;
s.FilterExit( filterMask );
return;
}
c = C::create( className.c_str() );
}
else
{
if ( c == NULL )
{
s.SetClassType( "" );
s.FilterExit( filterMask );
return;
}
else
{
s.SetClassType( c->className() );
}
}
s.Visited( visitToken, c );
}
if ( validToOutput & Serialiser::FILTER_WRITEENTER )
{
s.Enter( name );
c->Serialise( s );
s.Exit( name );
}
s.FilterExit( filterMask );
}
template <class C>
void SERIALISE( Serialiser &s, const char *name, C &c, unsigned int filterMask = 0 )
{
s.Enter( name );
c.Serialise( s );
s.Exit( name );
}
#include <map>
class VisitDictionary
{
std::map<void*, void*> m_written;
public:
virtual void* VisitToken( void *&visitToken )
{
void *out = m_written[visitToken];
return out;
}
virtual void Visited( void *visitToken, void *ptr )
{
m_written[visitToken] = ptr;
}
};
class BINSerialiserO : public Serialiser
{
FILE *m_f;
VisitDictionary *m_visit;
public:
BINSerialiserO( const char *filename, VisitDictionary *visit ) : m_visit(visit)
{
m_f = fopen( filename, "wb" );
}
~BINSerialiserO()
{
fclose(m_f);
}
virtual bool IsLoad()
{
return false;
}
virtual std::string GetClassType()
{
return "";
}
virtual void SetClassType( const char *ct )
{
int len = strlen( ct );
fwrite( &len, 1, sizeof(len), m_f );
fwrite( ct, 1, len, m_f );
}
virtual void Enter( const char *name )
{
}
virtual void Serialise( const char *name, float &v )
{
fwrite( &v, 1, sizeof(v), m_f );
}
virtual void Serialise( const char *name, int &v )
{
fwrite( &v, 1, sizeof(v), m_f );
}
virtual void Serialise( const char *name, unsigned int &v )
{
fwrite( &v, 1, sizeof(v), m_f );
}
virtual void Serialise( const char *name, float *v, int num )
{
fwrite( v, 1, sizeof(v[0])*num, m_f );
}
virtual void Serialise( const char *name, int *v, int num )
{
fwrite( v, 1, sizeof(v[0])*num, m_f );
}
virtual void Serialise( const char *name, unsigned int *v, int num )
{
fwrite( v, 1, sizeof(v[0])*num, m_f );
}
virtual void Exit( const char *name )
{
}
virtual bool VisitToken( void *&visitToken, void *&ptr )
{
visitToken = ptr;
bool res = ptr ? m_visit->VisitToken( visitToken ) != NULL : false;
fwrite( &visitToken, 1, sizeof(visitToken), m_f );
return res;
}
virtual void Visited( void *visitToken, void *ptr )
{
m_visit->Visited( visitToken, ptr );
}
};
class BINSerialiserO_Core : public BINSerialiserO
{
bool m_outputEnabled;
public:
BINSerialiserO_Core( const char *filename, VisitDictionary *visit ) : BINSerialiserO( filename, visit ), m_outputEnabled(true) {}
virtual void FilterEnter( unsigned int mask ) { if ( mask ) m_outputEnabled = false; }
virtual unsigned int FilterWrite() { return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_VISITTOKEN; }
virtual void FilterExit( unsigned int mask ) { if ( mask ) m_outputEnabled = true; }
};
class BINSerialiserO_Ext : public BINSerialiserO
{
bool m_outputEnabled;
public:
BINSerialiserO_Ext( const char *filename, VisitDictionary *visit ) : BINSerialiserO( filename, visit ), m_outputEnabled(false) {}
virtual void FilterEnter( unsigned int mask )
{
if ( mask ) m_outputEnabled = true;
}
virtual unsigned int FilterWrite()
{
return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_WRITEENTER;
}
virtual void FilterExit( unsigned int mask )
{
if ( mask ) m_outputEnabled = false;
}
};
class BINSerialiserI : public Serialiser
{
FILE *m_f;
VisitDictionary *m_visit;
public:
BINSerialiserI( const char *filename, VisitDictionary *visit ) : m_visit(visit)
{
m_f = fopen( filename, "rb" );
}
~BINSerialiserI()
{
fclose(m_f);
}
virtual bool IsLoad()
{
return true;
}
virtual std::string GetClassType()
{
int len;
fread( &len, 1, sizeof(len), m_f );
std::string str;
str.resize(len);
fread( &str[0], 1, len, m_f );
return str;
}
virtual void SetClassType( const char *ct )
{
}
virtual void Enter( const char *name )
{
}
virtual void Serialise( const char *name, float &v )
{
fread( &v, 1, sizeof(v), m_f );
}
virtual void Serialise( const char *name, int &v )
{
fread( &v, 1, sizeof(v), m_f );
}
virtual void Serialise( const char *name, unsigned int &v )
{
fread( &v, 1, sizeof(v), m_f );
}
virtual void Exit( const char *name )
{
}
virtual bool VisitToken( void *&visitToken, void *&ptr )
{
fread( &visitToken, 1, sizeof(visitToken), m_f );
ptr = m_visit->VisitToken( visitToken );
return ptr ? true : false;
}
virtual void Visited( void *visitToken, void *ptr )
{
m_visit->Visited( visitToken, ptr );
}
};
class BINSerialiserI_Core : public BINSerialiserI
{
bool m_outputEnabled;
public:
BINSerialiserI_Core( const char *filename, VisitDictionary *visit ) : BINSerialiserI( filename, visit ), m_outputEnabled(true) {}
virtual void FilterEnter( unsigned int mask ) { if ( mask ) m_outputEnabled = false; }
virtual unsigned int FilterWrite() { return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_VISITTOKEN; }
virtual void FilterExit( unsigned int mask ) { if ( mask ) m_outputEnabled = true; }
};
class BINSerialiserI_Ext : public BINSerialiserI
{
bool m_outputEnabled;
public:
BINSerialiserI_Ext( const char *filename, VisitDictionary *visit ) : BINSerialiserI( filename, visit ), m_outputEnabled(false) {}
virtual void FilterEnter( unsigned int mask )
{
if ( mask ) m_outputEnabled = true;
}
virtual unsigned int FilterWrite()
{
return m_outputEnabled ? FILTER_WRITEDATA|FILTER_VISITTOKEN|FILTER_WRITEENTER : FILTER_WRITEENTER;
}
virtual void FilterExit( unsigned int mask )
{
if ( mask ) m_outputEnabled = false;
}
};
struct B
{
SERIALISE_TYPEINFO(B,B);
virtual void Serialise( Serialiser &s )
{
}
};
SERIALISE_TYPEINFO_INST(B,B);
struct channel
{
std::vector< float > bigData;
SERIALISE_TYPEINFO(channel,channel);
virtual void Serialise( Serialiser &s )
{
SERIALISE( s, SERIALISE_NVP(bigData) );
}
};
SERIALISE_TYPEINFO_INST(channel,channel);
struct classA
{
float x, y, z;
B *ca;
B *cb;
channel *chan;
B c;
public:
classA() : x(0.f), y(0.f), z(0.f), ca(NULL), cb(NULL), chan(NULL)
{
}
SERIALISE_TYPEINFO(classA,classA);
virtual void Serialise( Serialiser &s )
{
SERIALISE( s, SERIALISE_NVP(x) );
SERIALISE( s, SERIALISE_NVP(y) );
SERIALISE( s, SERIALISE_NVP(z) );
SERIALISE( s, SERIALISE_NVP(ca) );
SERIALISE( s, SERIALISE_NVP(cb) );
SERIALISE( s, SERIALISE_NVP(c) );
SERIALISE( s, SERIALISE_NVP(chan), 1 );
}
};
SERIALISE_TYPEINFO_INST(classA,classA)
struct classB : public classA
{
float a, b;
public:
classB() : a(-1.f), b(1.f) {}
SERIALISE_TYPEINFO(classB,classA);
virtual void Serialise( Serialiser &s )
{
SuperClass::Serialise( s );
SERIALISE( s, SERIALISE_NVP(a) );
SERIALISE( s, SERIALISE_NVP(b) );
}
};
SERIALISE_TYPEINFO_INST(classB,classA)
template <class T, class C >
void Register()
{
T::registerCreator( C::staticClassName, C::staticCreator<T> );
if ( T::SuperClass::staticClassName != T::staticClassName )
{
Register<T::SuperClass,C>();
}
}
class XMLSerialiserO : public Serialiser
{
FILE *m_f;
std::string m_curClass;
public:
XMLSerialiserO( const char *filename )
{
m_f = fopen( filename, "wb" );
}
~XMLSerialiserO()
{
fclose(m_f);
}
virtual bool IsLoad()
{
return false;
}
virtual std::string GetClassType()
{
return "";
}
virtual void SetClassType( const char *ct )
{
m_curClass = ct;
}
virtual void Enter( const char *name )
{
fprintf( m_f, "<%s classname=\"%s\">\n", name, m_curClass.c_str() );
}
virtual void Serialise( const char *name, float &v )
{
fprintf( m_f, "<%s>%f</%s>\n", name, v, name );
}
virtual void Serialise( const char *name, int &v )
{
fprintf( m_f, "<%s>%d</%s>\n", name, v, name );
}
virtual void Serialise( const char *name, unsigned int &v )
{
fprintf( m_f, "<%s>%d</%s>\n", name, v, name );
}
virtual void Exit( const char *name )
{
fprintf( m_f, "</%s>\n", name, m_curClass.c_str() );
}
virtual bool VisitToken( void *&visitToken, void *&ptr )
{
visitToken = ptr;
return false;
}
virtual void Visited( void *visitToken, void *ptr )
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Register<classA,classA>();
Register<classB,classB>();
Register<B,B>();
Register<channel,channel>();
{
classA *a = classA::create( "classB" );
a->ca = B::create( "B" );
a->cb = a->ca;
a->chan = channel::create( "channel" );
a->chan->bigData.resize( 100 );
VisitDictionary dict;
{
BINSerialiserO_Ext ps("test_ext.bin", &dict);
SERIALISE( ps, "bin", a );
}
{
BINSerialiserO_Core ps("test.bin", &dict);
SERIALISE( ps, "bin", a );
}
{
XMLSerialiserO ps( "test.xml" );
SERIALISE( ps, "bin", a );
}
}
{
VisitDictionary dict;
classA *a;
{
BINSerialiserI_Core ps("test.bin", &dict);
SERIALISE( ps, "bin", a );
}
{
BINSerialiserI_Ext ps("test_ext.bin", &dict);
SERIALISE( ps, "bin", a );
}
printf("");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment