|
|
@@ -62,8 +62,8 @@ static const uint32_t unichars_symbols[] = { RANGE_SYMBOLS, RANGE_END }; |
|
|
|
static const uint32_t *unichars; |
|
|
|
|
|
|
|
/* The maximum image size we want to support */ |
|
|
|
#define MAX_W 4000 |
|
|
|
#define MAX_H 4000 |
|
|
|
#define RANGE_W 4000 |
|
|
|
#define RANGE_H 4000 |
|
|
|
|
|
|
|
/* How does the algorithm work: one point per cell, or two */ |
|
|
|
#define POINTS_PER_CELL 2 |
|
|
@@ -442,11 +442,22 @@ static inline float int2fullrange(int val, int range) |
|
|
|
return range > 1 ? (float)val / (float)(range - 1) : 0.0; |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void set_point(int index, float x, float y, float r, |
|
|
|
float g, float b, float s) |
|
|
|
{ |
|
|
|
int dx = (index / POINTS_PER_CELL) % dw; |
|
|
|
int dy = (index / POINTS_PER_CELL) / dw; |
|
|
|
int dx, dy; |
|
|
|
|
|
|
|
index2cell(index, &dx, &dy); |
|
|
|
|
|
|
|
float fx = (x - dx * RANGE_X) / RANGE_X; |
|
|
|
float fy = (y - dy * RANGE_Y) / RANGE_Y; |
|
|
@@ -468,9 +479,9 @@ static inline void get_point(int index, float *x, float *y, float *r, |
|
|
|
float *g, float *b, float *s, bool final = false) |
|
|
|
{ |
|
|
|
uint32_t pt = points[index]; |
|
|
|
int dx, dy; |
|
|
|
|
|
|
|
unsigned int dx = (index / POINTS_PER_CELL) % dw; |
|
|
|
unsigned int dy = (index / POINTS_PER_CELL) / dw; |
|
|
|
index2cell(index, &dx, &dy); |
|
|
|
|
|
|
|
*s = int2fullrange(pt % RANGE_S, RANGE_S); pt /= RANGE_S; |
|
|
|
|
|
|
@@ -936,6 +947,9 @@ int main(int argc, char *argv[]) |
|
|
|
return EXIT_FAILURE; |
|
|
|
} |
|
|
|
|
|
|
|
bitstack b(MAX_MSG_LEN); /* We cannot declare this before, because |
|
|
|
* MAX_MSG_LEN wouldn't be defined. */ |
|
|
|
|
|
|
|
/* Autodetect charset if decoding, otherwise switch to CJK. */ |
|
|
|
if(dstname) |
|
|
|
{ |
|
|
@@ -972,23 +986,6 @@ int main(int argc, char *argv[]) |
|
|
|
|
|
|
|
/* Precompute bit allocation */ |
|
|
|
NUM_CHARACTERS = count_unichars(); |
|
|
|
TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2); |
|
|
|
HEADER_BITS = logf(MAX_W * MAX_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; |
|
|
|
|
|
|
|
bitstack b(MAX_MSG_LEN); /* We cannot declare this before, because |
|
|
|
* MAX_MSG_LEN wouldn't be defined. */ |
|
|
|
|
|
|
|
if(dstname) |
|
|
|
{ |
|
|
@@ -999,8 +996,8 @@ int main(int argc, char *argv[]) |
|
|
|
|
|
|
|
/* Read width and height from bitstream */ |
|
|
|
src = NULL; |
|
|
|
width = b.pop(MAX_W); |
|
|
|
height = b.pop(MAX_H); |
|
|
|
width = b.pop(RANGE_W) + 1; |
|
|
|
height = b.pop(RANGE_H) + 1; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@@ -1017,6 +1014,28 @@ int main(int argc, char *argv[]) |
|
|
|
height = pipi_get_image_height(src); |
|
|
|
} |
|
|
|
|
|
|
|
if(width <= 0 || height <= 0 || width > RANGE_W || height > RANGE_H) |
|
|
|
{ |
|
|
|
fprintf(stderr, "Error: image size %ix%i is out of bounds\n", |
|
|
|
width, height); |
|
|
|
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++) |
|
|
@@ -1042,10 +1061,12 @@ int main(int argc, char *argv[]) |
|
|
|
fprintf(stderr, "Message size: %i\n", MAX_MSG_LEN); |
|
|
|
fprintf(stderr, "Available characters: %i\n", NUM_CHARACTERS); |
|
|
|
fprintf(stderr, "Available bits: %f\n", TOTAL_BITS); |
|
|
|
fprintf(stderr, "Maximum image resolution: %ix%i\n", MAX_W, MAX_H); |
|
|
|
fprintf(stderr, "Width/Height ranges: %ix%i\n", RANGE_W, RANGE_H); |
|
|
|
fprintf(stderr, "Image resolution: %ix%i\n", width, height); |
|
|
|
fprintf(stderr, "Header bits: %f\n", HEADER_BITS); |
|
|
|
fprintf(stderr, "Bits available for data: %f\n", DATA_BITS); |
|
|
|
fprintf(stderr, "X/Y/Red/Green/Blue/Extra ranges: %i %i %i %i %i %i\n", |
|
|
|
RANGE_X, RANGE_Y, RANGE_R, RANGE_G, RANGE_B, RANGE_S); |
|
|
|
fprintf(stderr, "Cell bits: %f\n", CELL_BITS); |
|
|
|
fprintf(stderr, "Available cells: %i\n", TOTAL_CELLS); |
|
|
|
fprintf(stderr, "Wasted bits: %f\n", |
|
|
@@ -1210,8 +1231,8 @@ int main(int argc, char *argv[]) |
|
|
|
/* Push our points to the bitstream */ |
|
|
|
for(int i = 0; i < npoints; i++) |
|
|
|
b.push(points[i], RANGE_SYXRGB); |
|
|
|
b.push(height, MAX_H); |
|
|
|
b.push(width, MAX_W); |
|
|
|
b.push(height - 1, RANGE_H); |
|
|
|
b.push(width - 1, RANGE_W); |
|
|
|
|
|
|
|
/* Pop Unicode characters from the bitstream and print them */ |
|
|
|
for(int i = 0; i < MAX_MSG_LEN; i++) |
|
|
|