Changeset 2726


Ignore:
Timestamp:
08/16/08 02:53:54 (5 years ago)
Author:
sam
Message:
  • Start working on colour reduction with a constrained palette.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libpipi/trunk/examples/img2rubik.c

    r2679 r2726  
    55#include <stdlib.h> 
    66#include <string.h> 
     7#include <math.h> 
    78 
    89#include <pipi.h> 
    910 
     11#define Y(x) (0.299*(x)[0] + 0.587*(x)[1] + 0.114*(x)[2]) 
     12 
     13#define STEPS 16 
     14#define EPSILON (0.000001) 
     15 
    1016int main(int argc, char *argv[]) 
    1117{ 
    12     char *srcname = NULL, *dstname = NULL; 
    13     pipi_image_t *img; 
     18    double palette[][3] = 
     19    { 
     20        { 1.0, 0.0, 0.0 }, /* red */ 
     21        { 0.0, 1.0, 0.0 }, /* green */ 
     22        { 0.0, 0.0, 1.0 }, /* blue */ 
     23        { 1.0, 1.0, 1.0 }, /* white */ 
     24        { 1.0, 1.0, 0.0 }, /* yellow */ 
     25        { 1.0, 0.5, 0.0 }, /* orange */ 
     26    }; 
     27#define NCOLORS ((int)(sizeof(palette)/sizeof(*palette))) 
    1428 
    15     if(argc < 3) 
     29    double tmp; 
     30    int i, j; 
     31 
     32    /* 
     33     * 1. Find the darkest and lightest colours 
     34     */ 
     35    double *dark = NULL, *light = NULL; 
     36    double min = 1.0, max = 0.0; 
     37    for(i = 0; i < NCOLORS; i++) 
    1638    { 
    17         fprintf(stderr, "%s: too few arguments\n", argv[0]); 
    18         return EXIT_FAILURE; 
     39        double p = Y(palette[i]); 
     40        if(p < min) 
     41        { 
     42            dark = palette[i]; 
     43            min = p; 
     44        } 
     45        if(p > max) 
     46        { 
     47            light = palette[i]; 
     48            max = p; 
     49        } 
    1950    } 
     51    printf("lightest (%g,%g,%g)\n", light[0], light[1], light[2]); 
     52    printf("darkest (%g,%g,%g)\n", dark[0], dark[1], dark[2]); 
    2053 
    21     srcname = argv[1]; 
    22     dstname = argv[2]; 
     54    /* 
     55     * 2. Find two base vectors for the chrominance planes 
     56     * FIXME: this doesn't work in all cases because u can be null 
     57     */ 
     58    double y[3], u[3], v[3]; 
     59    double ylen; 
    2360 
    24     img = pipi_load(srcname); 
    25     pipi_save(img, dstname); 
    26     pipi_free(img); 
     61    y[0] = light[0] - dark[0]; 
     62    y[1] = light[1] - dark[1]; 
     63    y[2] = light[2] - dark[2]; 
     64    ylen = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]); 
     65 
     66    u[0] = y[1]; 
     67    u[1] = -y[0]; 
     68    u[2] = 0; 
     69    tmp = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]); 
     70    u[0] /= tmp; u[1] /= tmp; u[2] /= tmp; 
     71 
     72    v[0] = y[1] * u[2] - y[2] * u[1]; 
     73    v[1] = y[2] * u[0] - y[0] * u[2]; 
     74    v[2] = y[0] * u[1] - y[1] * u[0]; 
     75    tmp = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 
     76    v[0] /= tmp; v[1] /= tmp; v[2] /= tmp; 
     77 
     78    printf("gray axis (%g,%g,%g) - length %g\n", y[0], y[1], y[2], ylen); 
     79    printf("u (%g,%g,%g)\n", u[0], u[1], u[2]); 
     80    printf("v (%g,%g,%g)\n", v[0], v[1], v[2]); 
     81 
     82    /* 
     83     * 3. Browse the grey axis and do stuff 
     84     */ 
     85    double t; 
     86    for(t = 0.; t <= 1.0; t += 1. / STEPS) 
     87    { 
     88        double pts[NCOLORS*NCOLORS/2][3]; 
     89        double p0[3]; 
     90        int npts = 0; 
     91 
     92        p0[0] = dark[0] + t * y[0]; 
     93        p0[1] = dark[1] + t * y[1]; 
     94        p0[2] = dark[2] + t * y[2]; 
     95        printf("%g,%g,%g\n", p0[0], p0[1], p0[2]); 
     96 
     97        /* 
     98         * 3.1. Find all edges that intersect the t.y + (u,v) plane 
     99         */ 
     100        for(i = 0; i < NCOLORS; i++) 
     101        { 
     102            double k1[3]; 
     103            k1[0] = palette[i][0] - dark[0]; 
     104            k1[1] = palette[i][1] - dark[1]; 
     105            k1[2] = palette[i][2] - dark[2]; 
     106            tmp = sqrt(k1[0] * k1[0] + k1[1] * k1[1] + k1[2] * k1[2]); 
     107 
     108            /* If k1.y > t.y.y, we don't want this point */ 
     109            double yk1 = y[0] * k1[0] + y[1] * k1[1] + y[2] * k1[2]; 
     110            if(yk1 > t * ylen * ylen + EPSILON) 
     111                continue; 
     112 
     113            for(j = 0; j < NCOLORS; j++) 
     114            { 
     115                if(i == j) 
     116                    continue; 
     117 
     118                double k2[3]; 
     119                k2[0] = palette[j][0] - dark[0]; 
     120                k2[1] = palette[j][1] - dark[1]; 
     121                k2[2] = palette[j][2] - dark[2]; 
     122                tmp = sqrt(k2[0] * k2[0] + k2[1] * k2[1] + k2[2] * k2[2]); 
     123 
     124                /* If k2.y < t.y.y, we don't want this point */ 
     125                double yk2 = y[0] * k2[0] + y[1] * k2[1] + y[2] * k2[2]; 
     126                if(yk2 < t * ylen * ylen - EPSILON) 
     127                    continue; 
     128 
     129                if(yk2 < yk1) 
     130                    continue; 
     131 
     132                double s = yk1 == yk2 ? 
     133                           0.5 : (t * ylen * ylen - yk1) / (yk2 - yk1); 
     134 
     135                pts[npts][0] = dark[0] + k1[0] + s * (k2[0] - k1[0]); 
     136                pts[npts][1] = dark[1] + k1[1] + s * (k2[1] - k1[1]); 
     137                pts[npts][2] = dark[2] + k1[2] + s * (k2[2] - k1[2]); 
     138                printf("  %i,%i: s = (%g,%g,%g)\n", i, j, pts[npts][0], pts[npts][1], pts[npts][2]); 
     139                npts++; 
     140            } 
     141        } 
     142 
     143        /* 
     144         * 3.2. Find the barycentre of these points' convex hull. (TODO) 
     145         */ 
     146    } 
    27147 
    28148    return 0; 
Note: See TracChangeset for help on using the changeset viewer.