Changeset 3537
 Timestamp:
 May 30, 2009, 6:01:09 PM (10 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

libpipi/trunk/examples/img2twit.cpp
r3536 r3537 67 67 static const uint32_t *unichars; 68 68 69 /* The maximum image size we want to support */ 70 #define RANGE_W 4000 71 #define RANGE_H 4000 69 /* The maximum image size we want to support, and the version range */ 70 #define RANGE_W 2000 71 #define RANGE_H 2000 72 #define RANGE_V 10 72 73 73 74 /* How does the algorithm work: one point per cell, or two? XXX: changing … … 118 119 static unsigned int TOTAL_CELLS; 119 120 120 #define RANGE_XY (RANGE_Y*RANGE_X)121 121 #define RANGE_XY2 (RANGE_Y*RANGE_X*(RANGE_Y*RANGE_X+1)/2) 122 #define RANGE_RXY (RANGE_Y*RANGE_X*RANGE_R) 123 #define RANGE_GRXY (RANGE_Y*RANGE_X*RANGE_R*RANGE_G) 124 #define RANGE_BGRXY (RANGE_Y*RANGE_X*RANGE_R*RANGE_G*RANGE_B) 122 #define RANGE_SBGR (RANGE_R*RANGE_G*RANGE_B*RANGE_S) 125 123 #define RANGE_SBGRXY (RANGE_Y*RANGE_X*RANGE_R*RANGE_G*RANGE_B*RANGE_S) 126 #define RANGE_SBGR (RANGE_R*RANGE_G*RANGE_B*RANGE_S)127 124 128 125 struct K : CGAL::Exact_predicates_inexact_constructions_kernel {}; … … 133 130 static unsigned int dw, dh; 134 131 132 /* Algorithm version */ 133 static unsigned int version; 134 135 135 /* Global point encoding */ 136 static uint32_t points[4096]; /* FIXME: allocate this dynamically */ 136 typedef struct point 137 { 138 uint8_t x, y, r, g, b, s; 139 } 140 point_t; 141 static point_t points[4096]; /* FIXME: allocate this dynamically */ 137 142 static int npoints = 0; 138 143 … … 147 152 { 148 153 TOTAL_BITS = MAX_MSG_LEN * logf(NUM_CHARACTERS) / logf(2); 149 HEADER_BITS = logf(RANGE_W * RANGE_H ) / logf(2);154 HEADER_BITS = logf(RANGE_W * RANGE_H * RANGE_V) / logf(2); 150 155 DATA_BITS = TOTAL_BITS  HEADER_BITS; 151 156 #if POINTS_PER_CELL == 2 … … 508 513 float fy = (y  dy * RANGE_Y) / RANGE_Y; 509 514 510 int iy = range2int(fy, RANGE_Y); 511 int ix = range2int(fx, RANGE_X); 512 513 int ir = range2int(r, RANGE_R); 514 int ig = range2int(g, RANGE_G); 515 int ib = range2int(b, RANGE_B); 516 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))))); 515 points[index].x = range2int(fx, RANGE_X); 516 points[index].y = range2int(fy, RANGE_Y); 517 518 points[index].r = range2int(r, RANGE_R); 519 points[index].g = range2int(g, RANGE_G); 520 points[index].b = range2int(b, RANGE_B); 521 522 points[index].s = range2int(s, RANGE_S); 521 523 } 522 524 … … 524 526 float *g, float *b, float *s, bool final = false) 525 527 { 526 uint32_t pt = points[index];527 528 int dx, dy; 528 529 529 530 index2cell(index, &dx, &dy); 530 531 531 float f y = int2midrange(pt % RANGE_Y, RANGE_Y); pt /= RANGE_Y;532 float f x = int2midrange(pt % RANGE_X, RANGE_X); pt /= RANGE_X;532 float fx = int2midrange(points[index].x, RANGE_X); 533 float fy = int2midrange(points[index].y, RANGE_Y); 533 534 534 535 *y = (fy + dy) * RANGE_Y /*+ 0.5 * (index & 1)*/; … … 537 538 if(final) 538 539 { 539 *r = int2fullrange(p t % RANGE_R, RANGE_R); pt /= RANGE_R;540 *g = int2fullrange(p t % RANGE_G, RANGE_G); pt /= RANGE_G;541 *b = int2fullrange(p t % RANGE_B, RANGE_B); pt /= RANGE_B;540 *r = int2fullrange(points[index].r, RANGE_R); 541 *g = int2fullrange(points[index].g, RANGE_G); 542 *b = int2fullrange(points[index].b, RANGE_B); 542 543 } 543 544 else 544 545 { 545 *r = int2midrange(p t % RANGE_R, RANGE_R); pt /= RANGE_R;546 *g = int2midrange(p t % RANGE_G, RANGE_G); pt /= RANGE_G;547 *b = int2midrange(p t % RANGE_B, RANGE_B); pt /= RANGE_B;548 } 549 550 *s = int2fullrange(p t % RANGE_S, RANGE_S); pt /= RANGE_S;546 *r = int2midrange(points[index].r, RANGE_R); 547 *g = int2midrange(points[index].g, RANGE_G); 548 *b = int2midrange(points[index].b, RANGE_B); 549 } 550 551 *s = int2fullrange(points[index].s, RANGE_S); 551 552 } 552 553 … … 590 591 static void add_random_point() 591 592 { 592 points[npoints] = det_rand(RANGE_SBGRXY); 593 points[npoints].x = det_rand(RANGE_X); 594 points[npoints].y = det_rand(RANGE_Y); 595 points[npoints].r = det_rand(RANGE_R); 596 points[npoints].g = det_rand(RANGE_G); 597 points[npoints].b = det_rand(RANGE_B); 598 points[npoints].s = det_rand(RANGE_S); 593 599 npoints++; 594 600 } … … 614 620 } 615 621 616 static uint32_t apply_op(uint8_t op, uint32_t val) 617 { 618 uint32_t rem, ext; 619 622 static void apply_op(uint8_t op, point_t *val) 623 { 620 624 switch(op) 621 625 { … … 624 628 /* Statistics show that this helps often, but does not reduce 625 629 * the error significantly. */ 626 rem = val % RANGE_BGRXY; 627 ext = val / RANGE_BGRXY; 628 ext ^= 1; 629 return ext * RANGE_BGRXY + rem; 630 val>s ^= 1; break; 630 631 case 2: /* Move up; if impossible, down */ 631 ext = val % RANGE_Y; 632 ext = ext > 0 ? ext  1 : ext + 1; 633 return val / RANGE_Y * RANGE_Y + ext; 632 val>y = val>y > 0 ? val>y  1 : val>y + 1; break; 634 633 case 3: /* Move down; if impossible, up */ 635 ext = val % RANGE_Y; 636 ext = ext < RANGE_Y  1 ? ext + 1 : ext  1; 637 return val / RANGE_Y * RANGE_Y + ext; 634 val>y = val>y + 1U < RANGE_Y ? val>y + 1 : val>y  1; break; 638 635 case 4: /* Move left; if impossible, right */ 639 rem = val % RANGE_Y; 640 ext = (val / RANGE_Y) % RANGE_X; 641 ext = ext > 0 ? ext  1 : ext + 1; 642 return (val / RANGE_XY * RANGE_X + ext) * RANGE_Y + rem; 643 case 5: /* Move left; if impossible, right */ 644 rem = val % RANGE_Y; 645 ext = (val / RANGE_Y) % RANGE_X; 646 ext = ext < RANGE_X  1 ? ext + 1 : ext  1; 647 return (val / RANGE_XY * RANGE_X + ext) * RANGE_Y + rem; 636 val>x = val>x > 0 ? val>x  1 : val>x + 1; break; 637 case 5: /* Move right; if impossible, left */ 638 val>x = val>x + 1U < RANGE_X ? val>x + 1 : val>x  1; break; 648 639 case 6: /* Corner 1 */ 649 return apply_op(2, apply_op(4, val)); 640 val>y = val>y > 0 ? val>y  1 : val>y + 1; 641 val>x = val>x > 0 ? val>x  1 : val>x + 1; break; 650 642 case 7: /* Corner 2 */ 651 return apply_op(2, apply_op(5, val)); 643 val>y = val>y > 0 ? val>y  1 : val>y + 1; 644 val>x = val>x + 1U < RANGE_X ? val>x + 1 : val>x  1; break; 652 645 case 8: /* Corner 3 */ 653 return apply_op(3, apply_op(5, val)); 646 val>y = val>y + 1U < RANGE_Y ? val>y + 1 : val>y  1; 647 val>x = val>x + 1U < RANGE_X ? val>x + 1 : val>x  1; break; 654 648 case 9: /* Corner 4 */ 655 return apply_op(3, apply_op(4, val)); 649 val>y = val>y + 1U < RANGE_Y ? val>y + 1 : val>y  1; 650 val>x = val>x > 0 ? val>x  1 : val>x + 1; break; 656 651 case 16: /* Double up */ 657 return apply_op(2, apply_op(2, val));652 val>y = val>y > 1 ? val>y  2 : val>y + 2; break; 658 653 case 17: /* Double down */ 659 return apply_op(3, apply_op(3, val));654 val>y = val>y + 2U < RANGE_Y ? val>y + 2 : val>y  2; break; 660 655 case 18: /* Double left */ 661 return apply_op(4, apply_op(4, val));656 val>x = val>x > 1 ? val>x  2 : val>x + 2; break; 662 657 case 19: /* Double right */ 663 return apply_op(5, apply_op(5, val));658 val>x = val>x + 2U < RANGE_X ? val>x + 2 : val>x  2; break; 664 659 case 10: /* R (or R++) */ 665 rem = val % RANGE_XY; 666 ext = (val / RANGE_XY) % RANGE_R; 667 ext = ext > 0 ? ext  1 : ext + 1; 668 return (val / RANGE_RXY * RANGE_R + ext) * RANGE_XY + rem; 660 val>r = val>r > 0 ? val>r  1 : val>r + 1; break; 669 661 case 11: /* R++ (or R) */ 670 rem = val % RANGE_XY; 671 ext = (val / RANGE_XY) % RANGE_R; 672 ext = ext < RANGE_R  1 ? ext + 1 : ext  1; 673 return (val / RANGE_RXY * RANGE_R + ext) * RANGE_XY + rem; 662 val>r = val>r + 1U < RANGE_R ? val>r + 1 : val>r  1; break; 674 663 case 12: /* G (or G++) */ 675 rem = val % RANGE_RXY; 676 ext = (val / RANGE_RXY) % RANGE_G; 677 ext = ext > 0 ? ext  1 : ext + 1; 678 return (val / RANGE_GRXY * RANGE_G + ext) * RANGE_RXY + rem; 664 val>g = val>g > 0 ? val>g  1 : val>g + 1; break; 679 665 case 13: /* G++ (or G) */ 680 rem = val % RANGE_RXY; 681 ext = (val / RANGE_RXY) % RANGE_G; 682 ext = ext < RANGE_G  1 ? ext + 1 : ext  1; 683 return (val / RANGE_GRXY * RANGE_G + ext) * RANGE_RXY + rem; 666 val>g = val>g + 1U < RANGE_G ? val>g + 1 : val>g  1; break; 684 667 case 14: /* B (or B++) */ 685 rem = val % RANGE_GRXY; 686 ext = (val / RANGE_GRXY) % RANGE_B; 687 ext = ext > 0 ? ext  1 : ext + 1; 688 return (val / RANGE_BGRXY * RANGE_B + ext) * RANGE_GRXY + rem; 668 val>b = val>b > 0 ? val>g  1 : val>b + 1; break; 689 669 case 15: /* B++ (or B) */ 690 rem = val % RANGE_GRXY; 691 ext = (val / RANGE_GRXY) % RANGE_B; 692 ext = ext < RANGE_B  1 ? ext + 1 : ext  1; 693 return (val / RANGE_BGRXY * RANGE_B + ext) * RANGE_GRXY + rem; 670 val>b = val>b + 1U < RANGE_B ? val>b + 1 : val>b  1; break; 694 671 #if 0 695 672 case 15: /* Brightness */ 696 return apply_op(9, apply_op(11, apply_op(13, val)));673 apply_op(9, val); apply_op(11, val); apply_op(13, val); break; 697 674 case 16: /* Brightness++ */ 698 return apply_op(10, apply_op(12, apply_op(14, val)));675 apply_op(10, val); apply_op(12, val); apply_op(14, val); break; 699 676 case 17: /* RG */ 700 return apply_op(9, apply_op(11, val));677 apply_op(9, val); apply_op(11, val); break; 701 678 case 18: /* RG++ */ 702 return apply_op(10, apply_op(12, val));679 apply_op(10, val); apply_op(12, val); break; 703 680 case 19: /* GB */ 704 return apply_op(11, apply_op(13, val));681 apply_op(11, val); apply_op(13, val); break; 705 682 case 20: /* GB++ */ 706 return apply_op(12, apply_op(14, val));683 apply_op(12, val); apply_op(14, val); break; 707 684 case 21: /* RB */ 708 return apply_op(9, apply_op(13, val));685 apply_op(9, val); apply_op(13, val); break; 709 686 case 22: /* RB++ */ 710 return apply_op(10, apply_op(14, val));687 apply_op(10, val); apply_op(14, val); break; 711 688 #endif 712 689 default: 713 return val;690 break; 714 691 } 715 692 } … … 1073 1050 b.push(uni2index(unicode_data[i]), NUM_CHARACTERS); 1074 1051 1052 /* The first thing we pop from the stream is the version information */ 1053 version = b.pop(RANGE_V); 1054 1075 1055 /* Read width and height from bitstream */ 1076 src = NULL;1077 1056 width = b.pop(RANGE_W) + 1; 1078 1057 height = b.pop(RANGE_H) + 1; 1058 src = NULL; 1079 1059 } 1080 1060 else … … 1089 1069 } 1090 1070 1071 version = 1; 1091 1072 width = pipi_get_image_width(src); 1092 1073 height = pipi_get_image_height(src); … … 1097 1078 fprintf(stderr, "Error: image size %ix%i is out of bounds\n", 1098 1079 width, height); 1080 return EXIT_FAILURE; 1081 } 1082 1083 if(version > 1) 1084 { 1085 fprintf(stderr, "Error: unsupported algorithm version %i\n", version); 1099 1086 return EXIT_FAILURE; 1100 1087 } … … 1142 1129 fprintf(stderr, "Available bits: %f\n", TOTAL_BITS); 1143 1130 fprintf(stderr, "Width/Height ranges: %ix%i\n", RANGE_W, RANGE_H); 1131 fprintf(stderr, "Algorithm version: %i\n", RANGE_V); 1144 1132 fprintf(stderr, "Image resolution: %ix%i\n", width, height); 1145 1133 fprintf(stderr, "Header bits: %f\n", HEADER_BITS); … … 1195 1183 /* Choose a point at random */ 1196 1184 int pt = det_rand(npoints); 1197 uint32_t oldval= points[pt];1185 point_t oldpt = points[pt]; 1198 1186 1199 1187 /* Compute the affected image zone */ … … 1213 1201 //uint8_t op2 = rand_op(); 1214 1202 1215 uint32_t candidates[3]; 1216 double besterr = error + 1.0; 1217 int bestop = 1; 1218 candidates[0] = apply_op(op1, oldval); 1219 //candidates[1] = apply_op(op2, oldval); 1220 //candidates[2] = apply_op(op1, apply_op(op2, oldval)); 1221 1222 for(int i = 0; i < 1; i++) 1223 //for(int i = 0; i < 3; i++) 1203 apply_op(op1, &points[pt]); 1204 1205 #if POINTS_PER_CELL == 2 1206 /* Check that two points don't fall at the same place */ 1207 while(points[pt].x == points[pt ^ 1].x 1208 && points[pt].y == points[pt ^ 1].y) 1224 1209 { 1225 if(oldval == candidates[i]) 1226 continue; 1227 1228 points[pt] = candidates[i]; 1229 1230 render(scrap, zonex * RANGE_X, zoney * RANGE_Y, 1231 zonew * RANGE_X, zoneh * RANGE_Y, false); 1232 1233 double newerr = pipi_measure_rmsd(src, scrap); 1234 if(newerr < besterr) 1235 { 1236 besterr = newerr; 1237 bestop = i; 1238 } 1210 points[pt] = oldpt; 1211 op1 = rand_op(); 1212 apply_op(op1, &points[pt]); 1239 1213 } 1214 #endif 1215 1216 render(scrap, zonex * RANGE_X, zoney * RANGE_Y, 1217 zonew * RANGE_X, zoneh * RANGE_Y, false); 1218 1219 double newerr = pipi_measure_rmsd(src, scrap); 1240 1220 1241 1221 opstats[op1 * 2]++; 1242 1222 //opstats[op2 * 2]++; 1243 1223 1244 if( besterr < error)1224 if(newerr < error) 1245 1225 { 1246 points[pt] = candidates[bestop];1247 /* Redraw image if the last check wasn't the best one */1248 if(bestop != 0)1249 render(scrap, zonex * RANGE_X, zoney * RANGE_Y,1250 zonew * RANGE_X, zoneh * RANGE_Y, false);1251 1252 1226 pipi_free(tmp); 1227 1228 #if 0 1229 /* Save image! */ 1230 if((success % 10) == 0) 1231 { 1232 char buf[128]; 1233 sprintf(buf, "twit%08i.bmp", success); 1234 tmp = pipi_new(width, height); 1235 render(tmp, 0, 0, width, height, true); 1236 pipi_save(tmp, buf); 1237 pipi_free(tmp); 1238 } 1239 #endif 1240 1253 1241 tmp = scrap; 1254 1242 1255 1243 if(DEBUG_MODE) 1256 fprintf(stderr, "%08i  .%08i %2.010g after op%i(%i)\n",1257 iter, (int)((error  besterr) * 100000000), error,1258 op1, pt);1259 1260 error = besterr;1244 fprintf(stderr, "%08i 0.%010i %2.010g after op%i(%i)\n", 1245 iter, (int)((error  newerr) * 10000000000L), 1246 error, op1, pt); 1247 1248 error = newerr; 1261 1249 opstats[op1 * 2 + 1]++; 1262 1250 //opstats[op2 * 2 + 1]++; 1263 1251 failures = 0; 1264 1252 success++; 1265 1266 /* Save image! */1267 char buf[128];1268 sprintf(buf, "twit%08i.bmp", success);1269 if((success % 10) == 0)1270 pipi_save(tmp, buf);1271 1253 } 1272 1254 else 1273 1255 { 1274 1256 pipi_free(scrap); 1275 points[pt] = old val;1257 points[pt] = oldpt; 1276 1258 failures++; 1277 1259 } … … 1299 1281 fprintf(stderr, "\r \r"); 1300 1282 1301 #if 01283 #if 1 1302 1284 dst = pipi_resize(tmp, width, height); 1303 1285 pipi_free(tmp); … … 1313 1295 #if POINTS_PER_CELL == 2 1314 1296 int x1, y1, x2, y2; 1315 x1 = (points[i] / RANGE_Y) % RANGE_X;1316 y1 = points[i] % RANGE_Y;1317 x2 = (points[i + 1] / RANGE_Y) % RANGE_X;1318 y2 = points[i + 1] % RANGE_Y;1297 x1 = points[i].x; 1298 y1 = points[i].y; 1299 x2 = points[i + 1].x; 1300 y2 = points[i + 1].y; 1319 1301 1320 1302 bool swap; 1321 1303 uint32_t pack = pack_coords(x1, y1, x2, y2, &swap); 1322 1304 1323 b.push(points[i + (swap ? 1 : 0)] / RANGE_XY, RANGE_SBGR); 1324 b.push(points[i + (swap ? 0 : 1)] / RANGE_XY, RANGE_SBGR); 1305 b.push(points[i + (swap ? 1 : 0)].s, RANGE_S); 1306 b.push(points[i + (swap ? 1 : 0)].b, RANGE_B); 1307 b.push(points[i + (swap ? 1 : 0)].g, RANGE_G); 1308 b.push(points[i + (swap ? 1 : 0)].r, RANGE_R); 1309 b.push(points[i + (swap ? 0 : 1)].s, RANGE_S); 1310 b.push(points[i + (swap ? 0 : 1)].b, RANGE_B); 1311 b.push(points[i + (swap ? 0 : 1)].g, RANGE_G); 1312 b.push(points[i + (swap ? 0 : 1)].r, RANGE_R); 1325 1313 b.push(pack, RANGE_XY2); 1326 1314 #else 1327 b.push(points[i], RANGE_SBGRXY); 1315 b.push(points[i].s, RANGE_S); 1316 b.push(points[i].b, RANGE_B); 1317 b.push(points[i].g, RANGE_G); 1318 b.push(points[i].r, RANGE_R); 1319 b.push(points[i].x, RANGE_X); 1320 b.push(points[i].y, RANGE_Y); 1328 1321 #endif 1329 1322 } 1330 1323 b.push(height  1, RANGE_H); 1331 1324 b.push(width  1, RANGE_W); 1325 b.push(version, RANGE_V); 1332 1326 1333 1327 /* Pop Unicode characters from the bitstream and print them */ … … 1343 1337 #if POINTS_PER_CELL == 2 1344 1338 uint32_t pack = b.pop(RANGE_XY2); 1345 uint32_t p2 = b.pop(RANGE_SBGR);1346 uint32_t p1 = b.pop(RANGE_SBGR);1347 1339 int x1, y1, x2, y2; 1348 1349 1340 unpack_coords(pack, &x1, &y1, &x2, &y2); 1350 points[i * 2] = p1 * RANGE_XY + x1 * RANGE_Y + y1; 1351 points[i * 2 + 1] = p2 * RANGE_XY + x2 * RANGE_Y + y2; 1341 1342 points[i * 2 + 1].y = y2; 1343 points[i * 2 + 1].x = x2; 1344 points[i * 2 + 1].r = b.pop(RANGE_R); 1345 points[i * 2 + 1].g = b.pop(RANGE_G); 1346 points[i * 2 + 1].b = b.pop(RANGE_B); 1347 points[i * 2 + 1].s = b.pop(RANGE_S); 1348 points[i * 2].y = y1; 1349 points[i * 2].x = x1; 1350 points[i * 2].r = b.pop(RANGE_R); 1351 points[i * 2].g = b.pop(RANGE_G); 1352 points[i * 2].b = b.pop(RANGE_B); 1353 points[i * 2].s = b.pop(RANGE_S); 1352 1354 #else 1353 points[i] = b.pop(RANGE_SBGRXY); 1355 points[i].y = b.pop(RANGE_Y); 1356 points[i].x = b.pop(RANGE_X); 1357 points[i].r = b.pop(RANGE_R); 1358 points[i].g = b.pop(RANGE_G); 1359 points[i].b = b.pop(RANGE_B); 1360 points[i].s = b.pop(RANGE_S); 1354 1361 #endif 1355 1362 }
Note: See TracChangeset
for help on using the changeset viewer.