source: trunk/src/testing/app/JuxtaView/main.cpp @ 4

Revision 4, 32.4 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/*=============================================================================
2
3  Program: JuxtaView for SAGE
4  Module:  main.cpp - main MPI control for JuxtaView
5  Authors: Nicholas Schwarz, schwarz@evl.uic.edu,
6           Arun Rao, arao@evl.uic.edu,
7           Luc Renambot, luc@evl.uic.edu,
8           et al.
9  Date:    30 September 2004
10  Modified: 9 September 2005
11
12   Copyright (C) 2004 Electronic Visualization Laboratory,
13 * University of Illinois at Chicago
14 *
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are met:
19 *
20 *  * Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 *  * Redistributions in binary form must reproduce the above
23 *    copyright notice, this list of conditions and the following disclaimer
24 *    in the documentation and/or other materials provided with the distribution.
25 *  * Neither the name of the University of Illinois at Chicago nor
26 *    the names of its contributors may be used to endorse or promote
27 *    products derived from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
33 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Direct questions, comments etc to schwarz@evl.uic.edu or
42 * http://www.evl.uic.edu/cavern/forum/
43
44  Direct questions, comments, etc. to schwarz@evl.uic.edu or
45  http://www.evl.uic.edu/cavern/forum/
46
47=============================================================================*/
48
49
50#include <stddef.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54
55// for MPI
56#include "mpi.h"
57
58// for UI
59#include "JuxtaUIServer.h"
60
61// for communication with UI via QUANTA
62#include <QUANTA/QUANTAinit.hxx>
63#include <QUANTA/QUANTAnet_tcp_c.hxx>
64
65// for converting global image coordinates, in pixels, to
66// individual files and their respective extents
67#include "GlobalCoordinatesToFileMapper.h"
68
69// for reading tiff files
70#include <tiffio.h>
71
72// for SAGE
73#include <sail.h>
74#include <misc.h>
75
76// SAGE Stuff
77int winWidth, winHeight;
78sail sageInf; // sail object
79
80#define LEFT 0
81#define RIGHT 1
82#define UP 2
83#define DOWN 3
84#define FASTLEFT 4
85#define FASTRIGHT 5
86#define FASTUP 6
87#define FASTDOWN 7
88#define ZOOMOUT 8
89#define ZOOMIN 9
90#define QUIT 10
91#define EXTENTS 11
92#define OVERVIEW 12
93#define FREETRANS 13
94#define RESEND 14
95
96// windows border definitions
97#define DBDR_TBLR 0
98#define DBDR_TB 1
99#define DBDR_LR 2
100#define DBDR_TL 3
101#define DBDR_TR 4
102#define DBDR_BL 5
103#define DBDR_BR 6
104#define DBDR_T 7
105#define DBDR_B 8
106#define DBDR_L 9
107#define DBDR_R 10
108#define DBDR_N 11
109#define DBDR_TLR 12
110#define DBDR_BLR 13
111#define DBDR_TBL 14
112#define DBDR_TBR 15
113
114#include <time.h>
115
116
117/* data set information */
118typedef struct {
119  long origin_x;         // image origin, usually 0,0
120  long origin_y;         // image origin, usually 0,0
121  long image_width;      // image width
122  long image_height;     // image height
123  long start_x;          // start position
124  long start_y;          // start position
125  long pan_amount;       // number of pixels to pan
126  long fast_pan_amount;  // number of pixels to fast pan
127  long fetch_w;          // horizontal extent to fetch, i.e. window size
128  long fetch_h;          // vertical extent to fetch, i.e. window size
129  int samplerate;        // sample rate for overview file
130  char name[512];        // overview file name
131} description;
132
133
134/* extent within the global image in pixel coordinates and the command */
135typedef struct {
136  long x;
137  long y;
138  long w;
139  long h;
140  long command;
141  long zoom;
142  long border;
143} info;
144
145
146/* viewport in normalized coordinates */
147typedef struct {
148  float x_min;
149  float y_min;
150  float x_max;
151  float y_max;
152  long border;
153  char ip[16];
154} viewport;
155
156
157/* begin - read config file given file name and return array of viewport */
158viewport* read_config(const char* name) {
159
160  // number of nodes in addition to master
161  int num;
162
163  // border
164  char border[10];
165
166  // file pointer
167  FILE *fptr = NULL;
168
169  // attempt to open the configuration file.
170  if ((fptr = fopen(name, "r")) == NULL)
171    return NULL;
172
173  // read number of nodes
174  fscanf(fptr, "%d", &num);
175
176  // allocate space for node configuration
177  viewport* viewports = (viewport*) malloc(sizeof(viewport) * num);
178
179  // check if memory allocation succeded
180  if (viewports == NULL)
181    return NULL;
182
183  // Read configuration data
184  for (int i = 0 ; i < num ; i++)
185    {
186      // read viewports
187      fscanf(fptr, "%f", &viewports[i].x_min);
188      //printf("%f\n", viewports[i].x_min);
189      fscanf(fptr, "%f", &viewports[i].y_min);
190      //printf("%f\n", viewports[i].y_min);
191      fscanf(fptr, "%f", &viewports[i].x_max);
192      //printf("%f\n", viewports[i].x_max);
193      fscanf(fptr, "%f", &viewports[i].y_max);
194      //printf("%f\n", viewports[i].y_max);
195      fscanf(fptr, "%s", border);
196      //printf("%s\n\n", border);
197
198      // determine and set border type
199      if (!strcmp(border, "BDR_TBLR")) {
200        viewports[i].border = DBDR_TBLR;
201      }
202      else if (!strcmp(border, "BDR_TB")) {
203        viewports[i].border = DBDR_TB;
204      }
205      else if (!strcmp(border, "BDR_LR")) {
206        viewports[i].border = DBDR_LR;
207      }
208      else if (!strcmp(border, "BDR_TL")) {
209        viewports[i].border = DBDR_TL;
210      }
211      else if (!strcmp(border, "BDR_TR")) {
212        viewports[i].border = DBDR_TR;
213      }
214      else if (!strcmp(border, "BDR_BL")) {
215        viewports[i].border = DBDR_BL;
216      }
217      else if (!strcmp(border, "BDR_BR")) {
218        viewports[i].border = DBDR_BR;
219      }
220      else if (!strcmp(border, "BDR_T")) {
221        viewports[i].border = DBDR_T;
222      }
223      else if (!strcmp(border, "BDR_B")) {
224        viewports[i].border = DBDR_B;
225      }
226      else if (!strcmp(border, "BDR_L")) {
227        viewports[i].border = DBDR_L;
228      }
229      else if (!strcmp(border, "BDR_R")) {
230        viewports[i].border = DBDR_R;
231      }
232      else if (!strcmp(border, "BDR_N")) {
233        viewports[i].border = DBDR_N;
234      }
235      else if (!strcmp(border, "BDR_TLR")) {
236        viewports[i].border = DBDR_TLR;
237      }
238      else if (!strcmp(border, "BDR_BLR")) {
239        viewports[i].border = DBDR_BLR;
240      }
241      else if (!strcmp(border, "BDR_TBL")) {
242        viewports[i].border = DBDR_TBL;
243      }
244      else if (!strcmp(border, "BDR_TBR")) {
245        viewports[i].border = DBDR_TBR;
246      }
247      else {
248        viewports[i].border = DBDR_N;
249      }
250
251      fscanf(fptr, "%s", viewports[i].ip);
252      //printf("%s\n", viewports[i].ip);
253
254    }
255
256  // close file
257  fclose(fptr);
258
259  // return
260  return viewports;
261
262} /* end - read config file */
263
264
265/* begin - read data description file given file name */
266description read_data(const char* name) {
267
268  // data description
269  description data;
270
271  // file pointer
272  FILE *fptrd = NULL;
273
274  // attempt to open the configuration file.
275  if ((fptrd = fopen(name, "r")) == NULL) {
276    printf("Can not read data description file.\n");
277    exit(EXIT_FAILURE);
278  }
279
280  // read origin and extent
281  fscanf(fptrd, "%ld %ld %ld %ld", &data.origin_x, &data.origin_y,
282         &data.image_width, &data.image_height);
283
284  // read starting position
285  fscanf(fptrd, "%ld %ld", &data.start_x, &data.start_y);
286
287  // read pan values
288  fscanf(fptrd, "%ld %ld", &data.pan_amount, &data.fast_pan_amount);
289
290  // width and height of data to fetch
291  fscanf(fptrd, "%ld %ld", &data.fetch_w, &data.fetch_h);
292
293  // overview file sample rate
294  fscanf(fptrd, "%d", &data.samplerate);
295
296  // overview file name
297  fscanf(fptrd, "%s", data.name);
298
299  // close file
300  fclose(fptrd);
301
302  // return true
303  return data;
304
305} /* end - read data description file */
306
307
308/* begin - add border to the top; called by add_border */
309void add_border_top(unsigned char* buffer, info extent) {
310
311  unsigned char r = 139;
312  unsigned char g = 161;
313  unsigned char b = 105;
314
315  for (long row = 0 ; row < 8 ; row++) {
316    for (long col = 0 ; col < (extent.w / extent.zoom) ; col++) {
317      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3)] = r;
318      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 1] = g;
319      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 2] = b;
320    }
321  }
322
323} /* end - add border to the top; called by add_border */
324
325
326/* begin - add border to the top; called by add_border */
327void add_border_bottom(unsigned char* buffer, info extent) {
328
329  unsigned char r = 139;
330  unsigned char g = 161;
331  unsigned char b = 105;
332
333  for (long row = (extent.h / extent.zoom) - 8 ;
334       row < (extent.h / extent.zoom) ;
335       row++) {
336    for (long col = 0 ; col < (extent.w / extent.zoom) ; col++) {
337      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3)] = r;
338      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 1] = g;
339      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 2] = b;
340    }
341  }
342
343} /* end - add border to the bottom; called by add_border */
344
345
346/* begin - add border to the left; called by add_border */
347void add_border_left(unsigned char* buffer, info extent) {
348
349  unsigned char r = 139;
350  unsigned char g = 161;
351  unsigned char b = 105;
352
353  for (long col = 0 ; col < 8 ; col++) {
354    for (long row = 0 ; row < (extent.h / extent.zoom) ; row++) {
355      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3)] = r;
356      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 1] = g;
357      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 2] = b;
358    }
359  }
360
361} /* end - add border to the left; called by add_border */
362
363
364/* begin - add border to the right; called by add_border */
365void add_border_right(unsigned char* buffer, info extent) {
366
367  unsigned char r = 139;
368  unsigned char g = 161;
369  unsigned char b = 105;
370
371  for (long col = (extent.w / extent.zoom) - 8 ;
372       col < (extent.w / extent.zoom) ;
373       col++) {
374    for (long row = 0 ; row < (extent.h / extent.zoom) ; row++) {
375      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3)] = r;
376      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 1] = g;
377      buffer[row * 3 * (extent.w / extent.zoom) + (col * 3) + 2] = b;
378    }
379  }
380
381} /* end - add border to the right; called by add_border */
382
383
384/* begin - add border to the buffer */
385void add_border(unsigned char* buffer, info extent) {
386
387  switch(extent.border) {
388  case DBDR_TBLR:
389    add_border_top(buffer, extent);
390    add_border_bottom(buffer, extent);
391    add_border_left(buffer, extent);
392    add_border_right(buffer, extent);
393    break;
394  case DBDR_TB:
395    add_border_top(buffer, extent);
396    add_border_bottom(buffer, extent);
397    break;
398  case DBDR_LR:
399    add_border_left(buffer, extent);
400    add_border_right(buffer, extent);
401    break;
402  case DBDR_TL:
403    add_border_top(buffer, extent);
404    add_border_left(buffer, extent);
405    break;
406  case DBDR_TR:
407    add_border_top(buffer, extent);
408    add_border_right(buffer, extent);
409    break;
410  case DBDR_BL:
411    add_border_bottom(buffer, extent);
412    add_border_left(buffer, extent);
413    break;
414  case DBDR_BR:
415    add_border_bottom(buffer, extent);
416    add_border_right(buffer, extent);
417    break;
418  case DBDR_T:
419    add_border_top(buffer, extent);
420    break;
421  case DBDR_B:
422    add_border_bottom(buffer, extent);
423    break;
424  case DBDR_L:
425    add_border_left(buffer, extent);
426    break;
427  case DBDR_R:
428    add_border_right(buffer, extent);
429    break;
430  case DBDR_N:
431    break;
432  case DBDR_TLR:
433    add_border_top(buffer, extent);
434    add_border_left(buffer, extent);
435    add_border_right(buffer, extent);
436    break;
437  case DBDR_BLR:
438    add_border_bottom(buffer, extent);
439    add_border_left(buffer, extent);
440    add_border_right(buffer, extent);
441    break;
442  case DBDR_TBL:
443    add_border_top(buffer, extent);
444    add_border_bottom(buffer, extent);
445    add_border_left(buffer, extent);
446    break;
447  case DBDR_TBR:
448    add_border_top(buffer, extent);
449    add_border_bottom(buffer, extent);
450    add_border_right(buffer, extent);
451    break;
452  }
453
454} /* end - add border to the buffer */
455
456
457/* begin - main */
458int main(int argc, char** argv) {
459
460  bool quit = false; // exit flag
461
462  info extent;  // extent that each node fetches
463
464  long zoom = 1;      // zoom out factor
465  long max_zoom = 7;  // max zoom out factor
466
467  int rank = 0;  // node rank
468  int size = 0;  // number of nodes
469  int frameRate = 5;
470
471  MPI_Datatype pinfo;  // info structure
472  MPI_Datatype ipinfo; // ip infor structure
473
474  // MPI Initialization
475  MPI_Init(&argc, &argv);
476  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
477  MPI_Comm_size(MPI_COMM_WORLD, &size);
478  MPI_Type_contiguous(7, MPI_LONG, &pinfo);
479  MPI_Type_contiguous(16, MPI_CHAR, &ipinfo);
480  MPI_Type_commit(&pinfo);
481  MPI_Type_commit(&ipinfo);
482
483  // Print some information about the program
484  printf("----------------------------------------------------------------\n");
485  printf("JuxtaView for SAGE - Node %d of %d\n", rank, size);
486  printf("9 September 2005\n");
487  printf("----------------------------------------------------------------\n");
488
489  // sync
490  MPI_Barrier(MPI_COMM_WORLD);
491
492  /* *********************************************************************** */
493  /* Begin - Master node                                                     */
494
495  if (rank == 0) {
496
497    /* Initialize QUANTA */
498    QUANTAinit();
499
500    /* Create a server for the UI */
501    JuxtaUIServer* server = new JuxtaUIServer();
502
503    /* Initialize server for UI */
504    if (!server -> Init(argv[4])) {
505      delete server;
506      printf("Can not create a UI server.\n");
507      return EXIT_FAILURE;
508    }
509
510    /* read viewports for each node */
511    viewport* viewports = read_config(argv[1]);
512    //cout << "********MASTER********** config " << argv[1] << endl;
513
514    /* check that viewports were read correctly */
515    if (viewports == NULL) {
516      printf("Can not read config file.\n");
517      return EXIT_FAILURE;
518    }
519
520    /* read data description file */
521    //description data = read_data("juxtadata.conf");
522    description data = read_data(argv[2]);
523    //cout << "********MASTER********** data " << argv[2]<< endl;
524
525    /* begin - read overview file */
526
527    //if the bitmap hasn't been read yet then read it!
528    //for now just read the whole tiff file
529    TIFF* tiffile = TIFFOpen(data.name, "r");
530
531    uint32 width = 1, height = 1;
532
533    if(tiffile)
534      {
535        //get the image width and height
536        TIFFGetField(tiffile, TIFFTAG_IMAGEWIDTH, &width);
537        TIFFGetField(tiffile, TIFFTAG_IMAGELENGTH, &height);
538      }
539
540    //get the pixels
541    int samplerate = data.samplerate;
542    int bmpW = width / samplerate;
543    int bmpH = height / samplerate;
544    if( bmpW == 0)
545      bmpW = 1;
546    if( bmpH == 0)
547      bmpH = 1;
548
549    unsigned char* bitmap = new unsigned char[bmpW * bmpH * 3];
550    fprintf(stderr,"Loading overview of size %d x %d\n",bmpW,bmpH);
551    memset(bitmap,0,bmpW * bmpH * 3);
552    if(tiffile)
553      {
554        char* scanline = (char*) _TIFFmalloc( TIFFScanlineSize(tiffile));
555
556        for( int row = 0; row < bmpH; row++)
557          {
558            TIFFReadScanline(tiffile,scanline,row * samplerate);
559            for( int i = 0; i < bmpW; i++)
560              {
561                memcpy(bitmap + (i * 3) + (row * 3 * bmpW),
562                       scanline + (samplerate * i * 3),
563                       3);
564              }
565          }
566
567        _TIFFfree(scanline);
568        TIFFClose(tiffile);
569      }
570
571    /* end - read overview file */
572
573    printf("Origin X: %ld\n", data.origin_x);
574    printf("Origin Y: %ld\n", data.origin_y);
575    printf("Image Width: %ld\n", data.image_width);
576    printf("Image Height: %ld\n", data.image_height);
577    printf("Start x: %ld\n", data.start_x);
578    printf("Start y: %ld\n", data.start_y);
579    printf("Pan amount: %ld\n", data.pan_amount);
580    printf("Fast pan amount: %d\n", data.fast_pan_amount);
581    printf("Fetch w: %ld\n", data.fetch_w);
582    printf("Fetch h: %ld\n", data.fetch_h);
583
584    /* extent to fetch */
585    long Xg = data.start_x;  // current x position in global image
586    long Yg = data.start_y;  // current y position in global image
587    long Wg = data.fetch_w;  // width of extent to fetch
588    long Hg = data.fetch_h;  // height of extent to fetch
589
590    for (int j = 0 ; j < size - 1 ; j++) {
591      MPI_Send(&(viewports[j].x_min), 1, MPI_FLOAT, j+1, 1, MPI_COMM_WORLD);
592    }
593    MPI_Barrier(MPI_COMM_WORLD);
594    for (int j = 0 ; j < size - 1 ; j++) {
595      MPI_Send(&(viewports[j].y_min), 1, MPI_FLOAT, j+1, 1, MPI_COMM_WORLD);
596    }
597    MPI_Barrier(MPI_COMM_WORLD);
598    for (int j = 0 ; j < size - 1 ; j++) {
599      MPI_Send(&(viewports[j].x_max), 1, MPI_FLOAT, j+1, 1, MPI_COMM_WORLD);
600    }
601    MPI_Barrier(MPI_COMM_WORLD);
602    for (int j = 0 ; j < size - 1 ; j++) {
603      MPI_Send(&(viewports[j].y_max), 1, MPI_FLOAT, j+1, 1, MPI_COMM_WORLD);
604    }
605    MPI_Barrier(MPI_COMM_WORLD);
606    for (int j = 0 ; j < size - 1 ; j++) {
607      MPI_Send(viewports[j].ip, 1, ipinfo, j+1, 1, MPI_COMM_WORLD);
608    }
609    MPI_Barrier(MPI_COMM_WORLD);
610
611    // insert code here to show first frame before GUI starts
612
613    // calculate and send extent for each node
614    for (int i = 0 ; i < size - 1 ; i++) {
615      extent.x = ((long)(Wg * viewports[i].x_min)) + Xg;
616      extent.y = ((long)(Hg * viewports[i].y_min)) + Yg;
617      extent.w = (long)(Wg * (viewports[i].x_max - viewports[i].x_min));
618      extent.h = (long)(Hg * (viewports[i].y_max - viewports[i].y_min));
619      extent.zoom = zoom;
620      extent.border = viewports[i].border;
621      MPI_Send(&extent, 1, pinfo, i+1, 1, MPI_COMM_WORLD);
622    }
623
624    // synchronize
625    MPI_Barrier(MPI_COMM_WORLD);
626
627
628    //cout << "Master entering loop" << endl;
629
630    /* begin - event loop */
631    while (!quit) {
632
633      // block until incoming message from UI
634      char* msg = server -> WaitForMessage();
635
636      //printf("Before: xg %ld, yg %ld, wg %ld, hg %ld\n", Xg, Yg, Wg, Hg);
637
638      // pan left
639      if (!strcmp(msg, JVPAN_LEFT)) {
640        if (Xg - data.pan_amount >= data.origin_x) {
641          Xg = Xg - data.pan_amount;
642        }
643        else {
644          Xg = data.origin_x;
645        }
646        extent.command = LEFT;
647      }
648
649      // pan right
650      else if (!strcmp(msg, JVPAN_RIGHT)) {
651        if (Xg + Wg + data.pan_amount <
652            data.origin_x + data.image_width) {
653          Xg = Xg + data.pan_amount;
654        }
655        else {
656          Xg = Xg + (data.origin_x + data.image_width) - (Xg + Wg) - 1;
657        }
658        extent.command = RIGHT;
659      }
660
661      // pan up
662      else if (!strcmp(msg, JVPAN_UP)) {
663        if (Yg - data.pan_amount >= data.origin_y) {
664          Yg = Yg - data.pan_amount;
665        }
666        else {
667          Yg = data.origin_y;
668        }
669        extent.command = UP;
670      }
671
672      // pan down
673      else if (!strcmp(msg, JVPAN_DOWN)) {
674        if (Yg + Hg + data.pan_amount <=
675            data.origin_y + data.image_height) {
676          Yg = Yg + data.pan_amount;
677        }
678        else {
679          Yg = Yg + (data.origin_y + data.image_height) - (Yg + Hg) - 1;
680        }
681        extent.command = DOWN;
682      }
683
684      // fast pan left
685      else if(!strcmp(msg, JVFAST_PAN_LEFT)) {
686        if (Xg - data.fast_pan_amount >= data.origin_x) {
687          Xg = Xg - data.fast_pan_amount;
688        }
689        else {
690          Xg = data.origin_x;
691        }
692        extent.command = FASTLEFT;
693      }
694
695      // fast pan right
696      else if(!strcmp(msg, JVFAST_PAN_RIGHT)) {
697        if (Xg + Wg + data.fast_pan_amount <
698            data.origin_x + data.image_width) {
699          Xg = Xg + data.fast_pan_amount;
700        }
701        else {
702          Xg = Xg + (data.origin_x + data.image_width) - (Xg + Wg) - 1;
703        }
704        extent.command = FASTRIGHT;
705      }
706
707      // fast pan up
708      else if(!strcmp(msg, JVFAST_PAN_UP)) {
709        if (Yg - data.fast_pan_amount >= data.origin_y) {
710          Yg = Yg - data.fast_pan_amount;
711        }
712        else {
713          Yg = data.origin_y;
714        }
715        extent.command = FASTUP;
716      }
717
718      // fast pan down
719      else if(!strcmp(msg, JVFAST_PAN_DOWN)) {
720        if (Yg + Hg + data.fast_pan_amount <=
721            data.origin_y + data.image_height) {
722          Yg = Yg + data.fast_pan_amount;
723        }
724        else {
725          Yg = Yg + (data.origin_y + data.image_height) - (Yg + Hg) -1;
726        }
727        extent.command = FASTDOWN;
728      }
729
730      // zoom out
731      else if(!strcmp(msg, JVZOOM_OUT)) {
732        if (zoom + 1 <= max_zoom) {
733
734          // calcualte new upper left corner and extents
735          long center_x = Xg + (Wg / 2);
736          long center_y = Yg + (Hg / 2);
737          long tXg = center_x - ((Wg + data.fetch_w) / 2);
738          long tYg = center_y - ((Hg + data.fetch_h) / 2);
739          long tHg = Hg + data.fetch_h;
740          long tWg = Wg + data.fetch_w;
741
742          // check that zoomed out image is within the image size
743          if (tWg <= data.image_width && tHg <= data.image_height) {
744
745            // new x position is too far left
746            if (tXg < data.origin_x) {
747              tXg = data.origin_x;
748            }
749
750            // new y position is too far up
751            if (tYg < data.origin_y) {
752              tYg = data.origin_y;
753            }
754
755            // new x extent is too far right
756            if (tXg + tWg >= data.origin_x + data.image_width) {
757              long delta_x = (tXg + tWg) - (data.origin_x + data.image_width);
758              tXg = tXg - delta_x - 1;
759            }
760
761            // new y extent is too far down
762            if (tYg + tHg >= data.origin_y + data.image_height) {
763              long delta_y = (tYg + tHg) - (data.origin_y + data.image_height);
764              tYg = tYg - delta_y - 1;
765            }
766
767            // update everthing
768            zoom++;
769            Xg = tXg;
770            Yg = tYg;
771            Hg = tHg;
772            Wg = tWg;
773
774          }
775
776        }
777        extent.command = ZOOMOUT;
778      }
779
780      // zoom in
781      else if(!strcmp(msg, JVZOOM_IN)) {
782        if (zoom - 1 >= 1) {
783          if ((Yg + Hg - data.fetch_h <= data.origin_y + data.image_height) &&
784              (Xg + Wg - data.fetch_w <= data.origin_x + data.image_width)) {
785            long center_x = Xg + (Wg / 2);
786            long center_y = Yg + (Hg / 2);
787            Xg = center_x - ((Wg - data.fetch_w) / 2);
788            Yg = center_y - ((Hg - data.fetch_h) / 2);
789            extent.command = ZOOMIN;
790            zoom--;
791            Hg -= data.fetch_h;
792            Wg -= data.fetch_w;
793          }
794        }
795        extent.command = ZOOMIN;
796      }
797
798      // free translation
799      else if (!strcmp(msg, JVTRANSLATE)) {
800
801        // normalized free translation coordinates
802        float nx = 0.0;
803        float ny = 0.0;
804
805        // get normalized free translation coordinates
806        server -> GetNormalizedFreeTranslation(&nx, &ny);
807
808        // convert normalized values to actual pixel coordinates
809        long tXg = (long) (nx * data.image_width);
810        long tYg = (long) (ny * data.image_height);
811
812        // set command
813        extent.command = FREETRANS;
814
815        // check left x
816        if (tXg < data.origin_x)
817          Xg = data.origin_x;
818        else
819          Xg = tXg;
820
821        // check top y
822        if (tYg < data.origin_y)
823          Yg = data.origin_y;
824        else
825          Yg = tYg;
826
827        // check right x
828        if (tXg + Wg >= data.origin_x + data.image_width)
829          Xg = Xg + (data.origin_x + data.image_width) - (Xg + Wg) - 1;
830        else
831          Xg = tXg;
832
833        // check bottom y
834        if (tYg + Hg >= data.origin_y + data.image_height)
835          Yg = Yg + (data.origin_y + data.image_height) - (Yg + Hg) - 1;
836        else
837          Yg = tYg;
838
839        //cout << "Freetrans tXg: " << tXg << " tYg: " << tYg << endl;
840        //cout << "Freetrans Xg: " << Xg << " Yg: " << Yg << endl;
841        //cout << "End of freetrans" << endl;
842      }
843
844      // send normalized extent of displayed area
845      else if (!strcmp(msg, JVEXTENTS)) {
846        float nx = (float) Xg / (float) data.image_width;
847        float ny = (float) Yg / (float) data.image_height;
848        float nw = (float) Wg / (float) data.image_width;
849        float nh = (float) Hg / (float) data.image_height;
850
851        //cout << "MASTER: normalized extents nx: " << nx
852        //     << " ny: " << ny << " nw: " << nw << " nh: " << nh << endl;
853        server -> SendNormalizedExtents(nx, ny, nw, nh);
854        extent.command = EXTENTS;
855        //cout << "End of extents" << endl;
856      }
857
858      else if (!strcmp(msg, JVOVERVIEW)) {
859        server -> SendOverview(bmpW, bmpH, bitmap);
860        extent.command = OVERVIEW;
861      }
862
863      // quit
864      else if(!strcmp(msg, JVQUIT)) {
865        quit = true;
866        extent.command = QUIT;
867      }
868
869      // resend
870      else if(!strcmp(msg, JVRESEND)) {
871        extent.command = RESEND;
872      }
873
874      //printf("After: xg %d, yg %d, wg %d, hg %d\n", Xg, Yg, Wg, Hg);
875
876      //fprintf(logfile,"Message Returned: %s\n",msg);
877
878      // calculate and send extent for each node
879      for (int i = 0 ; i < size - 1 ; i++) {
880        extent.x = ((long)(Wg * viewports[i].x_min)) + Xg;
881        extent.y = ((long)(Hg * viewports[i].y_min)) + Yg;
882        extent.w = (long)(Wg * (viewports[i].x_max - viewports[i].x_min));
883        extent.h = (long)(Hg * (viewports[i].y_max - viewports[i].y_min));
884        extent.zoom = zoom;
885        extent.border = viewports[i].border;
886        MPI_Send(&extent, 1, pinfo, i+1, 1, MPI_COMM_WORLD);
887      }
888
889      // synchronize
890      MPI_Barrier(MPI_COMM_WORLD);
891
892      // free memory used by message from UI
893      //cout << "Master deleting message - begin" << endl;
894      //delete [] msg;
895      //cout << "Master deleting message - end" << endl;
896
897    } /* end - event loop */
898
899    // free memory used by viewport list
900    free(viewports);
901
902    // free memory used by overview
903    free(bitmap);
904
905  }
906
907  /* End - Master node                                                       */
908  /* *************************************************************************/
909
910  /* *********************************************************************** */
911  /* Begin - Slave node                                                      */
912
913  else {
914
915    // first time slave is run
916    bool virgin = true;
917
918    // MPI status variable
919    MPI_Status status;
920
921    // create GlobalCoordinatesToFileMapper instance
922    GlobalCoordinatesToFileMapper gmapper;
923
924    // initialize GlobalCoordinatesToFileMapper instance
925    // TODO: change this to command line argument!!
926    //gmapper.Initialize("juxtalayout.conf");
927    gmapper.Initialize(argv[3]);
928    //cout << "********SLAVE********** layout " << endl;
929
930    // big image buffer
931    unsigned char* pixelarray = NULL;
932
933    // zoom adjusted image buffer
934    unsigned char* buffer = NULL;
935
936    // viewport information
937    viewport view;
938
939    // get viewport information
940    MPI_Recv(&(view.x_min), 1, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, &status);
941    MPI_Barrier(MPI_COMM_WORLD);
942    MPI_Recv(&(view.y_min), 1, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, &status);
943    MPI_Barrier(MPI_COMM_WORLD);
944    MPI_Recv(&(view.x_max), 1, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, &status);
945    MPI_Barrier(MPI_COMM_WORLD);
946    MPI_Recv(&(view.y_max), 1, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, &status);
947    MPI_Barrier(MPI_COMM_WORLD);
948    MPI_Recv(view.ip, 1, ipinfo, 0, 1, MPI_COMM_WORLD, &status);
949    MPI_Barrier(MPI_COMM_WORLD);
950
951    /*
952    cout << "Rank: " << rank << " x_min: " << view.x_min << endl;
953    cout << "Rank: " << rank << " y_min: " << view.y_min << endl;
954    cout << "Rank: " << rank << " x_max: " << view.x_max << endl;
955    cout << "Rank: " << rank << " y_max: " << view.y_max << endl;
956    */
957
958
959    /* begin - event loop */
960    while(!quit) {
961
962      //fprintf(stderr, "Proc %d> Receiving\n", rank);
963
964      // receive command from master
965      MPI_Recv(&extent, 1, pinfo, 0, 1, MPI_COMM_WORLD, &status);
966      //cout << "Rank: " << rank << " V1" << endl;
967      if (virgin) {
968
969        // initialize SAGE
970
971        sailConfig scfg;
972        scfg.init("JuxtaView.conf");
973        scfg.setAppName("JuxtaView");
974        if (argc > 6)
975                scfg.nwID = atoi(argv[6]);
976        scfg.rank = rank - 1;
977
978        scfg.resX = (extent.w / extent.zoom);
979        scfg.resY = (extent.h / extent.zoom);
980
981        sageRect renderImageMap;
982        renderImageMap.left = view.x_min;
983        renderImageMap.right = view.x_max;
984        renderImageMap.bottom = 1.0 - view.y_max;
985        renderImageMap.top = 1.0 - view.y_min;
986
987        scfg.imageMap = renderImageMap;
988        scfg.pixFmt = PIXFMT_888;
989        //scfg.rowOrd = TOP_TO_BOTTOM;
990        scfg.rowOrd = TOP_TO_BOTTOM;
991
992        if (scfg.rank == 0)
993                scfg.master = true;
994        else
995                scfg.master = false;
996
997        sageInf.init(scfg);
998
999        if (argc > 7)
1000                frameRate = atoi(argv[7]);
1001
1002        //cout << "Rank: " << rank << " V1.1" << endl;
1003
1004        // create zoom adjusted image buffer
1005        if (buffer)
1006                delete [] buffer;
1007
1008        buffer = (unsigned char*)sageInf.getBuffer();
1009
1010        //cout << "Rank: " << rank << " V1.2" << endl;
1011
1012        // no longer a virgin
1013        virgin = false;
1014      }
1015
1016      //cout << "Rank: " << rank << " V1.3" << endl;
1017
1018      // quit
1019      if (extent.command == QUIT) {
1020
1021        // set quit flag
1022        quit = true;
1023
1024        // synchronize
1025        MPI_Barrier(MPI_COMM_WORLD);
1026
1027      }
1028
1029      // resend
1030      else if (extent.command == RESEND) {
1031        if (!virgin) {
1032          // synchronize
1033          MPI_Barrier(MPI_COMM_WORLD);
1034                         /*
1035                         useconds_t interval = (useconds_t)floor(1.0/frameRate*1000000.0);
1036                         usleep(interval);
1037          // swap buffer
1038          sageInf.swapBuffer();
1039                         buffer = (unsigned char *)sageInf.getBuffer();
1040                         */
1041        }
1042      }
1043
1044      // get and display data
1045      else {
1046        //cout << "Rank: " << rank << " V2" << endl;
1047        // print the current query for this node
1048        //cout << "QueryExtent at node " << rank << " " << extent.x << " "
1049        //     << extent.y << " " << extent.w << " " << extent.h << endl;
1050
1051        // create big image buffer
1052        if (!pixelarray)
1053          pixelarray = new unsigned char[extent.w * extent.h * 3];
1054
1055        // set extent of data to fetch
1056        gmapper.SetQueryExtent(extent.x, extent.y, extent.w, extent.h);
1057
1058        // make query - this actually makes the mapper calculate
1059        // all the files this program should load
1060        gmapper.Query();
1061
1062        // print the state of the mapper
1063        //gmapper.PrintSelf(cout);
1064
1065        // number of columns and rows in the query result
1066        long columnResult = 0;
1067        long rowResult = 0;
1068
1069        // get the array of FileInfo and the number of rows and columns of
1070        // the 2D array of FileInfo
1071        FileInfo* files =
1072          gmapper.GetQueryFileInfoArray(&columnResult, &rowResult);
1073
1074        // print the number of columns and rows in the query result
1075        //cout << "FileInfoArrayDimensions: " << columnResult << " "
1076        //     << rowResult << endl;
1077
1078        // NOTE: THIS DOES NOT WORK. IT'S A MESS!!!
1079        // ANOTHER NOTE: IT WORKS NOW, BUT VERY, VERY SLOWLY
1080        // ////////////////////////////////////////////////////////////////////
1081        // Begin - read from files
1082
1083        long localx = 0;
1084        long localy = 0;
1085        long localw = 0;
1086        long localh = 0;
1087        long globalw = extent.w;
1088        long globalh = extent.h;
1089
1090        //cout << "Extent.w: " << extent.w << " Extent.h: "
1091        //     << extent.h << endl;
1092        //cout << "Rank: " << rank << " V3" << endl;
1093
1094        int array_index = 0;
1095        int array_max = columnResult * rowResult;
1096
1097        //cout << "Rank: " << rank << " V4" << endl;
1098
1099        memset(pixelarray, 0, globalw * globalh * 3);
1100
1101        //cout << "Rank: " << rank << " V5" << endl;
1102
1103        for(long c = 0; array_index < array_max && c < globalw; ){
1104          for(long r = 0; array_index < array_max && r < globalh; ){
1105
1106            TIFF* tiffile = NULL;
1107            tiffile = TIFFOpen(files[array_index].GetFileName(), "r");
1108
1109            // if the tif exists
1110            if (tiffile != NULL) {
1111
1112              //get the scanlines needed
1113              unsigned char *scanline =
1114                (unsigned char *) _TIFFmalloc(TIFFScanlineSize(tiffile));
1115
1116              files[array_index].GetExtent(&localx, &localy, &localw, &localh);
1117              //cout << "Rank: " << rank
1118              //           << "file: " << files[array_index].GetFileName()
1119              //           << "localx: " << localx
1120              //           << "localy: " << localy
1121              //           << "localw: " << localw
1122              //           << "localh: " << localh
1123              //           << endl;
1124
1125              for (int l = 0,  k = localy ; k < localy + (localh) ; k++, l++)
1126                {
1127                  //cout << "Rank: " << rank << " row: " << k << endl;
1128                  TIFFReadScanline(tiffile,scanline,k);
1129                  //for(int j = 0; j < localw; j++){
1130                  memcpy(&(pixelarray[ (r + l) * globalw *3 + c * 3]),
1131                         &(scanline[localx * 3]),localw * 3);
1132                }
1133
1134              _TIFFfree(scanline);
1135              TIFFClose(tiffile);
1136
1137            }
1138
1139            array_index++;
1140            r += localh;
1141          }
1142          c += localw;
1143        }
1144
1145        //cout << "Rank: " << rank << " V6" << endl;
1146
1147        // End - read from files
1148        // ////////////////////////////////////////////////////////////////////
1149
1150        // clear the zoom adjusted image buffer
1151        memset(buffer,
1152               0,
1153               (extent.w / extent.zoom) * (extent.h / extent.zoom) * 3);
1154
1155        // adjust for zoom by skipping pixels
1156        // NOTE: Zooming is from the upper left, not the center, I know
1157        // that's bad, so some day I'll fix it.
1158        for (long r = 0, rz = 0 ; r < extent.h ; r += extent.zoom, rz++) {
1159          for (long c = 0, cz = 0 ; c < extent.w ; c += extent.zoom, cz++) {
1160            buffer[rz * 3 * (extent.w / extent.zoom) + (cz * 3)] =
1161              pixelarray[r * 3 * extent.w + (c * 3)];
1162            buffer[rz * 3 * (extent.w / extent.zoom) + (cz * 3) + 1] =
1163              pixelarray[r * 3 * extent.w + (c * 3) + 1];
1164            buffer[rz * 3 * (extent.w / extent.zoom) + (cz * 3) + 2] =
1165              pixelarray[r * 3 * extent.w + (c * 3) + 2];
1166          }
1167        }
1168
1169        // delete big image buffer
1170        //cout << "slave deleting pixelarray - begin" << endl;
1171        delete [] pixelarray;
1172        //cout << "slave deleting pixelarray - end" << endl;
1173        pixelarray = NULL;
1174
1175        // add borders
1176        add_border(buffer, extent);
1177
1178        // synchronize
1179        MPI_Barrier(MPI_COMM_WORLD);
1180
1181        // swap buffer
1182        sageInf.swapBuffer();
1183        buffer = (unsigned char *)sageInf.getBuffer();
1184
1185      }
1186
1187    } /* end - event loop */
1188
1189    if (rank == 1)
1190      sageInf.shutdown();
1191
1192    // delete zoom adjusted image buffer
1193    delete [] buffer;
1194    buffer = NULL;
1195
1196  }
1197
1198  /* End - Slave node                                                        */
1199  /* *************************************************************************/
1200
1201  // finalize
1202  MPI_Finalize();
1203
1204  // exit
1205  return EXIT_SUCCESS;
1206
1207} /* end - main */
Note: See TracBrowser for help on using the repository browser.