refactor main.c into do_tile, add --benchmark, --randomize
authorTero Marttila <terom@fixme.fi>
Mon, 25 Jan 2010 22:04:02 +0200
changeset 101 578d90d0cf92
parent 100 aee9d0b12fe9
child 102 a4d1e046ed3e
refactor main.c into do_tile, add --benchmark, --randomize
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 <unistd.h>
 #include <stdbool.h>
 
+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