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.