home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / saoimage / sao1_07.tar / mgfydraw.c < prev    next >
C/C++ Source or Header  |  1991-06-21  |  10KB  |  348 lines

  1. #ifndef lint
  2. static char SccsId[] = "%W%  %G%";
  3. #endif
  4.  
  5. /* Module:    mgfydraw.c (Magnify Draw)
  6.  * Purpose:    Quickly draw the zoomed piece of image in the zoom box
  7.  * Subroutine:    draw_magnifier()            returns: void
  8.  * Copyright:    1988 Smithsonian Astrophysical Observatory
  9.  *        You may do anything you like with this file except remove
  10.  *        this copyright.  The Smithsonian Astrophysical Observatory
  11.  *        makes no representations about the suitability of this
  12.  *        software for any purpose.  It is provided "as is" without
  13.  *        express or implied warranty.
  14.  * Modified:    {0} Michael VanHilst    initial version          3 December 1988
  15.  *        {1} MVH improved limit checking, added comments       1 Jan 1991
  16.  *        {2} MVH same fix as 1, for bitmap display      21 Jun 1991
  17.  *        {n} <who> -- <does what> -- <when>
  18.  */
  19.  
  20. #include <X11/Xlib.h>        /* X window stuff */
  21. #include <X11/Xutil.h>        /* X window manager stuff */
  22. #include "hfiles/color.h"    /* define GCspec */
  23. #include "hfiles/magnify.h"    /* magnifier quick access structure */
  24.  
  25. struct magRec magset;
  26.  
  27.  
  28. #ifdef ANSIC
  29. /*  Exported declarations must be centralized before ANSI C can be used  */
  30.  
  31. void        draw_magnifier(    double bufx, double bufy );
  32.  
  33. #else
  34.  
  35. void draw_magnifier();
  36. GC set_gc(), set_gc_with_background();
  37. void blank_scope(), mark_Zmagnifier(), mark_XYmagnifier();
  38.  
  39. #endif
  40.  
  41.  
  42. /* Subroutine:    draw_magnifier
  43.  * Purpose:    Draw image in zoombox, quickly (use magset parameters)
  44.  */
  45. #ifdef ANSIC
  46. void draw_magnifier( double bufx, double bufy )
  47. #else
  48. void draw_magnifier ( bufx, bufy )
  49.      double bufx, bufy;
  50. #endif
  51. {
  52.   int magXwdth, magYhght;    /* Dimensions of destination area drawn */
  53.   int magX1, magY1;        /* Upper left coords of destination drawn */
  54.   int bufX1, bufY1;        /* Upper left coords of source area */
  55.   int Xrep1, Yrep1;        /* Repetitions of first pixel (on UL edge) */
  56.   int margin;
  57.   int imgjump;            /* Memory offset from end to start of next */
  58.   /* Variables used in display loop */
  59.   int rep;
  60.   unsigned char *lookup;
  61.   unsigned char *magline;
  62.   int yline;
  63.   int yrepend;
  64.  
  65.   /* Check for special handling */
  66.   margin = 0;
  67.   /* Check for being completely beyoind buffer and set initial dimensions */
  68.   if( bufx < magset.buf.X1lim ) {
  69.     blank_scope();
  70.     return;
  71.   }
  72.   if( bufx <= magset.buf.X2bdr )
  73.     magXwdth = magset.win.width;
  74.   else {
  75.     if( bufx > magset.buf.X2lim ) {
  76.       blank_scope();
  77.       return;
  78.     }
  79.     /* Note rounding for a negative number */
  80.     magXwdth = magset.win.width +
  81.       (int)(((magset.buf.X2bdr - bufx) * (float)magset.zoom_rep) - 0.5);
  82.     margin = 1;
  83.   }
  84.   if( bufy < magset.buf.Y1lim ) {
  85.     blank_scope();
  86.     return;
  87.   }
  88.   if( bufy <= magset.buf.Y2bdr )
  89.     magYhght = magset.win.height;
  90.   else {
  91.     if( bufy > magset.buf.Y2lim ) {
  92.       blank_scope();
  93.       return;
  94.     }
  95.     /* Note rounding for a negative number */
  96.     magYhght = magset.win.height +
  97.       (int)(((magset.buf.Y2bdr - bufy) * (float)magset.zoom_rep) - 0.5);
  98.     margin = 1;
  99.   }
  100.   /* Convert to buffer coordinates, and calculate partial offsets */
  101.   bufx -= magset.buf.Xcen;
  102.   if( bufx >= 0.0 ) {
  103.     int xrepoff;
  104.  
  105.     /* Left edge of magnifier within buffer */
  106.     magX1 = 0;
  107.     bufX1 = (int)bufx;
  108.     /* Number of replications of first pixel is less fractional overlap */
  109.     xrepoff = (int)((bufx - (float)bufX1) * magset.zoom_rep);
  110.     if( xrepoff < magset.zoom_rep ) {
  111.       Xrep1 = magset.zoom_rep - xrepoff;
  112.       imgjump = magset.buf.width -
  113.     (1 + ((magXwdth + xrepoff - 1) / magset.zoom_rep));
  114.     } else {
  115.       /* If rounds to next edge, skip first pixel */
  116.       bufX1 += 1;
  117.       Xrep1 = magset.zoom_rep;
  118.       imgjump = magset.buf.width - (1 + ((magXwdth - 1) / magset.zoom_rep));
  119.     }
  120.   } else {
  121.     /* Left edge of magnifier beyond buffer */
  122.     magX1 = -(int)(0.5 + (bufx * magset.zoom_rep));
  123.     magXwdth -= magX1;
  124.     bufX1 = 0;
  125.     Xrep1 = magset.zoom_rep;
  126.     imgjump = magset.buf.width - (1 + ((magXwdth - 1) / magset.zoom_rep));
  127.     margin = 1;
  128.   }
  129.   bufy -= magset.buf.Ycen;
  130.   if( bufy >= 0.0 ) {
  131.     /* Top edge of magnifier within buffer */
  132.     magY1 = 0;
  133.     bufY1 = (int)bufy;
  134.     /* Number of replications of first pixel is less fractional overlap */
  135.     Yrep1 = magset.zoom_rep -
  136.       (int)((bufy - (float)bufY1) * (float)magset.zoom_rep);
  137.     /* If rounds to next edge, skip first pixel */
  138.     if( Yrep1 <= 0 ) {
  139.       bufY1 += 1;
  140.       Yrep1 = magset.zoom_rep;
  141.     }
  142.   } else {
  143.     /* Top edge of magnifier beyond buffer */
  144.     magY1 = -(int)(0.5 + (bufy * (float)magset.zoom_rep));
  145.     magYhght -= magY1;
  146.     bufY1 = 0;
  147.     Yrep1 = magset.zoom_rep;
  148.     margin = 1;
  149.   }
  150.   if( !magset.halftone ) {
  151.     /* Variables used only in color loop */
  152.     int magjump;
  153.     register unsigned char *magbuf;
  154.     if( margin == 1 ) {
  155.       /* Image doesn't cover entire field, blank field, compute offset start */
  156.       bzero(magset.data, magset.data_size);
  157.       magbuf = (unsigned char *)magset.data + magX1 +
  158.     (magset.win.width * magY1);
  159.     } else {
  160.       /* Simple start at top left corner of magnibox buffer */
  161.       magbuf = (unsigned char *)magset.data;
  162.     }
  163.     {
  164.       register unsigned char *xrowend;
  165.       register unsigned char *xrepend;
  166.       register short *imgbuf;
  167.  
  168.       /* Compute start in data buffer, get scaling lookup table */
  169.       imgbuf = magset.buf.shortbuf + bufX1 + (bufY1 * magset.buf.width);
  170.       lookup = magset.lookup;
  171.       magjump = magset.win.width - magXwdth;
  172.       rep = magset.zoom_rep;
  173.       yline = 0;
  174.       yrepend = Yrep1;
  175.       while( yline < magYhght ) {
  176.     magline = magbuf;
  177.     /* Create row of magnibuf from image buffer data */
  178.     xrowend = magbuf + magXwdth;
  179.     xrepend = magbuf + Xrep1;
  180.     while( magbuf < xrowend ) {
  181.       unsigned char val;
  182.  
  183.       val = lookup[*imgbuf++];
  184.       /* Make sure repetition does not run beyond end */
  185.       if( xrepend > xrowend )
  186.         xrepend = xrowend;
  187.       while( magbuf < xrepend )
  188.         *magbuf++ = val;
  189.       xrepend += rep;
  190.     }
  191.     magbuf += magjump;
  192.     imgbuf += imgjump;
  193.     /* Make sure repetition does not run beyond end */
  194.     if( yrepend > magYhght )
  195.       yrepend = magYhght;
  196.     /* Copy original row for rep'd lines (magnification in Y direction) */
  197.     while( ++yline < yrepend ) {
  198.       register unsigned char *copy;
  199.  
  200.       copy = magline;
  201.       while( copy < xrowend )
  202.         *magbuf++ = *copy++;
  203.       magbuf += magjump;
  204.     }
  205.     yrepend += rep;
  206.       }
  207.     }
  208.     {
  209.       GC gc;
  210.       /* Install the sighting mark */
  211.       mark_Zmagnifier();
  212.       gc = set_gc(magset.gcset_disp);
  213.       XPutImage(magset.win.display, magset.win.ID, gc, magset.image,
  214.         0, 0, magset.win.x, magset.win.y,
  215.         magset.win.width, magset.win.height);
  216.     }
  217.   } else {
  218.     /* Variables used only in bitmap loop */
  219.     unsigned char *bitmap_row;
  220.     short *matrix_row;
  221.     int first_bit;
  222.     unsigned char *valbuf;
  223.     unsigned char linebuf[1024];
  224.  
  225.     /* Blank field */
  226.     bzero((char *)magset.data, magset.bitmap_size);
  227.     if( margin == 1 ) {
  228.       /* Image doesn't cover entire field - compute offset start  */
  229.       bitmap_row = (unsigned char *)
  230.     magset.data + (magX1 / 8) + (magset.bytes_per_line * magY1);
  231.       first_bit = magX1 & 7;
  232.     } else {
  233.       /* Simple start at top left corner of magnibox buffer */
  234.       bitmap_row = (unsigned char *)magset.data;
  235.       first_bit = 0;
  236.     }
  237.     {
  238.       register unsigned char *bitmap_byte_or_xrepend;
  239.       register unsigned char *xrowend;
  240.       register short *imgbuf;
  241.  
  242.       /* Compute start in data buffer, get scaling lookup table */
  243.       imgbuf = magset.buf.shortbuf + bufX1 + (bufY1 * magset.buf.width);
  244.       lookup = magset.lookup;
  245.       rep = magset.zoom_rep;
  246.       matrix_row = magset.matrix;
  247.       yline = 0;
  248.       xrowend = linebuf + magXwdth;
  249.       yrepend = Yrep1;
  250.       while( yline < magYhght ) {
  251.     /* Load scaled image data into temporary value buffer */
  252.     valbuf = linebuf;
  253.     bitmap_byte_or_xrepend = valbuf + Xrep1;
  254.     while( valbuf < xrowend ) {
  255.       unsigned char val;
  256.  
  257.       val = lookup[*imgbuf++];
  258.       if( bitmap_byte_or_xrepend > xrowend )
  259.         bitmap_byte_or_xrepend = xrowend;
  260.       while( valbuf < bitmap_byte_or_xrepend )
  261.         *valbuf++ = val;
  262.       bitmap_byte_or_xrepend += rep;
  263.     }
  264.     imgbuf += imgjump;
  265.     /* Copy data line row for rep'd lines, using dither mask */
  266.     bitmap_byte_or_xrepend = bitmap_row;
  267.     if( magset.inverse ) {
  268.       if( yrepend > magYhght )
  269.         yrepend = magYhght;
  270.       while( yline < yrepend ) {
  271.         register short *matrix;
  272.         register int bitmap_bit;
  273.  
  274.         /* Count lines when actually written */
  275.         yline++;
  276.         /* Set markers for start of a line */
  277.         bitmap_bit = first_bit;
  278.         valbuf = linebuf;
  279.         /* Point mask at start of dither mtrx row (each row is 16 wide) */
  280.         matrix = matrix_row;
  281.         while( valbuf < xrowend ) {
  282.           /* Set bit by comparing val to matrix entry */
  283.           if( *valbuf++ <= matrix[bitmap_bit] ) 
  284.         *bitmap_byte_or_xrepend |= 1 << bitmap_bit;
  285.           /* Check for next bitmap word */
  286.           if( ++bitmap_bit >= 8 ) {
  287.         bitmap_bit = 0;
  288.         ++bitmap_byte_or_xrepend;
  289.         if( matrix == matrix_row )
  290.           matrix += 8;
  291.         else
  292.           matrix = matrix_row;
  293.           }
  294.         }
  295.         if( (matrix_row += 16) >= magset.matrix_end )
  296.           matrix_row = magset.matrix;
  297.         bitmap_byte_or_xrepend = (bitmap_row += magset.bytes_per_line);
  298.       }
  299.       yrepend += rep;
  300.     } else {
  301.       if( yrepend > magYhght )
  302.         yrepend = magYhght;
  303.       while( yline < yrepend ) {
  304.         register short *matrix;
  305.         register int bitmap_bit;
  306.  
  307.         /* Count lines when actually written */
  308.         yline++;
  309.         /* Set markers for start of a line */
  310.         bitmap_bit = first_bit;
  311.         valbuf = linebuf;
  312.         /* Point mask at start of dither mtrx row (each row is 16 wide) */
  313.         matrix = matrix_row;
  314.         while( valbuf < xrowend ) {
  315.           /* Set bit by comparing val to matrix entry */
  316.           if( *valbuf++ > matrix[bitmap_bit] ) 
  317.         *bitmap_byte_or_xrepend |= 1 << bitmap_bit;
  318.           /* Check for next bitmap word */
  319.           if( ++bitmap_bit >= 8 ) {
  320.         bitmap_bit = 0;
  321.         ++bitmap_byte_or_xrepend;
  322.         if( matrix == matrix_row )
  323.           matrix += 8;
  324.         else
  325.           matrix = matrix_row;
  326.           }
  327.         }
  328.         if( (matrix_row += 16) >= magset.matrix_end )
  329.           matrix_row = magset.matrix;
  330.         bitmap_byte_or_xrepend = (bitmap_row += magset.bytes_per_line);
  331.       }
  332.       yrepend += rep;
  333.     }
  334.       }
  335.     }
  336.     {
  337.       GC gc;
  338.       /* Install the sighting mark */
  339.       mark_XYmagnifier();
  340.       gc = set_gc_with_background(magset.gcset_disp,
  341.                   magset.gcset_disp->background);
  342.       XPutImage(magset.win.display, magset.win.ID, gc, magset.image,
  343.         0, 0, magset.win.x, magset.win.y,
  344.         magset.win.width, magset.win.height);
  345.     }
  346.   }
  347. }
  348.