# HG changeset patch # User Tero Marttila # Date 1264449842 -7200 # Node ID 578d90d0cf926184911f01669c2ecf1ac2e6910f # Parent aee9d0b12fe98aa013903d5292d68aff5b77fb73 refactor main.c into do_tile, add --benchmark, --randomize diff -r aee9d0b12fe9 -r 578d90d0cf92 src/pngtile/main.c --- a/src/pngtile/main.c Mon Jan 25 22:03:41 2010 +0200 +++ b/src/pngtile/main.c Mon Jan 25 22:04:02 2010 +0200 @@ -8,6 +8,14 @@ #include #include +enum option_names { + + _OPT_LONGONLY = 255, + + OPT_BENCHMARK, + OPT_RANDOMIZE, +}; + /** * Command-line options */ @@ -26,7 +34,11 @@ { "zoom", true, NULL, 'z' }, { "out", true, NULL, 'o' }, { "threads", true, NULL, 'j' }, - { 0, 0, 0, 0 } + + // --long-only options + { "benchmark", true, NULL, OPT_BENCHMARK }, + { "randomize", false, NULL, OPT_RANDOMIZE }, + { 0, 0, 0, 0 } }; /** @@ -39,27 +51,148 @@ "Open each of the given image files, check cache status, optionally update their cache, display image info, and\n" "optionally render a tile of each.\n" "\n" - "\t-h, --help show this help and exit\n" - "\t-q, --quiet supress informational output\n" - "\t-v, --verbose display more informational output\n" - "\t-D, --debug equivalent to -v\n" - "\t-U, --force-update unconditionally update image caches\n" - "\t-N, --no-update do not update the image cache\n" - "\t-B, --background set background pattern for sparse cache file: 0xHH..\n" - "\t-W, --width set tile width\n" - "\t-H, --height set tile height\n" - "\t-x, --x set tile x offset\n" - "\t-y, --y set tile y offset\n" - "\t-z, --zoom set zoom factor (<0)\n" - "\t-o, --out set tile output file\n" - "\t-j, --threads number of threads\n" + "\t-h, --help show this help and exit\n" + "\t-q, --quiet supress informational output\n" + "\t-v, --verbose display more informational output\n" + "\t-D, --debug equivalent to -v\n" + "\t-U, --force-update unconditionally update image caches\n" + "\t-N, --no-update do not update the image cache\n" + "\t-B, --background set background pattern for sparse cache file: 0xHH..\n" + "\t-W, --width PX set tile width\n" + "\t-H, --height PX set tile height\n" + "\t-x, --x PX set tile x offset\n" + "\t-y, --y PX set tile y offset\n" + "\t-z, --zoom ZL set zoom factor (<0)\n" + "\t-o, --out FILE set tile output file\n" + "\t-j, --threads N number of threads\n" + "\t--benchmark N do N tile renders\n" + "\t--randomize randomize tile x/y coords\n" ); } +unsigned long parse_uint (const char *val, const char *name) +{ + char *endptr; + long int out; + + // decode + out = strtol(val, &endptr, 0); + + // validate + if (*endptr || out < 0) + EXIT_ERROR(EXIT_FAILURE, "Invalid value for %s: %s", name, val); + + // ok + return out; +} + +signed long parse_sint (const char *val, const char *name) +{ + char *endptr; + long int out; + + // decode + out = strtol(val, &endptr, 0); + + // validate + if (*endptr) + EXIT_ERROR(EXIT_FAILURE, "Invalid value for %s: %s", name, val); + + // ok + return out; +} + +long randrange (long start, long end) +{ + return start + (rand() * (end - start) / RAND_MAX); +} + +/** + * Randomize tile x/y with given image info + */ +void randomize_tile (struct pt_tile_info *ti, const struct pt_image_info *info) +{ + ti->x = randrange(0, info->img_width - ti->width); + ti->y = randrange(0, info->img_height - ti->height); +} + +/** + * Render a tile + */ +int do_tile (struct pt_ctx *ctx, struct pt_image *image, const struct pt_tile_info *ti, const char *out_path) +{ + FILE *out_file = NULL; + char tmp_name[] = "pt-tile-XXXXXX"; + int err = 0; + + if (!out_path) { + int fd; + + // temporary file for output + if ((fd = mkstemp(tmp_name)) < 0) { + log_errno("mkstemp"); + goto error; + } + + out_path = tmp_name; + + // open out + if ((out_file = fdopen(fd, "wb")) == NULL) { + log_errno("fdopen"); + goto error; + } + + } else if (strcmp(out_path, "-") == 0) { + // use stdout + if ((out_file = fdopen(STDOUT_FILENO, "wb")) == NULL) { + log_errno("fdopen: STDOUT_FILENO"); + goto error; + } + + } else { + // use file + if ((out_file = fopen(out_path, "wb")) == NULL) { + log_errno("fopen: %s", out_path); + goto error; + } + + } + + + if (ctx) { + // render + log_info("\tAsync render tile %zux%zu@(%zu,%zu) -> %s", ti->width, ti->height, ti->x, ti->y, out_path); + + if ((err = pt_image_tile_async(image, ti, out_file))) { + log_errno("pt_image_tile_async: %s", pt_strerror(err)); + goto error; + } + + // will close it itself + out_file = NULL; + + } else { + // render + log_info("\tRender tile %zux%zu@(%zu,%zu) -> %s", ti->width, ti->height, ti->x, ti->y, out_path); + + if ((err = pt_image_tile_file(image, ti, out_file))) { + log_errno("pt_image_tile_file: %s", pt_strerror(err)); + goto error; + } + } + +error: + // cleanup + if (out_file && fclose(out_file)) + log_warn_errno("fclose: out_file"); + + return err; +} + int main (int argc, char **argv) { int opt; - bool force_update = false, no_update = false; + bool force_update = false, no_update = false, randomize = false; struct pt_tile_info ti = { .width = 800, .height = 600, @@ -69,8 +202,8 @@ }; struct pt_image_params update_params = { }; const char *out_path = NULL; - int threads = 0; - int tmp, err; + int threads = 0, benchmark = 0; + int err; // parse arguments while ((opt = getopt_long(argc, argv, "hqvDUNB:W:H:x:y:z:o:j:", options, NULL)) != -1) { @@ -83,28 +216,20 @@ case 'q': // supress excess log output - set_log_level(LOG_WARN); - - break; + set_log_level(LOG_WARN); break; case 'v': case 'D': // display additional output - set_log_level(LOG_DEBUG); - - break; + set_log_level(LOG_DEBUG); break; case 'U': // force update of image caches - force_update = true; - - break; + force_update = true; break; case 'N': // supress update of image caches - no_update = true; - - break; + no_update = true; break; case 'B': // background pattern @@ -124,31 +249,32 @@ } break; case 'W': - ti.width = strtol(optarg, NULL, 0); break; + ti.width = parse_uint(optarg, "--width"); break; case 'H': - ti.height = strtol(optarg, NULL, 0); break; + ti.height = parse_uint(optarg, "--height"); break; case 'x': - ti.x = strtol(optarg, NULL, 0); break; + ti.x = parse_uint(optarg, "--x"); break; case 'y': - ti.y = strtol(optarg, NULL, 0); break; + ti.y = parse_uint(optarg, "--y"); break; case 'z': - ti.zoom = strtol(optarg, NULL, 0); break; + ti.zoom = parse_sint(optarg, "--zoom"); break; case 'o': // output file - out_path = optarg; - - break; + out_path = optarg; break; case 'j': - if ((tmp = strtol(optarg, NULL, 0)) < 1) - FATAL("Invalid value for -j/--threads: %s", optarg); + threads = parse_uint(optarg, "--threads"); break; - threads = tmp; break; + case OPT_BENCHMARK: + benchmark = parse_uint(optarg, "--benchmark"); break; + + case OPT_RANDOMIZE: + randomize = true; break; case '?': // useage error @@ -258,64 +384,29 @@ } // render tile? - if (out_path) { - FILE *out_file; - char tmp_name[] = "pt-tile-XXXXXX"; + if (benchmark) { + log_info("\tRunning %d %stile renders...", benchmark, randomize ? "randomized " : ""); - if (strcmp(out_path, "-") == 0) { - // use stdout - if ((out_file = fdopen(STDOUT_FILENO, "wb")) == NULL) { - log_errno("fdopen: STDOUT_FILENO"); + // n times + for (int i = 0; i < benchmark; i++) { + // randomize x, y + if (randomize) + randomize_tile(&ti, info); + + if (do_tile(ctx, image, &ti, out_path)) goto error; - } - - } else if (false /* tmp */) { - int fd; - - // temporary file for output - if ((fd = mkstemp(tmp_name)) < 0) { - log_errno("mkstemp"); - goto error; - } - - out_path = tmp_name; - - // open out - if ((out_file = fdopen(fd, "wb")) == NULL) { - log_errno("fdopen"); - goto error; - } - - } else { - // use file - if ((out_file = fopen(out_path, "wb")) == NULL) { - log_errno("fopen: %s", out_path); - goto error; - } - } - - if (ctx) { - // render - log_info("\tAsync render tile %zux%zu@(%zu,%zu) -> %s", ti.width, ti.height, ti.x, ti.y, out_path); - - if ((err = pt_image_tile_async(image, &ti, out_file))) - log_errno("pt_image_tile_async: %s: %s", img_path, pt_strerror(err)); + } else if (out_path) { + // randomize x, y + if (randomize) + randomize_tile(&ti, info); - } else { - // render - log_info("\tRender tile %zux%zu@(%zu,%zu) -> %s", ti.width, ti.height, ti.x, ti.y, out_path); + // just once + if (do_tile(ctx, image, &ti, out_path)) + goto error; - if ((err = pt_image_tile_file(image, &ti, out_file))) - log_errno("pt_image_tile_file: %s: %s", img_path, pt_strerror(err)); - - // cleanup - if (fclose(out_file)) - log_warn_errno("fclose: out_file"); - } } - error: // cleanup // XXX: leak because of async