Parcourir la source

Make img2twit's points-per-cell value changeable at runtime.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@3538 92316355-f0b4-4df1-b90c-862c8a59935f
master
sam il y a 15 ans
Parent
révision
e26e8598f4
1 fichiers modifiés avec 103 ajouts et 103 suppressions
  1. +103
    -103
      examples/img2twit.cpp

+ 103
- 103
examples/img2twit.cpp Voir le fichier

@@ -71,10 +71,6 @@ static const uint32_t *unichars;
#define RANGE_H 2000
#define RANGE_V 10

/* 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

/* Start with a random image (1), or with a good estimate (0)? */
#define RANDOM_START 0

@@ -91,6 +87,9 @@ static int MAX_MSG_LEN = 140;
/* Iterations per point -- larger means slower but nicer */
static int ITERATIONS_PER_POINT = 50;

/* Points per cell -- 1 allows to put more cells, but 2 gives better results */
static int POINTS_PER_CELL = 2;

/* The range value for point parameters: X Y, red/green/blue, "strength"
* Tested values (on Mona Lisa) are:
* 16 16 5 5 5 2 -> 0.06511725914
@@ -153,12 +152,16 @@ void compute_ranges(int width, int height)
TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2);
HEADER_BITS = logf(RANGE_W * RANGE_H * RANGE_V) / logf(2);
DATA_BITS = TOTAL_BITS - HEADER_BITS;
#if POINTS_PER_CELL == 2
CELL_BITS = (2 * logf(RANGE_SBGR) + logf(RANGE_XY2)) / logf(2);
//CELL_BITS = 2 * logf(RANGE_SBGRXY) / logf(2);
#else
CELL_BITS = logf(RANGE_SBGRXY) / logf(2);
#endif
if(version == 0)
{
POINTS_PER_CELL = 1;
CELL_BITS = logf(RANGE_SBGRXY) / logf(2);
}
else if(version == 1)
{
POINTS_PER_CELL = 2;
CELL_BITS = (2 * logf(RANGE_SBGR) + logf(RANGE_XY2)) / logf(2);
}
TOTAL_CELLS = (int)(DATA_BITS / CELL_BITS);
MAX_ITERATIONS = ITERATIONS_PER_POINT * POINTS_PER_CELL * TOTAL_CELLS;

@@ -839,35 +842,24 @@ static void analyse(pipi_image_t *src)
wmin = 0.0, wmax = 1.0;

#if RANDOM_START == 1
# if POINTS_PER_CELL == 2
add_random_point();
# endif
add_random_point();
for(int i = 0; i < POINTS_PER_CELL; i++)
add_random_point();
#else
/* 0.80 and 0.20 were chosen empirically, it gives a 10% better
* initial distance. Definitely worth it. */
# if POINTS_PER_CELL == 1
if(total < min + (max - min) / 2)
{
# endif
add_point(xmin, ymin,
data[4 * (xmin + ymin * p->w) + 0] * 0.80 + mr * 0.20,
data[4 * (xmin + ymin * p->w) + 1] * 0.80 + mg * 0.20,
data[4 * (xmin + ymin * p->w) + 2] * 0.80 + mb * 0.20,
wmin);
# if POINTS_PER_CELL == 1
}
else
{
# endif
add_point(xmax, ymax,
data[4 * (xmax + ymax * p->w) + 0] * 0.80 + mr * 0.20,
data[4 * (xmax + ymax * p->w) + 1] * 0.80 + mg * 0.20,
data[4 * (xmax + ymax * p->w) + 2] * 0.80 + mb * 0.20,
wmax);
# if POINTS_PER_CELL == 1
}
# endif
if(POINTS_PER_CELL == 2 || total < min + (max - min) / 2)
add_point(xmin, ymin,
data[4 * (xmin + ymin * p->w) + 0] * 0.80 + mr * 0.20,
data[4 * (xmin + ymin * p->w) + 1] * 0.80 + mg * 0.20,
data[4 * (xmin + ymin * p->w) + 2] * 0.80 + mb * 0.20,
wmin);

if(POINTS_PER_CELL == 2 || total >= min + (max - min) / 2)
add_point(xmax, ymax,
data[4 * (xmax + ymax * p->w) + 0] * 0.80 + mr * 0.20,
data[4 * (xmax + ymax * p->w) + 1] * 0.80 + mg * 0.20,
data[4 * (xmax + ymax * p->w) + 2] * 0.80 + mb * 0.20,
wmax);
#endif
}
}
@@ -1052,6 +1044,13 @@ int main(int argc, char *argv[])
/* The first thing we pop from the stream is the version information */
version = b.pop(RANGE_V);

if(version > 1)
{
fprintf(stderr, "Error: unsupported algorithm version %i\n",
version);
return EXIT_FAILURE;
}

/* Read width and height from bitstream */
width = b.pop(RANGE_W) + 1;
height = b.pop(RANGE_H) + 1;
@@ -1080,12 +1079,6 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}

if(version > 1)
{
fprintf(stderr, "Error: unsupported algorithm version %i\n", version);
return EXIT_FAILURE;
}

compute_ranges(width, height);

/* Try to cram some more information into our points as long as it
@@ -1147,7 +1140,7 @@ int main(int argc, char *argv[])
if(srcname)
{
/* Resize and filter image to better state */
tmp = pipi_gaussian_blur(src, 0.5 * dw * RANGE_X / width);
tmp = pipi_gaussian_blur(src, 0.25 * dw * RANGE_X / width);
pipi_free(src);
src = pipi_resize(tmp, dw * RANGE_X, dh * RANGE_Y);
pipi_free(tmp);
@@ -1202,16 +1195,17 @@ int main(int argc, char *argv[])

apply_op(op1, &points[pt]);

#if POINTS_PER_CELL == 2
/* Check that two points don't fall at the same place */
while(points[pt].x == points[pt ^ 1].x
&& points[pt].y == points[pt ^ 1].y)
if(POINTS_PER_CELL == 2)
{
points[pt] = oldpt;
op1 = rand_op();
apply_op(op1, &points[pt]);
while(points[pt].x == points[pt ^ 1].x
&& points[pt].y == points[pt ^ 1].y)
{
points[pt] = oldpt;
op1 = rand_op();
apply_op(op1, &points[pt]);
}
}
#endif

render(scrap, zonex * RANGE_X, zoney * RANGE_Y,
zonew * RANGE_X, zoneh * RANGE_Y, false);
@@ -1280,7 +1274,7 @@ int main(int argc, char *argv[])
else
fprintf(stderr, "\r \r");

#if 1
#if 0
dst = pipi_resize(tmp, width, height);
pipi_free(tmp);

@@ -1292,33 +1286,36 @@ int main(int argc, char *argv[])
/* Push our points to the bitstream */
for(int i = 0; i < npoints; i += POINTS_PER_CELL)
{
#if POINTS_PER_CELL == 2
int x1, y1, x2, y2;
x1 = points[i].x;
y1 = points[i].y;
x2 = points[i + 1].x;
y2 = points[i + 1].y;

bool swap;
uint32_t pack = pack_coords(x1, y1, x2, y2, &swap);

b.push(points[i + (swap ? 1 : 0)].s, RANGE_S);
b.push(points[i + (swap ? 1 : 0)].b, RANGE_B);
b.push(points[i + (swap ? 1 : 0)].g, RANGE_G);
b.push(points[i + (swap ? 1 : 0)].r, RANGE_R);
b.push(points[i + (swap ? 0 : 1)].s, RANGE_S);
b.push(points[i + (swap ? 0 : 1)].b, RANGE_B);
b.push(points[i + (swap ? 0 : 1)].g, RANGE_G);
b.push(points[i + (swap ? 0 : 1)].r, RANGE_R);
b.push(pack, RANGE_XY2);
#else
b.push(points[i].s, RANGE_S);
b.push(points[i].b, RANGE_B);
b.push(points[i].g, RANGE_G);
b.push(points[i].r, RANGE_R);
b.push(points[i].x, RANGE_X);
b.push(points[i].y, RANGE_Y);
#endif
if(POINTS_PER_CELL == 2)
{
int x1, y1, x2, y2;
x1 = points[i].x;
y1 = points[i].y;
x2 = points[i + 1].x;
y2 = points[i + 1].y;

bool swap;
uint32_t pack = pack_coords(x1, y1, x2, y2, &swap);

b.push(points[i + (swap ? 1 : 0)].s, RANGE_S);
b.push(points[i + (swap ? 1 : 0)].b, RANGE_B);
b.push(points[i + (swap ? 1 : 0)].g, RANGE_G);
b.push(points[i + (swap ? 1 : 0)].r, RANGE_R);
b.push(points[i + (swap ? 0 : 1)].s, RANGE_S);
b.push(points[i + (swap ? 0 : 1)].b, RANGE_B);
b.push(points[i + (swap ? 0 : 1)].g, RANGE_G);
b.push(points[i + (swap ? 0 : 1)].r, RANGE_R);
b.push(pack, RANGE_XY2);
}
else
{
b.push(points[i].s, RANGE_S);
b.push(points[i].b, RANGE_B);
b.push(points[i].g, RANGE_G);
b.push(points[i].r, RANGE_R);
b.push(points[i].x, RANGE_X);
b.push(points[i].y, RANGE_Y);
}
}
b.push(height - 1, RANGE_H);
b.push(width - 1, RANGE_W);
@@ -1334,31 +1331,34 @@ int main(int argc, char *argv[])
/* Pop points from the bitstream */
for(int i = dw * dh; i--; )
{
#if POINTS_PER_CELL == 2
uint32_t pack = b.pop(RANGE_XY2);
int x1, y1, x2, y2;
unpack_coords(pack, &x1, &y1, &x2, &y2);

points[i * 2 + 1].y = y2;
points[i * 2 + 1].x = x2;
points[i * 2 + 1].r = b.pop(RANGE_R);
points[i * 2 + 1].g = b.pop(RANGE_G);
points[i * 2 + 1].b = b.pop(RANGE_B);
points[i * 2 + 1].s = b.pop(RANGE_S);
points[i * 2].y = y1;
points[i * 2].x = x1;
points[i * 2].r = b.pop(RANGE_R);
points[i * 2].g = b.pop(RANGE_G);
points[i * 2].b = b.pop(RANGE_B);
points[i * 2].s = b.pop(RANGE_S);
#else
points[i].y = b.pop(RANGE_Y);
points[i].x = b.pop(RANGE_X);
points[i].r = b.pop(RANGE_R);
points[i].g = b.pop(RANGE_G);
points[i].b = b.pop(RANGE_B);
points[i].s = b.pop(RANGE_S);
#endif
if(POINTS_PER_CELL == 2)
{
uint32_t pack = b.pop(RANGE_XY2);
int x1, y1, x2, y2;
unpack_coords(pack, &x1, &y1, &x2, &y2);

points[i * 2 + 1].y = y2;
points[i * 2 + 1].x = x2;
points[i * 2 + 1].r = b.pop(RANGE_R);
points[i * 2 + 1].g = b.pop(RANGE_G);
points[i * 2 + 1].b = b.pop(RANGE_B);
points[i * 2 + 1].s = b.pop(RANGE_S);
points[i * 2].y = y1;
points[i * 2].x = x1;
points[i * 2].r = b.pop(RANGE_R);
points[i * 2].g = b.pop(RANGE_G);
points[i * 2].b = b.pop(RANGE_B);
points[i * 2].s = b.pop(RANGE_S);
}
else
{
points[i].y = b.pop(RANGE_Y);
points[i].x = b.pop(RANGE_X);
points[i].r = b.pop(RANGE_R);
points[i].g = b.pop(RANGE_G);
points[i].b = b.pop(RANGE_B);
points[i].s = b.pop(RANGE_S);
}
}
npoints = dw * dh * POINTS_PER_CELL;



Chargement…
Annuler
Enregistrer