Changeset 3536


Ignore:
Timestamp:
May 28, 2009 3:54:56 AM (5 years ago)
Author:
sam
Message:

Optimise img2twit's cell packing even more, gaining around 60 bits.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libpipi/trunk/examples/img2twit.cpp

    r3535 r3536  
    7474 * this value breaks compatibility with other images. */
    7575#define POINTS_PER_CELL 2
     76
     77/* Start with a random image (1), or with a good estimate (0)? */
     78#define RANDOM_START 0
    7679
    7780/*
     
    116119
    117120#define RANGE_XY (RANGE_Y*RANGE_X)
    118 #define RANGE_XYXY (RANGE_XY*RANGE_XY)
    119 //#define RANGE_XYXY (RANGE_Y*RANGE_X*(RANGE_Y*RANGE_X+1)/2)
     121#define RANGE_XY2 (RANGE_Y*RANGE_X*(RANGE_Y*RANGE_X+1)/2)
    120122#define RANGE_RXY (RANGE_Y*RANGE_X*RANGE_R)
    121123#define RANGE_GRXY (RANGE_Y*RANGE_X*RANGE_R*RANGE_G)
     
    147149    HEADER_BITS = logf(RANGE_W * RANGE_H) / logf(2);
    148150    DATA_BITS = TOTAL_BITS - HEADER_BITS;
    149 #if POINTS_PER_CELL == 1
     151#if POINTS_PER_CELL == 2
     152    CELL_BITS = (2 * logf(RANGE_SBGR) + logf(RANGE_XY2)) / logf(2);
     153    //CELL_BITS = 2 * logf(RANGE_SBGRXY) / logf(2);
     154#else
    150155    CELL_BITS = logf(RANGE_SBGRXY) / logf(2);
    151 #else
    152     // TODO: implement the following shit
    153     //float coord_bits = logf((RANGE_Y * RANGE_X) * (RANGE_Y * RANGE_X + 1) / 2);
    154     //float other_bits = logf(RANGE_R * RANGE_G * RANGE_B * RANGE_S);
    155     //CELL_BITS = (coord_bits + 2 * other_bits) / logf(2);
    156     CELL_BITS = 2 * logf(RANGE_SBGRXY) / logf(2);
    157156#endif
    158157    TOTAL_CELLS = (int)(DATA_BITS / CELL_BITS);
     
    509508    float fy = (y - dy * RANGE_Y) / RANGE_Y;
    510509
    511     int is = range2int(s, RANGE_S);
    512 
     510    int iy = range2int(fy, RANGE_Y);
    513511    int ix = range2int(fx, RANGE_X);
    514     int iy = range2int(fy, RANGE_Y);
    515512
    516513    int ir = range2int(r, RANGE_R);
     
    518515    int ib = range2int(b, RANGE_B);
    519516
    520     points[index] = iy + RANGE_Y * (ix + RANGE_X * (ib + RANGE_B *
    521                       (ig + (RANGE_R * ir + (RANGE_S * is)))));
     517    int is = range2int(s, RANGE_S);
     518
     519    points[index] = iy + RANGE_Y * (ix + RANGE_X * (ir + RANGE_R *
     520                      (ig + (RANGE_G * ib + (RANGE_B * is)))));
    522521}
    523522
     
    533532    float fx = int2midrange(pt % RANGE_X, RANGE_X); pt /= RANGE_X;
    534533
     534    *y = (fy + dy) * RANGE_Y /*+ 0.5 * (index & 1)*/;
    535535    *x = (fx + dx) * RANGE_X /*+ 0.5 * (index & 1)*/;
    536     *y = (fy + dy) * RANGE_Y /*+ 0.5 * (index & 1)*/;
    537536
    538537    if(final)
    539538    {
    540         *b = int2fullrange(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
     539        *r = int2fullrange(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
    541540        *g = int2fullrange(pt % RANGE_G, RANGE_G); pt /= RANGE_G;
    542         *r = int2fullrange(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
     541        *b = int2fullrange(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
    543542    }
    544543    else
    545544    {
    546         *b = int2midrange(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
     545        *r = int2midrange(pt % RANGE_R, RANGE_R); pt /= RANGE_R;
    547546        *g = int2midrange(pt % RANGE_G, RANGE_G); pt /= RANGE_G;
    548         *r = int2midrange(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
     547        *b = int2midrange(pt % RANGE_B, RANGE_B); pt /= RANGE_B;
    549548    }
    550549
     
    558557}
    559558
    560 static uint32_t pack_coords(int x1, int y1, int x2, int y2)
    561 {
    562     return ((y2 * RANGE_X + x2) * RANGE_Y + y1) * RANGE_X + x1;
     559static uint32_t pack_coords(int x1, int y1, int x2, int y2, bool *swap)
     560{
     561    int k1 = y1 * RANGE_X + x1;
     562    int k2 = y2 * RANGE_X + x2;
     563
     564    /* XXX: this should not happen */
     565    if(k1 == k2)
     566        k1 += (x1 > 0 ? -1 : 1);
     567
     568    *swap = k1 > k2;
     569
     570    if(*swap)
     571    {
     572        int tmp = k1; k1 = k2; k2 = tmp;
     573    }
     574
     575    return k2 * (k2 + 1) / 2 + k1;
    563576}
    564577
    565578static void unpack_coords(uint32_t pack, int *x1, int *y1, int *x2, int *y2)
    566579{
    567     *x1 = pack % RANGE_X; pack /= RANGE_X;
    568     *y1 = pack % RANGE_Y; pack /= RANGE_Y;
    569     *x2 = pack % RANGE_X; pack /= RANGE_X;
    570     *y2 = pack % RANGE_Y;
    571 }
    572 
    573 #if 0
     580    int k2 = ((int)sqrt(1.0 + 8 * pack) - 1) / 2;
     581    int k1 = pack - k2 * (k2 + 1) / 2;
     582
     583    *x1 = k1 % RANGE_X;
     584    *y1 = k1 / RANGE_X;
     585    *x2 = k2 % RANGE_X;
     586    *y2 = k2 / RANGE_X;
     587}
     588
     589#if RANDOM_START == 1
    574590static void add_random_point()
    575591{
     
    846862                wmin = 0.0, wmax = 1.0;
    847863
    848 #if 0
     864#if RANDOM_START == 1
     865#   if POINTS_PER_CELL == 2
    849866            add_random_point();
     867#   endif
    850868            add_random_point();
    851869#else
    852870            /* 0.80 and 0.20 were chosen empirically, it gives a 10% better
    853871             * initial distance. Definitely worth it. */
    854 #if POINTS_PER_CELL == 1
     872#   if POINTS_PER_CELL == 1
    855873            if(total < min + (max - min) / 2)
    856874            {
    857 #endif
     875#   endif
    858876            add_point(xmin, ymin,
    859877                      data[4 * (xmin + ymin * p->w) + 0] * 0.80 + mr * 0.20,
     
    861879                      data[4 * (xmin + ymin * p->w) + 2] * 0.80 + mb * 0.20,
    862880                      wmin);
    863 #if POINTS_PER_CELL == 1
     881#   if POINTS_PER_CELL == 1
    864882            }
    865883            else
    866884            {
    867 #endif
     885#   endif
    868886            add_point(xmax, ymax,
    869887                      data[4 * (xmax + ymax * p->w) + 0] * 0.80 + mr * 0.20,
     
    871889                      data[4 * (xmax + ymax * p->w) + 2] * 0.80 + mb * 0.20,
    872890                      wmax);
    873 #if POINTS_PER_CELL == 1
     891#   if POINTS_PER_CELL == 1
    874892            }
    875 #endif
     893#   endif
    876894#endif
    877895        }
     
    939957            if(ITERATIONS_PER_POINT < 0)
    940958                ITERATIONS_PER_POINT = 0;
    941             else if(ITERATIONS_PER_POINT > 100)
    942                 ITERATIONS_PER_POINT = 100;
     959            else if(ITERATIONS_PER_POINT > 200)
     960                ITERATIONS_PER_POINT = 200;
    943961            break;
    944962        case 'd':
     
    954972            printf("  -l, --length <size>       message length in characters (default 140)\n");
    955973            printf("  -c, --charset <block>     character set to use (ascii, [cjk], symbols)\n");
    956             printf("  -q, --quality <rate>      set image quality (0 - 10) (default 5)\n");
     974            printf("  -q, --quality <rate>      set image quality (0 - 20) (default 5)\n");
    957975            printf("  -d, --debug               print debug information\n");
    958976            printf("  -h, --help                display this help and exit\n");
     
    10961114    } while(0)
    10971115
    1098     for(int i = 0; i < 5; i++)
     1116    for(int i = 0; i < 2; i++)
    10991117    {
    11001118        TRY(RANGE_G++, RANGE_G--);
     
    11421160    {
    11431161        /* Resize and filter image to better state */
    1144         tmp = pipi_resize(src, dw * RANGE_X, dh * RANGE_Y);
     1162        tmp = pipi_gaussian_blur(src, 0.5 * dw * RANGE_X / width);
    11451163        pipi_free(src);
    1146         src = pipi_median_ext(tmp, 1, 1);
     1164        src = pipi_resize(tmp, dw * RANGE_X, dh * RANGE_Y);
    11471165        pipi_free(tmp);
    11481166
     
    11821200            float fx, fy, fr, fg, fb, fs;
    11831201            get_point(pt, &fx, &fy, &fr, &fg, &fb, &fs);
    1184             int zonex = (int)fx / RANGE_X - 1;
    1185             int zoney = (int)fy / RANGE_Y - 1;
    1186             int zonew = 3;
    1187             int zoneh = 3;
    1188             if(zonex < 0) { zonex = 0; zonew--; }
    1189             if(zoney < 0) { zoney = 0; zoneh--; }
    1190             if(zonex + zonew >= (int)dw) { zonew--; }
    1191             if(zoney + zoneh >= (int)dh) { zoneh--; }
     1202            int zonex = (int)fx / RANGE_X - 2;
     1203            int zoney = (int)fy / RANGE_Y - 2;
     1204            int zonew = 4;
     1205            int zoneh = 4;
     1206            if(zonex < 0) { zonew += zonex; zonex = 0; }
     1207            if(zoney < 0) { zoneh += zoney; zoney = 0;; }
     1208            if(zonex + zonew > (int)dw) { zonew = dw - zonex; }
     1209            if(zoney + zoneh > (int)dh) { zoneh = dh - zoney; }
    11921210
    11931211            /* Choose random operations and measure their effect */
     
    12471265
    12481266                /* Save image! */
    1249                 //char buf[128];
    1250                 //sprintf(buf, "twit%08i.bmp", success);
    1251                 //if((success % 10) == 0)
    1252                 //    pipi_save(tmp, buf);
     1267                char buf[128];
     1268                sprintf(buf, "twit%08i.bmp", success);
     1269                if((success % 10) == 0)
     1270                    pipi_save(tmp, buf);
    12531271            }
    12541272            else
     
    12991317            x2 = (points[i + 1] / RANGE_Y) % RANGE_X;
    13001318            y2 = points[i + 1] % RANGE_Y;
    1301             uint32_t pack = pack_coords(x1, y1, x2, y2);
    1302 
    1303             b.push(points[i] / RANGE_XY, RANGE_SBGR);
    1304             b.push(points[i + 1] / RANGE_XY, RANGE_SBGR);
    1305             b.push(pack, RANGE_XYXY);
     1319
     1320            bool swap;
     1321            uint32_t pack = pack_coords(x1, y1, x2, y2, &swap);
     1322
     1323            b.push(points[i + (swap ? 1 : 0)] / RANGE_XY, RANGE_SBGR);
     1324            b.push(points[i + (swap ? 0 : 1)] / RANGE_XY, RANGE_SBGR);
     1325            b.push(pack, RANGE_XY2);
    13061326#else
    13071327            b.push(points[i], RANGE_SBGRXY);
     
    13221342        {
    13231343#if POINTS_PER_CELL == 2
    1324             uint32_t pack = b.pop(RANGE_XYXY);
     1344            uint32_t pack = b.pop(RANGE_XY2);
    13251345            uint32_t p2 = b.pop(RANGE_SBGR);
    13261346            uint32_t p1 = b.pop(RANGE_SBGR);
    13271347            int x1, y1, x2, y2;
     1348
    13281349            unpack_coords(pack, &x1, &y1, &x2, &y2);
    13291350            points[i * 2] = p1 * RANGE_XY + x1 * RANGE_Y + y1;
Note: See TracChangeset for help on using the changeset viewer.