|
|
@@ -65,7 +65,8 @@ static const uint32_t *unichars; |
|
|
|
#define RANGE_W 4000 |
|
|
|
#define RANGE_H 4000 |
|
|
|
|
|
|
|
/* How does the algorithm work: one point per cell, or two */ |
|
|
|
/* How does the algorithm work: one point per cell, or two? XXX: changing |
|
|
|
* this value breaks compatibility with other images. */ |
|
|
|
#define POINTS_PER_CELL 2 |
|
|
|
|
|
|
|
/* |
|
|
@@ -128,6 +129,47 @@ static int npoints = 0; |
|
|
|
/* Global triangulation */ |
|
|
|
static Delaunay_triangulation dt; |
|
|
|
|
|
|
|
/* |
|
|
|
* Bit allocation handling |
|
|
|
*/ |
|
|
|
|
|
|
|
void compute_ranges(int width, int height) |
|
|
|
{ |
|
|
|
TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2); |
|
|
|
HEADER_BITS = logf(RANGE_W * RANGE_H) / logf(2); |
|
|
|
DATA_BITS = TOTAL_BITS - HEADER_BITS; |
|
|
|
#if POINTS_PER_CELL == 1 |
|
|
|
CELL_BITS = logf(RANGE_SYXRGB) / logf(2); |
|
|
|
#else |
|
|
|
// TODO: implement the following shit |
|
|
|
//float coord_bits = logf((RANGE_Y * RANGE_X) * (RANGE_Y * RANGE_X + 1) / 2); |
|
|
|
//float other_bits = logf(RANGE_R * RANGE_G * RANGE_B * RANGE_S); |
|
|
|
//CELL_BITS = (coord_bits + 2 * other_bits) / logf(2); |
|
|
|
CELL_BITS = 2 * logf(RANGE_SYXRGB) / logf(2); |
|
|
|
#endif |
|
|
|
TOTAL_CELLS = (int)(DATA_BITS / CELL_BITS); |
|
|
|
MAX_ITERATIONS = ITERATIONS_PER_POINT * POINTS_PER_CELL * TOTAL_CELLS; |
|
|
|
|
|
|
|
/* Compute "best" w/h ratio */ |
|
|
|
dw = 1; dh = TOTAL_CELLS; |
|
|
|
for(unsigned int i = 1; i <= TOTAL_CELLS; i++) |
|
|
|
{ |
|
|
|
int j = TOTAL_CELLS / i; |
|
|
|
|
|
|
|
float r = (float)width / (float)height; |
|
|
|
float ir = (float)i / (float)j; |
|
|
|
float dwr = (float)dw / (float)dh; |
|
|
|
|
|
|
|
if(fabs(logf(r / ir)) < fabs(logf(r / dwr))) |
|
|
|
{ |
|
|
|
dw = i; |
|
|
|
dh = TOTAL_CELLS / dw; |
|
|
|
} |
|
|
|
} |
|
|
|
while((dh + 1) * dw <= TOTAL_CELLS) dh++; |
|
|
|
while(dh * (dw + 1) <= TOTAL_CELLS) dw++; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* Unicode stuff handling |
|
|
|
*/ |
|
|
@@ -444,12 +486,8 @@ static inline float int2fullrange(int val, int range) |
|
|
|
|
|
|
|
static inline void index2cell(int index, int *dx, int *dy) |
|
|
|
{ |
|
|
|
// This check will be used once we add points to our list |
|
|
|
//if(index < dw * dh * POINTS_PER_CELL) |
|
|
|
{ |
|
|
|
*dx = (index / POINTS_PER_CELL) % dw; |
|
|
|
*dy = (index / POINTS_PER_CELL) / dw; |
|
|
|
} |
|
|
|
*dx = (index / POINTS_PER_CELL) % dw; |
|
|
|
*dy = (index / POINTS_PER_CELL) / dw; |
|
|
|
} |
|
|
|
|
|
|
|
static inline void set_point(int index, float x, float y, float r, |
|
|
@@ -1021,39 +1059,40 @@ int main(int argc, char *argv[]) |
|
|
|
return EXIT_FAILURE; |
|
|
|
} |
|
|
|
|
|
|
|
TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2); |
|
|
|
HEADER_BITS = logf(RANGE_W * RANGE_H) / logf(2); |
|
|
|
DATA_BITS = TOTAL_BITS - HEADER_BITS; |
|
|
|
#if POINTS_PER_CELL == 1 |
|
|
|
CELL_BITS = logf(RANGE_SYXRGB) / logf(2); |
|
|
|
#else |
|
|
|
// TODO: implement the following shit |
|
|
|
//float coord_bits = logf((RANGE_Y * RANGE_X) * (RANGE_Y * RANGE_X + 1) / 2); |
|
|
|
//float other_bits = logf(RANGE_R * RANGE_G * RANGE_B * RANGE_S); |
|
|
|
//CELL_BITS = (coord_bits + 2 * other_bits) / logf(2); |
|
|
|
CELL_BITS = 2 * logf(RANGE_SYXRGB) / logf(2); |
|
|
|
#endif |
|
|
|
TOTAL_CELLS = (int)(DATA_BITS / CELL_BITS); |
|
|
|
MAX_ITERATIONS = ITERATIONS_PER_POINT * POINTS_PER_CELL * TOTAL_CELLS; |
|
|
|
|
|
|
|
/* Compute "best" w/h ratio */ |
|
|
|
dw = 1; dh = TOTAL_CELLS; |
|
|
|
for(unsigned int i = 1; i <= TOTAL_CELLS; i++) |
|
|
|
compute_ranges(width, height); |
|
|
|
|
|
|
|
/* Try to cram some more information into our points as long as it |
|
|
|
* does not change the cell distribution. This cannot be too clever, |
|
|
|
* because we want the computation to depend only on the source image |
|
|
|
* coordinates. */ |
|
|
|
#define TRY(op, revert) \ |
|
|
|
do { \ |
|
|
|
unsigned int olddw = dw, olddh = dh; \ |
|
|
|
op; compute_ranges(width, height); \ |
|
|
|
if(dw != olddw || dh != olddh) \ |
|
|
|
{ revert; compute_ranges(width, height); } \ |
|
|
|
} while(0) |
|
|
|
|
|
|
|
for(int i = 0; i < 5; i++) |
|
|
|
{ |
|
|
|
int j = TOTAL_CELLS / i; |
|
|
|
|
|
|
|
float r = (float)width / (float)height; |
|
|
|
float ir = (float)i / (float)j; |
|
|
|
float dwr = (float)dw / (float)dh; |
|
|
|
TRY(RANGE_G++, RANGE_G--); |
|
|
|
TRY(RANGE_R++, RANGE_R--); |
|
|
|
TRY(RANGE_B++, RANGE_B--); |
|
|
|
} |
|
|
|
|
|
|
|
if(fabs(logf(r / ir)) < fabs(logf(r / dwr))) |
|
|
|
for(int i = 0; i < 10; i++) |
|
|
|
{ |
|
|
|
if((float)width / dw >= (float)height / dh) |
|
|
|
{ |
|
|
|
dw = i; |
|
|
|
dh = TOTAL_CELLS / dw; |
|
|
|
TRY(RANGE_X++, RANGE_X--); |
|
|
|
TRY(RANGE_Y++, RANGE_Y--); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
TRY(RANGE_Y++, RANGE_Y--); |
|
|
|
TRY(RANGE_X++, RANGE_X--); |
|
|
|
} |
|
|
|
} |
|
|
|
while((dh + 1) * dw <= TOTAL_CELLS) dh++; |
|
|
|
while(dh * (dw + 1) <= TOTAL_CELLS) dw++; |
|
|
|
|
|
|
|
/* Print debug information */ |
|
|
|
if(DEBUG_MODE) |
|
|
|