render_file.c
changeset 0 5b010627d7ed
child 1 6aa1a0d1f88d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/render_file.c	Fri May 30 14:24:23 2008 +0300
@@ -0,0 +1,173 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "mandelbrot.h"
+#include "common.h"
+
+static int verbose;
+
+int file_write (const unsigned char *data, size_t length, void *arg) {
+    size_t ret = fwrite(data, length, 1, (FILE *) arg);
+    
+    return (ret == 1) ? RENDER_CB_OK : RENDER_CB_ERR;
+}
+
+void render_local (int img_w, int img_h, FILE *output) {
+    struct render_ctx ctx;
+
+    render_ctx_set(&ctx, &file_write, NULL, output);
+
+    double duration;
+
+    if (mandelbrot_render_full_timed(
+            &ctx, 
+            img_w, img_h, 
+            &duration
+    ) != MANDELBROT_OK)
+        err_exit("mandelbrot_render_region failed");
+    
+    if (verbose) 
+        fprintf(stdout, "rendered %dx%d mandelbrot in %f seconds\n", img_w, img_h, duration);
+}
+
+void render_remote (int img_w, int img_h, FILE *output, FILE *remote) {
+    struct render_cmd cmd;
+
+    if (render_cmd_set_full(&cmd, img_w, img_h) != MANDELBROT_OK) {
+        err_exit("mandelbrot_render_remote failed");
+    }
+
+    int ret = fwrite((void *) &cmd, sizeof(cmd), 1, remote);
+    
+    if (ret != 1)
+        perr_exit("fwrite(remote)");
+        
+    if (verbose)
+        printf("sent render command of %zu bytes\n", sizeof(cmd));
+
+    // shuffle data around
+    while (!feof(remote)) {
+        char buf[1024];
+
+        int bytes = fread(buf, 1, sizeof(buf), remote);
+
+        if (bytes)
+            if (fwrite(buf, bytes, 1, output) != 1)
+                perr_exit("fwrite(output)");
+    }
+    
+    if (verbose)
+        printf("got PNG data\n");
+
+    if (ferror(remote))
+        perr_exit("fread(remote)");
+}
+
+FILE *open_remote (char *remote) {
+    char *addr_str, *port_str = NULL;
+
+    addr_str = strsep(&remote, ":");
+
+    if (remote)
+        port_str = remote;
+    
+    struct sockaddr_in addr;
+
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port_str ? atoi(port_str) : RENDER_PORT);
+    
+    if (inet_aton(addr_str, &addr.sin_addr) == 0)
+        err_exit("invalid address: %s", addr_str);
+
+    int sock;
+    
+    if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
+        perr_exit("socket");
+
+    if (verbose)
+        printf("connect(%s, %d)\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+    
+    if (connect(sock, (const struct sockaddr *) &addr, sizeof(addr)) == -1)
+        perr_exit("connect(%s, %d)", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+    
+    FILE *fh = fdopen(sock, "w+");
+
+    if (!fh || ferror(fh))
+        perr_exit("fdopen");
+
+    setbuffer(fh, NULL, 0);
+
+    return fh;
+}
+
+int main (int argc, char **argv) {
+    int opt;
+    
+    FILE *output = NULL, *remote = NULL;
+    int img_w = 256, img_h = 256;
+    
+
+    while ((opt = getopt(argc, argv, "w:h:o:vr:")) != -1) {
+        switch(opt) {
+            case 'w' :
+                img_w = atoi(optarg);
+                break;
+
+            case 'h' :
+                img_h = atoi(optarg);
+                break;
+
+            case 'o' :
+                if (output)
+                    err_exit("Only use -o once");
+
+                output = fopen(optarg, "w");
+
+                if (!output)
+                    die(optarg);
+
+                break;
+
+            case 'v' :
+                verbose = 1;
+                break;
+
+            case 'r' :
+                if (remote)
+                    err_exit("Only use -r once");
+
+                remote = open_remote(optarg);
+
+                break;
+
+            default :
+                err_exit("Usage: %s [-w img_w] [-h img_h] [-o output_file] [-v] [-r host[:port]]", argv[0]);
+        }
+    }
+
+    if (!output)
+        output = stdout;
+    
+    if (remote) {
+        if (verbose)
+            fprintf(stderr, "Render [%dx%d] mandelbrot remotely\n", img_w, img_h);
+
+        render_remote(img_w, img_h, output, remote);
+
+        fclose(remote);
+    } else {
+        if (verbose)
+            fprintf(stderr, "Render [%dx%d] mandelbrot locally\n", img_w, img_h);
+
+        render_local(img_w, img_h, output);
+    }
+
+    fclose(output);
+
+    return 0;
+}