浏览代码

* img2rubik.c: factor out the hull generation so that we can also build a

convex hull of the Neugebauer primaries.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2730 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
sam 16 年前
父节点
当前提交
e23268c286
共有 1 个文件被更改,包括 143 次插入70 次删除
  1. +143
    -70
      examples/img2rubik.c

+ 143
- 70
examples/img2rubik.c 查看文件

@@ -14,77 +14,94 @@


#define BRIGHT(x) (0.299*(x)[0] + 0.587*(x)[1] + 0.114*(x)[2]) #define BRIGHT(x) (0.299*(x)[0] + 0.587*(x)[1] + 0.114*(x)[2])


#define STEPS 1024 #define MAXCOLORS 16
#define STEPS 256
#define EPSILON (0.000001) #define EPSILON (0.000001)


int main(int argc, char *argv[]) typedef struct
{ {
double palette[][3] = double pts[STEPS + 1][MAXCOLORS * (MAXCOLORS - 1) / 2][6];
{ int hullsize[STEPS + 1];
{ 0.8, 0.0, 0.0 }, /* red */ double bary[STEPS + 1][3];
{ 0.0, 0.8, 0.0 }, /* green */ }
{ 0.0, 0.0, 0.7 }, /* blue */ hull_t;
{ 1.0, 1.0, 1.0 }, /* white */
{ 0.9, 0.9, 0.0 }, /* yellow */
{ 0.8, 0.4, 0.0 }, /* orange */
};
#define NCOLORS ((int)(sizeof(palette)/sizeof(*palette)))


static double const y[3] = { .299, .587, .114 };
static double u[3], v[3];
static int ylen;

/*
* Find two base vectors for the chrominance planes.
*/
static void init_uv(void)
{
double tmp;

ylen = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);

u[0] = y[1];
u[1] = -y[0];
u[2] = 0;
tmp = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
u[0] /= tmp; u[1] /= tmp; u[2] /= tmp;

v[0] = y[1] * u[2] - y[2] * u[1];
v[1] = y[2] * u[0] - y[0] * u[2];
v[2] = y[0] * u[1] - y[1] * u[0];
tmp = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= tmp; v[1] /= tmp; v[2] /= tmp;
}

/*
* Compute the convex hull of a given palette.
*/
static hull_t *compute_hull(int ncolors, double const *palette)
{
hull_t *ret = malloc(sizeof(hull_t));
double tmp; double tmp;
int i, j; int i, j;


double pal[ncolors][3];
for(i = 0; i < ncolors; i++)
{
pal[i][0] = palette[i * 3];
pal[i][1] = palette[i * 3 + 1];
pal[i][2] = palette[i * 3 + 2];
}

/* /*
* 1. Find the darkest and lightest colours * 1. Find the darkest and lightest colours
*/ */
double *dark = NULL, *light = NULL; double *dark = NULL, *light = NULL;
double min = 1.0, max = 0.0; double min = 1.0, max = 0.0;
for(i = 0; i < NCOLORS; i++) for(i = 0; i < ncolors; i++)
{ {
double p = BRIGHT(palette[i]); double p = BRIGHT(pal[i]);
if(p < min) if(p < min)
{ {
dark = palette[i]; dark = pal[i];
min = p; min = p;
} }
if(p > max) if(p > max)
{ {
light = palette[i]; light = pal[i];
max = p; max = p;
} }
} }


/* double gray[3];
* 2. Find two base vectors for the chrominance planes
* FIXME: this doesn't work in all cases because u can be null
*/
double y[3], u[3], v[3];
double ylen;


y[0] = light[0] - dark[0]; gray[0] = light[0] - dark[0];
y[1] = light[1] - dark[1]; gray[1] = light[1] - dark[1];
y[2] = light[2] - dark[2]; gray[2] = light[2] - dark[2];
ylen = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);

u[0] = y[1];
u[1] = -y[0];
u[2] = 0;
tmp = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
u[0] /= tmp; u[1] /= tmp; u[2] /= tmp;

v[0] = y[1] * u[2] - y[2] * u[1];
v[1] = y[2] * u[0] - y[0] * u[2];
v[2] = y[0] * u[1] - y[1] * u[0];
tmp = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] /= tmp; v[1] /= tmp; v[2] /= tmp;


/* /*
* 3. Browse the grey axis and do stuff * 3. Browse the grey axis and do stuff
*/ */
double bary[STEPS + 1][3];
int n; int n;
for(n = 0; n <= STEPS; n++) for(n = 0; n <= STEPS; n++)
{ {
double pts[NCOLORS * (NCOLORS - 1) / 2][6]; double pts[ncolors * (ncolors - 1) / 2][6];
double ptmp[6]; double ptmp[6];
#define SWAP(p1,p2) do { memcpy(ptmp, p1, sizeof(ptmp)); \ #define SWAP(p1,p2) do { memcpy(ptmp, p1, sizeof(ptmp)); \
memcpy(p1, p2, sizeof(ptmp)); \ memcpy(p1, p2, sizeof(ptmp)); \
@@ -93,19 +110,19 @@ int main(int argc, char *argv[])
int npts = 0; int npts = 0;


double p0[3]; double p0[3];
p0[0] = dark[0] + t * y[0]; p0[0] = dark[0] + t * gray[0];
p0[1] = dark[1] + t * y[1]; p0[1] = dark[1] + t * gray[1];
p0[2] = dark[2] + t * y[2]; p0[2] = dark[2] + t * gray[2];


/* /*
* 3.1. Find all edges that intersect the t.y + (u,v) plane * 3.1. Find all edges that intersect the t.y + (u,v) plane
*/ */
for(i = 0; i < NCOLORS; i++) for(i = 0; i < ncolors; i++)
{ {
double k1[3]; double k1[3];
k1[0] = palette[i][0] - dark[0]; k1[0] = pal[i][0] - p0[0];
k1[1] = palette[i][1] - dark[1]; k1[1] = pal[i][1] - p0[1];
k1[2] = palette[i][2] - dark[2]; k1[2] = pal[i][2] - p0[2];
tmp = sqrt(k1[0] * k1[0] + k1[1] * k1[1] + k1[2] * k1[2]); tmp = sqrt(k1[0] * k1[0] + k1[1] * k1[1] + k1[2] * k1[2]);


/* If k1.y > t.y.y, we don't want this point */ /* If k1.y > t.y.y, we don't want this point */
@@ -113,15 +130,15 @@ int main(int argc, char *argv[])
if(yk1 > t * ylen * ylen + EPSILON) if(yk1 > t * ylen * ylen + EPSILON)
continue; continue;


for(j = 0; j < NCOLORS; j++) for(j = 0; j < ncolors; j++)
{ {
if(i == j) if(i == j)
continue; continue;


double k2[3]; double k2[3];
k2[0] = palette[j][0] - dark[0]; k2[0] = pal[j][0] - p0[0];
k2[1] = palette[j][1] - dark[1]; k2[1] = pal[j][1] - p0[1];
k2[2] = palette[j][2] - dark[2]; k2[2] = pal[j][2] - p0[2];
tmp = sqrt(k2[0] * k2[0] + k2[1] * k2[1] + k2[2] * k2[2]); tmp = sqrt(k2[0] * k2[0] + k2[1] * k2[1] + k2[2] * k2[2]);


/* If k2.y < t.y.y, we don't want this point */ /* If k2.y < t.y.y, we don't want this point */
@@ -135,9 +152,9 @@ int main(int argc, char *argv[])
double s = yk1 == yk2 ? double s = yk1 == yk2 ?
0.5 : (t * ylen * ylen - yk1) / (yk2 - yk1); 0.5 : (t * ylen * ylen - yk1) / (yk2 - yk1);


pts[npts][0] = dark[0] + k1[0] + s * (k2[0] - k1[0]); pts[npts][0] = p0[0] + k1[0] + s * (k2[0] - k1[0]);
pts[npts][1] = dark[1] + k1[1] + s * (k2[1] - k1[1]); pts[npts][1] = p0[1] + k1[1] + s * (k2[1] - k1[1]);
pts[npts][2] = dark[2] + k1[2] + s * (k2[2] - k1[2]); pts[npts][2] = p0[2] + k1[2] + s * (k2[2] - k1[2]);
npts++; npts++;
} }
} }
@@ -150,12 +167,12 @@ int main(int argc, char *argv[])
/* Make our problem a 2-D problem. */ /* Make our problem a 2-D problem. */
for(i = 0; i < npts; i++) for(i = 0; i < npts; i++)
{ {
pts[i][X] = (pts[i][0] - dark[0]) * u[0] pts[i][X] = (pts[i][0] - p0[0]) * u[0]
+ (pts[i][1] - dark[1]) * u[1] + (pts[i][1] - p0[1]) * u[1]
+ (pts[i][2] - dark[2]) * u[2]; + (pts[i][2] - p0[2]) * u[2];
pts[i][Y] = (pts[i][0] - dark[0]) * v[0] pts[i][Y] = (pts[i][0] - p0[0]) * v[0]
+ (pts[i][1] - dark[1]) * v[1] + (pts[i][1] - p0[1]) * v[1]
+ (pts[i][2] - dark[2]) * v[2]; + (pts[i][2] - p0[2]) * v[2];
} }


/* Find the leftmost point */ /* Find the leftmost point */
@@ -234,18 +251,59 @@ int main(int argc, char *argv[])
cty = 0.5 * (pts[0][Y] + pts[right][Y]); cty = 0.5 * (pts[0][Y] + pts[right][Y]);
} }


bary[n][0] = p0[0] + ctx * u[0] + cty * v[0]; /*
bary[n][1] = p0[1] + ctx * u[1] + cty * v[1]; * 3.3. Store the barycentre and convex hull information.
bary[n][2] = p0[2] + ctx * u[2] + cty * v[2]; */

ret->bary[n][0] = p0[0] + ctx * u[0] + cty * v[0];
ret->bary[n][1] = p0[1] + ctx * u[1] + cty * v[1];
ret->bary[n][2] = p0[2] + ctx * u[2] + cty * v[2];
//if(ncolors == 6) printf("%i %g %g %g\n", n, ret->bary[n][0], ret->bary[n][1], ret->bary[n][2]);

for(i = 0; i < npts; i++)
{
ret->pts[n][i][0] = pts[i][0];
ret->pts[n][i][1] = pts[i][1];
ret->pts[n][i][2] = pts[i][2];
}
ret->hullsize[n] = npts;
} }


return ret;
}


int main(int argc, char *argv[])
{
static double const rgbpal[] =
{
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1,
1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1,
};

static double const mypal[] =
{
0.8, 0.0, 0.0, /* red */
0.0, 0.8, 0.0, /* green */
0.0, 0.0, 0.6, /* blue */
1.0, 1.0, 1.0, /* white */
0.9, 0.9, 0.0, /* yellow */
0.8, 0.4, 0.0, /* orange */
};

int i, j;

init_uv();


hull_t *rgbhull = compute_hull(8, rgbpal);
hull_t *myhull = compute_hull(6, mypal);


/* /*
* Last step: load image and change its palette. * 4. Load image and change its palette.
*/ */

pipi_image_t *src = pipi_load(argv[1]); pipi_image_t *src = pipi_load(argv[1]);
pipi_pixels_t *srcp = pipi_getpixels(src, PIPI_PIXELS_Y_F); pipi_pixels_t *srcp = pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
float *srcdata = (float *)srcp->pixels; float *srcdata = (float *)srcp->pixels;


int w = srcp->w, h = srcp->h; int w = srcp->w, h = srcp->h;
@@ -257,11 +315,26 @@ int main(int argc, char *argv[])
for(j = 0; j < h; j++) for(j = 0; j < h; j++)
for(i = 0; i < w; i++) for(i = 0; i < w; i++)
{ {
/* FIXME: Imlib fucks this up */ double p[3];
double p = srcdata[j * w + i]; /* FIXME: Imlib fucks up the RGB order. */
dstdata[4 * (j * w + i)] = bary[(int)(p * STEPS)][2]; p[2] = srcdata[4 * (j * w + i)];
dstdata[4 * (j * w + i) + 1] = bary[(int)(p * STEPS)][1]; p[1] = srcdata[4 * (j * w + i) + 1];
dstdata[4 * (j * w + i) + 2] = bary[(int)(p * STEPS)][0]; p[0] = srcdata[4 * (j * w + i) + 2];
double gray = BRIGHT(p);

double dx = (p[0] - gray * y[0]) * u[0]
+ (p[1] - gray * y[1]) * u[1]
+ (p[2] - gray * y[2]) * u[2];
double dy = (p[0] - gray * y[0]) * v[0]
+ (p[1] - gray * y[1]) * v[1]
+ (p[2] - gray * y[2]) * v[2];

dstdata[4 * (j * w + i)] = myhull->bary[(int)(gray * STEPS)][2]
+ dx * u[2] * .3 + dy * v[2] * .3;
dstdata[4 * (j * w + i) + 1] = myhull->bary[(int)(gray * STEPS)][1]
+ dx * u[1] * .3 + dy * v[1] * .3;
dstdata[4 * (j * w + i) + 2] = myhull->bary[(int)(gray * STEPS)][0]
+ dx * u[0] * .3 + dy * v[0] * .3;
} }


pipi_save(dst, argv[2]); pipi_save(dst, argv[2]);


||||||
x
 
000:0
正在加载...
取消
保存