home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.3 Development Libraries / SGI IRIX 6.3 Development Libraries.iso / dist6.3 / gl_dev.idb / usr / share / src / OpenGL / teach / pixel / convolve.c.z / convolve.c
Encoding:
C/C++ Source or Header  |  1996-12-06  |  47.1 KB  |  1,827 lines

  1. #include <GL/glx.h>
  2. #include <GL/gl.h>
  3.  
  4. #include <gl/image.h>
  5.  
  6. #include <stdio.h>
  7.  
  8. #include <Xm/MainW.h>
  9. #include <Xm/Form.h>
  10. #include <Xm/Frame.h>
  11. #include <Xm/Label.h>
  12. #include <Xm/ToggleB.h>
  13. #include <Xm/PushB.h>
  14. #include <Xm/RowColumn.h>
  15. #include <Xm/Scale.h>
  16. #include <Xm/FileSB.h>
  17. #include <Xm/SelectioB.h>
  18. #include <Xm/MessageB.h>
  19.  
  20. #include <GL/GLwMDrawA.h>
  21.  
  22.  
  23. #include <math.h>
  24.  
  25. /* size of squares in test image */
  26. #define GRID 16
  27.  
  28. /* To compile: cc -o convolve convolve.c -lGL -lX11 -limage */
  29.  
  30. /* Motif Stuff */
  31.  
  32. static String fallbackResources[] = {
  33.     "*sgiMode: true",
  34.     "*useSchemes: all",
  35.     "*title: Convolution Demo Program",
  36.     "*glxarea*width: 256",
  37.     "*glxarea*height: 256",
  38.     NULL
  39. };
  40.  
  41. XtWorkProcId workId = 0;
  42. Widget       toplevel, mainw, frame, glxarea, form;
  43. Widget       control, fwidth, fheight;
  44. Widget       actions, load, readit, copy, draw, makeconv2d, makesep2d, texmap;
  45. Widget       makeconv1d;
  46. Widget       enables, enable1d, enable2d, enableSep2d;
  47. Widget       enabletex1d, enabletex2d;
  48. Widget       filter_format, filter_type, filter_contents, filters;
  49. Widget       image_format, image_type, image_contents;
  50. Widget       pzoom, xzoom, yzoom;
  51. Widget       getconv1dfilter, getconv2dfilter, getsepfilter;
  52. Widget       copyfilter1d, copyfilter2d;
  53. Widget       newlist, endlist, calllist;
  54. Arg          args[1];
  55.  
  56.  
  57. /*
  58. ** Generate a pop-up if an OpenGL error is detected. Keep popping up until
  59. ** all errors are shown.
  60. */
  61. void check_error(char *string)
  62. {
  63.     Widget glerror;
  64.     char message_string[1000];
  65.     XmString error_message;
  66.     GLenum error;
  67.     while((error = glGetError()) != GL_NO_ERROR) {
  68.     glerror = XmCreateErrorDialog(toplevel, "gl Error", NULL, 0);
  69.     sprintf(message_string, "%s: %s", 
  70.         string,
  71.         (char *)gluErrorString(error)); 
  72.     error_message = XmStringCreateLocalized(message_string);
  73.     XtVaSetValues(glerror, XmNmessageString, error_message, NULL);
  74.     XtManageChild(glerror);
  75.     XmStringFree(error_message);
  76.     }    
  77. }
  78.  
  79. /*
  80. ** The following two structures are used for bookkeeping details about
  81. ** the current image and the current filter.
  82. ** The create function is called to create or resize a filter or image.
  83. ** the function is called with a pointer to the appropriate structure,
  84. ** with the desired information filled in. If the creation function can't
  85. ** meet all the criteria described in the data, it changes the value to
  86. ** on it can meet. 
  87. **
  88. ** For example, if a filter of a certain size is desired, but the filter
  89. ** is defined to be a fixed size, the width and height information are
  90. ** changed to match the fixed size filter created. The calling routine
  91. ** must check for changed values.
  92. */
  93.  
  94.  
  95. /*
  96. ** Current filter
  97. */
  98.  
  99. typedef enum {BOX, SOBEL, LAPLACE} FilterContents;
  100.  
  101. typedef struct filter_info {
  102.     /* used as arguments to OpenGL calls */
  103.     GLsizei width;
  104.     GLsizei height;
  105.     GLenum internalformat;
  106.     GLenum format;
  107.     GLenum type;
  108.     /* Destination format and type for glGet*Filter() calls */
  109.     GLenum get_target;
  110.     GLenum get_format;
  111.     GLenum get_type;
  112.     /* Internal filter information */
  113.     void (*create)(struct filter_info *filt);
  114.     FilterContents contents;
  115.     unsigned char *filter;
  116.     unsigned char *row; /* if filter is separable */
  117.     unsigned char *col; /* if filter is separable */
  118. } Filter;
  119.  
  120.  
  121. /*
  122. ** Current Image
  123. */
  124.  
  125. typedef enum {SQUARES, CHECKERBOARD, FILES} ImageContents;
  126.  
  127. typedef struct image_info {
  128.     /* used as arguments to OpenGL calls */
  129.     GLenum format;
  130.     GLenum type;
  131.     GLint x;
  132.     GLint y;
  133.     GLsizei width;
  134.     GLsizei height;
  135.     GLfloat rasterposx;
  136.     GLfloat rasterposy;
  137.     /* Internal image information */
  138.     void (*create)(struct image_info *image);
  139.     char filename[100]; /* filename of file read to make image */
  140.     ImageContents contents;
  141.     unsigned int wid; /* actual dimensions and size of filter */
  142.     unsigned int ht;
  143.     unsigned char *image;
  144. } Image;
  145.  
  146.  
  147. /*
  148. ** Global filter and image
  149. */
  150.  
  151. Image image;
  152. Filter filter;
  153.  
  154.  
  155.  
  156. int format_size(GLenum format)
  157. {
  158.     switch(format) {
  159.     case GL_RGB:
  160.     return 3;
  161.     case GL_LUMINANCE_ALPHA:
  162.         return 2;
  163.     case GL_RGBA:
  164.     case GL_ABGR_EXT:
  165.         return 4;
  166.     default:
  167.         return 1;
  168.     }
  169. }
  170.  
  171. int type_size(GLenum type)
  172. {
  173.    switch(type) {
  174.       case GL_UNSIGNED_SHORT:
  175.       case GL_SHORT:
  176.         return 2;
  177.       case GL_UNSIGNED_BYTE:
  178.       case GL_BYTE:
  179.         return 1;
  180.       case GL_INT:
  181.       case GL_UNSIGNED_INT:
  182.       case GL_FLOAT:
  183.       default:
  184.         return 4;
  185.     }
  186. }
  187.  
  188.  
  189. /*
  190. ** Convert an element from a float to the destination type
  191. */
  192. void write_type(float *source, unsigned char *dest, GLenum type)
  193. {
  194.     switch(type) {
  195.     case GL_UNSIGNED_BYTE:
  196.     *(GLubyte *)dest = (GLubyte)(*source * 255.);
  197.     break;
  198.     case GL_BYTE:
  199.     *(GLbyte *)dest = (GLbyte)(*source * 128.);
  200.     break;
  201.     case GL_UNSIGNED_SHORT:
  202.     *(GLushort *)dest = (GLushort)(*source * 65535.);
  203.     break;
  204.     case GL_SHORT:
  205.     *(GLshort *)dest = (GLshort)(*source * 32767.);
  206.     break;
  207.     case GL_UNSIGNED_INT:
  208.     *(GLuint *)dest = (GLuint)(*source * 4292965000);
  209.     break;
  210.     case GL_INT:
  211.     *(GLint *)dest = (GLint)(*source * 2147482000);
  212.     break;
  213.     case GL_FLOAT:
  214.     *(GLfloat *)dest = *source;
  215.     break;
  216.     default:
  217.     fprintf(stderr, "write_type: error, invalid type: %d\n", (int)type);
  218.     break;
  219.     }
  220. }
  221.  
  222. /*
  223. ** Copy an element from an array of float RGBA elements in the proper
  224. ** format and type of the destination void * array
  225. */
  226. void write_element(float *source, unsigned char **dest, 
  227.            GLenum format, GLenum type)
  228. {
  229.  
  230.     float *src = source;
  231.     float tmp; /* for luminance, luminance_alpha, intensity */
  232.  
  233.     switch(format) {
  234.     case GL_RGBA:
  235.     write_type(src, *dest, type);
  236.     src++;
  237.     *dest += type_size(type);
  238.     write_type(src, *dest, type);
  239.     src++;
  240.     *dest += type_size(type);
  241.     write_type(src, *dest, type);
  242.     src++;
  243.     *dest += type_size(type);
  244.     write_type(src, *dest, type);
  245.     src++;
  246.     *dest += type_size(type);
  247.     break;
  248.     case GL_ABGR_EXT:
  249.     write_type(src + 3, *dest, type);
  250.     *dest += type_size(type);
  251.     write_type(src + 2, *dest, type);
  252.     *dest += type_size(type);
  253.     write_type(src + 1, *dest, type);
  254.     *dest += type_size(type);
  255.     write_type(src, *dest, type);
  256.     *dest += type_size(type);
  257.     break;
  258.     case GL_RGB:
  259.     write_type(src, *dest, type);
  260.     src++;
  261.     *dest += type_size(type);
  262.     write_type(src, *dest, type);
  263.     src++;
  264.     *dest += type_size(type);
  265.     write_type(src, *dest, type);
  266.     src++;
  267.     *dest += type_size(type);
  268.     break;
  269.     case GL_LUMINANCE_ALPHA:
  270.     tmp = src[0] + src[1] + src[2];
  271.     write_type(&tmp, *dest, type);
  272.     *dest += type_size(type);
  273.     write_type(src + 3, *dest, type);
  274.     *dest += type_size(type);
  275.     break;
  276.     case GL_LUMINANCE:
  277.     tmp = src[0] + src[1] + src[2];
  278.     if(tmp > 1.0) tmp = 1.0;
  279.     write_type(&tmp, *dest, type);
  280.     *dest += type_size(type);
  281.     break;
  282.     case GL_INTENSITY_EXT:
  283.     tmp = src[0] + src[1] + src[2] + src[3];
  284.     if(tmp > 1.0) tmp = 1.0;
  285.     write_type(&tmp, *dest, type);
  286.     *dest += type_size(type);
  287.     break;
  288.     }
  289. }
  290.  
  291.  
  292. void create_sobel(Filter *filter_info)
  293. {
  294.     static float sbl[] = {-1.,-1.,-1., 1., 0., 0., 0., 1.,1., 1., 1., 1.,
  295.               -2.,-2.,-2., 1., 0., 0., 0., 1.,2., 2., 2., 1.,
  296.               -1.,-1.,-1., 1., 0., 0., 0., 1.,1., 1., 1., 1.};
  297.  
  298.     static float sbl_row[] = {-1.,-1.,-1., 1., 0., 0., 0., 1., 1., 1., 1., 1.};
  299.     static float sbl_col[] = { 1., 1., 1., 1., 2., 2., 2., 1., 1., 1., 1., 1.};
  300.     int i, j;    
  301.     unsigned char *f;
  302.     float *s;
  303.  
  304.     filter_info->create = create_sobel; /* for resizing */
  305.     filter_info->contents = SOBEL;
  306.  
  307.     filter_info->width = 3;
  308.     filter_info->height = 3;
  309.  
  310.     if(filter_info->filter) free(filter_info->filter);
  311.     if(filter_info->row) free(filter_info->row);
  312.     if(filter_info->col) free(filter_info->col);
  313.  
  314.     filter_info->filter = (unsigned char *)malloc(filter_info->width *
  315.                           filter_info->height *
  316.                           format_size(filter_info->format) *
  317.                           type_size(filter_info->type));
  318.  
  319.     filter_info->row = (unsigned char *)malloc(filter_info->width *
  320.                      format_size(filter_info->format) *
  321.                      type_size(filter_info->type));
  322.  
  323.     filter_info->col = (unsigned char *)malloc(filter_info->height *
  324.                      format_size(filter_info->format) *
  325.                      type_size(filter_info->type));
  326.  
  327.     
  328.     s = sbl;
  329.     f = filter_info->filter;
  330.     for(j = 0;j < 3;j++) {
  331.     for(i = 0;i < 3;i++) {
  332.         write_element(s, &f, filter_info->format, filter_info->type);
  333.         s += 4;
  334.     }
  335.     }
  336.  
  337.     s = sbl_row;
  338.     f = filter_info->row;
  339.     for(i = 0;i < 3;i++) {
  340.     write_element(s, &f, filter_info->format, filter_info->type);
  341.     s += 4;
  342.     }
  343.  
  344.     s = sbl_col;
  345.     f = filter_info->col;
  346.     for(j = 0;j < 3;j++) {
  347.     write_element(s, &f, filter_info->format, filter_info->type);
  348.     s += 4;
  349.     }
  350. }
  351.  
  352.  
  353. /*
  354. ** Create a laplacian filter
  355. */
  356. void create_laplace(Filter *filter_info)
  357. {
  358.     float lp[] = { 0., 0., 0., 1.,   1., 1., 1., 1.,  0., 0., 0., 1.,
  359.            1., 1., 1., 1.,  -4.,-4.,-4., 1.,  1., 1., 1., 1.,
  360.            0., 0., 0., 1.,   1., 1., 1., 1.,  0., 0., 0., 1.};
  361.  
  362.     int i, j;    
  363.     unsigned char *f;
  364.     float *s;
  365.  
  366.     filter_info->create = create_laplace; /* for resizing */
  367.     filter_info->contents = LAPLACE;
  368.  
  369.     filter_info->width = 3;
  370.     filter_info->height = 3;
  371.  
  372.     if(filter_info->filter) free(filter_info->filter);
  373.     if(filter_info->row) free(filter_info->row);
  374.     if(filter_info->col) free(filter_info->col);
  375.  
  376.     filter_info->filter = (unsigned char *)malloc(filter_info->width *
  377.                            filter_info->height *
  378.                           format_size(filter_info->format) *
  379.                           type_size(filter_info->type));
  380.  
  381.     filter_info->row = NULL;
  382.     filter_info->col = NULL;
  383.     
  384.     s = lp;
  385.     f = filter_info->filter;
  386.     for(j = 0;j < 3;j++) {
  387.     for(i = 0;i < 3;i++) {
  388.         write_element(s, &f, filter_info->format, filter_info->type);
  389.         s += 4;
  390.     }
  391.     }
  392. }
  393.  
  394. /*
  395. ** Create a Box filter
  396. */
  397. void create_box(Filter *filter_info)
  398. {
  399.     int i;
  400.     float value[4];
  401.     unsigned char *f;
  402.  
  403.     filter_info->create = create_box; /* for resizing */
  404.     filter_info->contents = BOX;
  405.  
  406.     /* TODO: check for maximum filter width, height? */
  407.  
  408.     if(filter_info->filter) free(filter_info->filter);
  409.     if(filter_info->row) free(filter_info->row);
  410.     if(filter_info->col) free(filter_info->col);
  411.  
  412.     filter_info->filter = (unsigned char *)malloc(filter_info->width *
  413.                           filter_info->height *
  414.                           format_size(filter_info->format) *
  415.                           type_size(filter_info->type));
  416.  
  417.     filter_info->row = (unsigned char *)malloc(filter_info->width *
  418.                      format_size(filter_info->format) *
  419.                      type_size(filter_info->type));
  420.  
  421.     filter_info->col = (unsigned char *)malloc(filter_info->height *
  422.                      format_size(filter_info->format) *
  423.                      type_size(filter_info->type));
  424.  
  425.  
  426.     value[0] = value[1] = value[2] = 1.0/(GLfloat)(filter_info->width * 
  427.                            filter_info->height);
  428.     value[3] = 1.0;
  429.  
  430.     f = filter_info->filter;
  431.     for(i = 0; i < filter_info->width * filter_info->height; i++) {
  432.     write_element(value, &f, filter_info->format, filter_info->type);
  433.     }
  434.  
  435.     value[0] = value[1] = value[2] = 1.0/(GLfloat)filter_info->width;
  436.     value[3] = 1.0;
  437.     f = filter_info->row;
  438.     for(i = 0; i < filter_info->width; i++) {
  439.     write_element(value, &f, filter_info->format, filter_info->type);
  440.     }
  441.  
  442.     value[0] = value[1] = value[2] = 1.0/(GLfloat)filter_info->height;
  443.     value[3] = 1.0;
  444.     f = filter_info->col;
  445.     for(i = 0; i < filter_info->height; i++) {
  446.     write_element(value, &f, filter_info->format, filter_info->type);
  447.     }
  448. }
  449.  
  450.  
  451. /*
  452. ** Create an image of white squares on a black background
  453. */
  454. void create_squares(Image *image_info)
  455. {
  456.     unsigned int x, y;
  457.     float zero[4], one[4];
  458.     unsigned char *i;
  459.  
  460.     zero[0] = 0.; zero[1] = 0.; zero[2] = 0.; zero[3] = 1.;
  461.     one[0] = 1.; one[1] = 1.; one[2] = 1.; one[3] = 1.;
  462.  
  463.     image_info->create = create_squares; /* for resizing */
  464.  
  465.     if(image_info->image) free(image_info->image);
  466.  
  467.     image_info->image = (unsigned char *)malloc(image_info->wid *
  468.                           image_info->ht *
  469.                           format_size(image_info->format) *
  470.                           type_size(image_info->type));
  471.  
  472.     i = image_info->image;
  473.     for(y = 0; y < image_info->ht; y++) {
  474.     for(x = 0; x < image_info->wid; x++) {
  475.         if(!(x/GRID & 0x1) & 
  476.            !(y/GRID & 0x1)) {
  477.         write_element(one, &i, image_info->format, image_info->type);
  478.         } else {
  479.         write_element(zero, &i, image_info->format, image_info->type);
  480.         }
  481.     }
  482.     }
  483. }
  484.  
  485. /*
  486. ** Create a checkerboard image
  487. */
  488.  
  489. void create_checkerboard(Image *image_info)
  490. {
  491.     unsigned int x, y;
  492.     float zero[4], one[4];
  493.     unsigned char *i;
  494.  
  495.     zero[0] = 0.; zero[1] = 0.; zero[2] = 0.; zero[3] = 1.;
  496.     one[0] = 1.; one[1] = 1.; one[2] = 1.; one[3] = 1.;
  497.  
  498.     image_info->create = create_checkerboard; /* for resizing */
  499.  
  500.     if(image_info->image) free(image_info->image);
  501.  
  502.     image_info->image = (unsigned char *)malloc(image_info->wid *
  503.                           image_info->ht *
  504.                           format_size(image_info->format) *
  505.                           type_size(image_info->type));
  506.  
  507.     i = image_info->image;
  508.     for(y = 0; y < image_info->ht; y++) {
  509.     for(x = 0; x < image_info->wid; x++) {
  510.         if((x/GRID & 0x1) ^ 
  511.            (y/GRID & 0x1)) {
  512.         write_element(one, &i, image_info->format, image_info->type);
  513.         } else {
  514.         write_element(zero, &i, image_info->format, image_info->type);
  515.         }
  516.     }
  517.     }
  518. }
  519.  
  520. void create_from_file(Image *image_info)
  521. {
  522.     IMAGE *fileimage;
  523.     GLubyte *img, *pixel;
  524.     unsigned short *rbuf, *gbuf, *bbuf;
  525.     int i,j;
  526.  
  527.  
  528.     image_info->create = create_from_file; /* for resizing */
  529.  
  530.     fileimage = iopen(image_info->filename, "r");
  531.     if(!fileimage) { /* open failed */
  532.     fprintf(stderr, "Unable to read rgb image file %s\n", 
  533.         image_info->filename);
  534.     return;
  535.     }    
  536.     
  537.     free(image_info->image);
  538.  
  539.     /* TODO: fix so format, type can be changed */
  540.     image_info->width = image_info->wid = fileimage->xsize; 
  541.     image_info->height = image_info->ht = fileimage->ysize; 
  542.     
  543.     image_info->type = GL_UNSIGNED_BYTE;
  544.     image_info->format = GL_RGB;
  545.     img = (GLubyte *)malloc(fileimage->xsize * 
  546.                 fileimage->ysize * 
  547.                 3 * 
  548.                 sizeof(GLushort));
  549.     image_info->image = (unsigned char *)img;
  550.  
  551.     rbuf = (unsigned short *) malloc(fileimage->xsize * sizeof(unsigned short));
  552.     gbuf = (unsigned short *) malloc(fileimage->xsize * sizeof(unsigned short));
  553.     bbuf = (unsigned short *) malloc(fileimage->xsize * sizeof(unsigned short));
  554.  
  555.  
  556.     for(j = 0; j < fileimage->ysize; j++) {
  557.     getrow(fileimage, rbuf, j, 0);
  558.     getrow(fileimage, gbuf, j, 1);
  559.     getrow(fileimage, bbuf, j, 2);
  560.     pixel = img + j * fileimage->xsize * 3; /* row pointer */
  561.     for(i = 0; i < fileimage->xsize;i++) {
  562.         pixel[0] = rbuf[i];
  563.         pixel[1] = gbuf[i];
  564.         pixel[2] = bbuf[i];
  565.         pixel += 3; /* next pixel */
  566.     }
  567.     }
  568.  
  569.     iclose(fileimage);
  570.     free(rbuf);
  571.     free(gbuf);
  572.     free(bbuf);
  573.  
  574. /* TODO: update option menus
  575.     XtVaSetValues(filter_format, XmNmenuHistory, button_1, NULL);
  576.     XtVaSetValues(filter_type, XmNmenuHistory, button_3, NULL);
  577. */
  578. }
  579.  
  580. void make_image(Image *image_info)
  581.  
  582.     switch(image_info->contents) { 
  583.     case SQUARES: /* generate squares on a background */
  584.     create_squares(image_info);
  585.     break;
  586.     case CHECKERBOARD: /* generate a checkerboard pattern */
  587.     create_checkerboard(image_info);
  588.     break;
  589.     case FILES: /* image read in from a file */
  590.     create_from_file(image_info);
  591.     break;
  592.     }
  593. }
  594.  
  595. void make_filter(Filter *filter_info)
  596. {
  597.     switch(filter_info->contents) {
  598.     case BOX:
  599.     create_box(filter_info);
  600.     break;
  601.     case SOBEL:
  602.     create_sobel(filter_info);
  603.     break;
  604.     case LAPLACE:
  605.     create_laplace(filter_info);
  606.     break;
  607.     }
  608. }
  609.  
  610. GLfloat pyramid[3 * (3 + 2) * 4]; /* 4 3d Triangles w/ 2d textures */
  611. void make_pyramid()
  612. {
  613.     int i, j, k;
  614.     float angle;
  615.  
  616.     angle = 120. * M_PI * 2.0 / 360. ;
  617.  
  618.     k = 0; /* index for loading array */
  619.     for(j = 0; j < 3; j++) { /* number of triangles */
  620.     for(i = j; i < j + 2; i++) { /* finding x & y coordinates */
  621.         if(i == j) {
  622.         pyramid[k++] = 0.0; /* texture coord */
  623.         pyramid[k++] = 0.0;
  624.         } else {
  625.         pyramid[k++] = 1.0; /* texture coord */
  626.         pyramid[k++] = 0.0;
  627.         }
  628.         pyramid[k++] = fcos(i * angle);
  629.         pyramid[k++] = fsin(i * angle);
  630.         pyramid[k++] = -1.0;
  631.     }
  632.     pyramid[k++] = 0.5; /* texture coord */
  633.     pyramid[k++] = 1.0;
  634.  
  635.     pyramid[k++] = 0.;
  636.     pyramid[k++] = 0.;
  637.     pyramid[k++] = 0.;
  638.     } 
  639.     /* now; last triangle */
  640.     for(i = 0; i < 3; i++) { /* finding x & y coordinates */
  641.     switch(i) {
  642.     case 0:
  643.         pyramid[k++] = 0.0; /* texture coord */
  644.         pyramid[k++] = 0.0;
  645.         break;
  646.     case 1:
  647.         pyramid[k++] = 1.0; /* texture coord */
  648.         pyramid[k++] = 0.0;
  649.         break;
  650.     case 2:
  651.         pyramid[k++] = 0.5; /* texture coord */
  652.         pyramid[k++] = 1.0;
  653.         break;
  654.     }
  655.     pyramid[k++] = fcos(i * angle);
  656.     pyramid[k++] = fsin(i * angle);
  657.     pyramid[k++] = -1.0;
  658.     }
  659. }
  660.  
  661. void clear_screen(Widget w, XtPointer data, XtPointer callData)
  662. {
  663.     glClear(GL_COLOR_BUFFER_BIT);
  664. }
  665.  
  666.  
  667. void draw_tex(Widget w, XtPointer data, XtPointer callData)
  668. {
  669.     GLint zoomx, zoomy;
  670.     int i;
  671.  
  672.     XmScaleGetValue(xzoom, &zoomx);
  673.     XmScaleGetValue(yzoom, &zoomy);
  674.     
  675.     glPixelZoom(zoomx/100., zoomy/100.);
  676.  
  677.     if(glIsEnabled(GL_TEXTURE_1D))
  678.     gluBuild1DMipmaps(GL_TEXTURE_1D, 4, image.wid,
  679.               image.format, image.type, image.image);
  680.     if(glIsEnabled(GL_TEXTURE_2D))
  681.     gluBuild2DMipmaps(GL_TEXTURE_2D, 4, image.wid, image.ht,
  682.               image.format, image.type, image.image);
  683.  
  684.     glBegin(GL_TRIANGLES);
  685.     glTexCoord2f(0.,0.);
  686.     glVertex3f(-1.,-1.,0.);
  687.     glTexCoord2f(1.,0.);
  688.     glVertex3f(1.,-1.,0.);
  689.     glTexCoord2f(.5,1.);
  690.     glVertex3f(0.,1.,0.);
  691.     glEnd();
  692.  
  693. }
  694.  
  695.  
  696. void load_image(Widget w, XtPointer data, XtPointer callData)
  697. {
  698.     make_image(&image);
  699. }
  700.  
  701. void draw_pix(Widget w, XtPointer data, XtPointer callData)
  702. {
  703.     GLint zoomx, zoomy;
  704.  
  705.     XmScaleGetValue(xzoom, &zoomx);
  706.     XmScaleGetValue(yzoom, &zoomy);
  707.     
  708.     glPixelZoom(zoomx/100., zoomy/100.);
  709.  
  710.     glRasterPos3f(-1.0, -1.0, 0.0);
  711.  
  712.     glDrawPixels(image.wid, image.ht, image.format, image.type,
  713.          image.image);
  714. }
  715.  
  716. void read_pix(Widget w, XtPointer data, XtPointer callData)
  717. {
  718.     GLint zoomx, zoomy;
  719.  
  720.     XmScaleGetValue(xzoom, &zoomx);
  721.     XmScaleGetValue(yzoom, &zoomy);
  722.     
  723.     glPixelZoom(zoomx/100., zoomy/100.);
  724.  
  725.     glReadPixels(0, 0, image.wid, image.ht, image.format, image.type,
  726.          image.image);
  727. }
  728.  
  729. void copy_pix(Widget w, XtPointer data, XtPointer callData)
  730. {
  731.     GLint zoomx, zoomy;
  732.  
  733.     XmScaleGetValue(xzoom, &zoomx);
  734.     XmScaleGetValue(yzoom, &zoomy);
  735.     
  736.     glPixelZoom(zoomx/100., zoomy/100.);
  737.  
  738.     glRasterPos2f(image.rasterposx, image.rasterposy);
  739.     glCopyPixels(image.x, image.y, image.width, image.height, GL_COLOR);
  740.     glRasterPos2f(-1.0, -1.0); /* restore raster position */
  741. }
  742.  
  743. void enable_1d(Widget w, XtPointer data, XtPointer call_data)
  744. {
  745.     if(((XmToggleButtonCallbackStruct *)call_data)->set)
  746.     glEnable(GL_CONVOLUTION_1D_EXT);
  747.     else
  748.     glDisable(GL_CONVOLUTION_1D_EXT);
  749. }
  750.  
  751. void enable_2d(Widget w, XtPointer data, XtPointer call_data)
  752. {
  753.     if(((XmToggleButtonCallbackStruct *)call_data)->set)
  754.     glEnable(GL_CONVOLUTION_2D_EXT);
  755.     else
  756.     glDisable(GL_CONVOLUTION_2D_EXT);
  757. }
  758.  
  759. void enable_tex_1d(Widget w, XtPointer data, XtPointer call_data)
  760. {
  761.     if(((XmToggleButtonCallbackStruct *)call_data)->set)
  762.     glEnable(GL_TEXTURE_1D);
  763.     else
  764.     glDisable(GL_TEXTURE_1D);
  765. }
  766.  
  767. void enable_tex_2d(Widget w, XtPointer data, XtPointer call_data)
  768. {
  769.     if(((XmToggleButtonCallbackStruct *)call_data)->set)
  770.     glEnable(GL_TEXTURE_2D);
  771.     else
  772.     glDisable(GL_TEXTURE_2D);
  773. }
  774.  
  775. void enable_sep_2d(Widget w, XtPointer data, XtPointer call_data)
  776. {
  777.     if(((XmToggleButtonCallbackStruct *)call_data)->set)
  778.     glEnable(GL_SEPARABLE_2D_EXT);
  779.     else
  780.     glDisable(GL_SEPARABLE_2D_EXT);
  781. }
  782.  
  783. void make_conv_1d(Widget w, XtPointer data, XtPointer callData)
  784. {
  785.     int wid, ht;
  786.  
  787.     XmScaleGetValue(fwidth, &wid);
  788.     XmScaleGetValue(fheight, &ht);
  789.     filter.width = wid;
  790.     filter.height = ht;
  791.     (*filter.create)(&filter);
  792.  
  793.     /* load filter */
  794.     glConvolutionFilter1DEXT(GL_CONVOLUTION_1D_EXT, 
  795.                  filter.internalformat,
  796.                  filter.width,
  797.                  filter.format,
  798.                  filter.type,
  799.                  filter.row);
  800.     check_error("glConvolutionFilter1DEXT");
  801. }
  802.  
  803. void make_conv_2d(Widget w, XtPointer data, XtPointer callData)
  804. {
  805.     int wid, ht;
  806.  
  807.     XmScaleGetValue(fwidth, &wid);
  808.     XmScaleGetValue(fheight, &ht);
  809.     filter.width = wid;
  810.     filter.height = ht;
  811.     (*filter.create)(&filter);
  812.  
  813.     /* load filter */
  814.     glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT, 
  815.                  filter.internalformat,
  816.                  filter.width, filter.height,
  817.                  filter.format,
  818.                  filter.type,
  819.                  filter.filter);
  820.     check_error("glConvolutionFilter2DEXT");
  821. }
  822.  
  823. void make_sep_2d(Widget w, XtPointer data, XtPointer callData)
  824. {
  825.     int wid, ht;
  826.  
  827.     XmScaleGetValue(fwidth, &wid);
  828.     XmScaleGetValue(fheight, &ht);
  829.     filter.width = wid;
  830.     filter.height = ht;
  831.     (*filter.create)(&filter);
  832.  
  833.     /* load filter */
  834.     glSeparableFilter2DEXT(GL_SEPARABLE_2D_EXT, 
  835.                filter.internalformat,
  836.                filter.width, filter.height,
  837.                filter.format,
  838.                filter.type,
  839.                filter.row,
  840.                filter.col);
  841.     check_error("glSeparableFilter2DEXT");
  842. }
  843.  
  844. void new_list(Widget w, XtPointer data, XtPointer callData)
  845. {
  846.     if(glIsList(1)) {
  847.     check_error("glIsList");
  848.     glDeleteLists(1,1);
  849.     check_error("glDeleteLists");
  850.     }
  851.     glNewList(1, GL_COMPILE);
  852.     check_error("glNewList");
  853. }
  854.  
  855. void end_list(Widget w, XtPointer data, XtPointer callData)
  856. {
  857.     glEndList();
  858.     check_error("glEndList");
  859. }
  860.  
  861. void call_list(Widget w, XtPointer data, XtPointer callData)
  862. {
  863.     glCallList(1);
  864.     check_error("glCallList");
  865. }
  866.  
  867.  
  868. /*
  869. ** Return number of characters needed to print a given type
  870. */
  871. int print_type_size(GLenum type)
  872. {
  873.     return(4); /* hardwired for GL_FLOAT (X.XX or %.2f) */
  874. }
  875. /*
  876. ** Return number of characters needed to print a given format & type
  877. */
  878. int print_format_size(GLenum format, GLenum type)
  879. {
  880.    return (print_type_size(type) + 2) * 4 + 1; /* hardwired for RGBA */
  881. }
  882.  
  883. void get_conv_1d_filter(Widget w, XtPointer data, XtPointer callData)
  884. {
  885.     GLfloat *filter_image, *f;
  886.     Widget filter_output;
  887.     XmString filter_elements;
  888.     char *filter_text, *ft;
  889.     GLint wid, ht;
  890.     int i, j;
  891.  
  892.     glGetConvolutionParameterivEXT(GL_CONVOLUTION_1D_EXT,
  893.                   GL_CONVOLUTION_WIDTH_EXT,
  894.                   &wid);
  895.     check_error("glGetConvolutionParameterivEXT");
  896.  
  897.     ht = 1;
  898.     filter_image = (GLfloat *)malloc(4 * sizeof(GLfloat) * wid);
  899.  
  900.     glGetConvolutionFilterEXT(GL_CONVOLUTION_1D_EXT,
  901.                   filter.get_format,
  902.                   filter.get_type,
  903.                   filter_image);
  904.     check_error("glGetConvolutionFilterEXT");
  905.  
  906.     
  907. /*
  908. **     TODO: make so format and type can vary.
  909. **     4 components/element, 6 chars/component, 1 comma + 3 space/element,
  910. **     2 newline/line
  911. */
  912.     filter_text = (char *)malloc(26 * wid + 3);
  913.  
  914.     ft = filter_text;
  915.     for(f = filter_image, i = 0; i < wid; i++) {
  916.     ft += sprintf(ft, "%.2f  ",  *f++);
  917.     ft += sprintf(ft, "%.2f  ",  *f++);
  918.     ft += sprintf(ft, "%.2f  ",  *f++);
  919.     ft += sprintf(ft, "%.2f,   ", *f++);
  920.     }
  921.  
  922.     filter_output = XmCreateMessageDialog(toplevel, "FilterContents", NULL, 0);
  923.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  924.                      XmDIALOG_CANCEL_BUTTON));
  925.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  926.                      XmDIALOG_HELP_BUTTON));
  927.     filter_elements = XmStringCreateLtoR(filter_text,
  928.                      XmFONTLIST_DEFAULT_TAG);
  929.     XtVaSetValues(filter_output, XmNmessageString, filter_elements, NULL);
  930.     XmStringFree(filter_elements);
  931.     XtManageChild(filter_output);
  932.     free(filter_text);
  933.     free(filter_image);
  934. }
  935.  
  936. void get_conv_2d_filter(Widget w, XtPointer data, XtPointer callData)
  937. {
  938.     GLfloat *filter_image, *f;
  939.     Widget filter_output;
  940.     XmString filter_elements;
  941.     char *filter_text, *ft;
  942.     GLint wid, ht;
  943.     int i, j;
  944.  
  945.     glGetConvolutionParameterivEXT(GL_CONVOLUTION_2D_EXT,
  946.                   GL_CONVOLUTION_WIDTH_EXT,
  947.                   &wid);
  948.     check_error("glGetConvolutionParameterivEXT");
  949.  
  950.     glGetConvolutionParameterivEXT(filter.get_target,
  951.                    GL_CONVOLUTION_HEIGHT_EXT,
  952.                    &ht);
  953.     check_error("glGetConvolutionParameterivEXT");
  954.  
  955.     filter_image = (GLfloat *)malloc(4 * sizeof(GLfloat) * wid * ht);
  956.  
  957.     glGetConvolutionFilterEXT(GL_CONVOLUTION_2D_EXT,
  958.                   filter.get_format,
  959.                   filter.get_type,
  960.                   filter_image);
  961.     check_error("glGetConvolutionFilterEXT");
  962.  
  963.     
  964. /*
  965. **     TODO: make so format and type can vary.
  966. **     4 components/element, 6 chars/component, 1 comma + 3 space/element,
  967. **     2 newline/line
  968. */
  969.     filter_text = (char *)malloc((26 * wid + 2) * ht + 1);
  970.  
  971.     ft = filter_text;
  972.     for(j = 0; j < ht; j++) { /* assuming output is RGBA */
  973.     for(f = filter_image, i = 0; i < wid; i++) {
  974.         ft += sprintf(ft, "%.2f  ",  *f++);
  975.         ft += sprintf(ft, "%.2f  ",  *f++);
  976.         ft += sprintf(ft, "%.2f  ",  *f++);
  977.         ft += sprintf(ft, "%.2f,   ", *f++);
  978.     }
  979.     if(j < ht - 1)
  980.         ft += sprintf(ft, "\n\n");
  981.     }
  982.  
  983.     filter_output = XmCreateMessageDialog(toplevel, "FilterContents", NULL, 0);
  984.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  985.                      XmDIALOG_CANCEL_BUTTON));
  986.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  987.                      XmDIALOG_HELP_BUTTON));
  988.     filter_elements = XmStringCreateLtoR(filter_text,
  989.                      XmFONTLIST_DEFAULT_TAG);
  990.     XtVaSetValues(filter_output, XmNmessageString, filter_elements, NULL);
  991.     XmStringFree(filter_elements);
  992.     XtManageChild(filter_output);
  993.     free(filter_text);
  994.     free(filter_image);
  995. }
  996.  
  997. void get_sep_filter(Widget w, XtPointer data, XtPointer callData)
  998. {
  999.     GLfloat *row, *col, *dummy, *f;
  1000.     Widget filter_output;
  1001.     XmString filter_elements;
  1002.     char *filter_text, *ft;
  1003.     GLint wid, ht;
  1004.     int i;
  1005.  
  1006.     /* which convolution filter are we using? */
  1007.  
  1008.     glGetConvolutionParameterivEXT(GL_SEPARABLE_2D_EXT,
  1009.                   GL_CONVOLUTION_WIDTH_EXT,
  1010.                   &wid);
  1011.     check_error("glGetConvolutionParameterivEXT");
  1012.     glGetConvolutionParameterivEXT(GL_SEPARABLE_2D_EXT,
  1013.                   GL_CONVOLUTION_HEIGHT_EXT,
  1014.                   &ht);
  1015.     check_error("glGetConvolutionParameterivEXT");
  1016.  
  1017.     row = (GLfloat *)malloc(4 * sizeof(GLfloat) * wid);
  1018.     col = (GLfloat *)malloc(4 * sizeof(GLfloat) * ht);
  1019.  
  1020.     glGetSeparableFilterEXT(GL_SEPARABLE_2D_EXT,
  1021.                 filter.get_format,
  1022.                 filter.get_type,
  1023.                 row,
  1024.                 col,
  1025.                 dummy);
  1026.     check_error("glGetSeparableFilterEXT");
  1027.  
  1028.  
  1029. /*
  1030. **     TODO: make so format and type can vary.
  1031. **     4 components/element, 6 chars/component, 1 comma + 3 space/element,
  1032. **     2 newline/line
  1033. */
  1034.     filter_text = (char *)malloc(26 * wid + 26 * ht + 15);
  1035.  
  1036.     ft = filter_text;
  1037.     ft += sprintf(ft, "Row:  ");
  1038.     for(f = row, i = 0; i < wid; i++) { /* assuming output is RGBA */
  1039.     ft += sprintf(ft, "%.2f  ",  *f++);
  1040.     ft += sprintf(ft, "%.2f  ",  *f++);
  1041.     ft += sprintf(ft, "%.2f  ",  *f++);
  1042.     ft += sprintf(ft, "%.2f,   ", *f++);
  1043.     }
  1044.  
  1045.     ft += sprintf(ft, "\n\n Col:  ");
  1046.     for(f = col, i = 0; i < ht; i++) { /* assuming output is RGBA */
  1047.     ft += sprintf(ft, "%.2f  ",  *f++);
  1048.     ft += sprintf(ft, "%.2f  ",  *f++);
  1049.     ft += sprintf(ft, "%.2f  ",  *f++);
  1050.     ft += sprintf(ft, "%.2f,   ", *f++);
  1051.     }
  1052.  
  1053.     filter_output = XmCreateMessageDialog(toplevel, "FilterContents", NULL, 0);
  1054.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  1055.                      XmDIALOG_CANCEL_BUTTON));
  1056.     XtUnmanageChild(XmMessageBoxGetChild(filter_output, 
  1057.                      XmDIALOG_HELP_BUTTON));
  1058.     filter_elements = XmStringCreateLtoR(filter_text,
  1059.                      XmFONTLIST_DEFAULT_TAG);
  1060.     XtVaSetValues(filter_output, XmNmessageString, filter_elements, NULL);
  1061.     XmStringFree(filter_elements);
  1062.     XtManageChild(filter_output);
  1063.     free(filter_text);
  1064.     free(row);
  1065.     free(col);
  1066. }
  1067.  
  1068. void copy_filter_1d(Widget w, XtPointer data, XtPointer callData)
  1069. {
  1070.     glCopyConvolutionFilter1DEXT(GL_CONVOLUTION_1D_EXT, GL_RGB, 
  1071.                  image.x, image.y, 
  1072.                  image.width);
  1073.     check_error("glCopyConvolutionFilter1DEXT");
  1074.  
  1075.     XmScaleSetValue(fwidth, image.width);
  1076. }
  1077.  
  1078. void copy_filter_2d(Widget w, XtPointer data, XtPointer callData)
  1079. {
  1080.     glCopyConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT, GL_RGB, 
  1081.                  image.x, image.y, 
  1082.                  image.width, image.height);
  1083.     check_error("glCopyConvolutionFilter2DEXT");
  1084.     XmScaleSetValue(fwidth, image.width);
  1085.     XmScaleSetValue(fheight, image.height);
  1086. }
  1087.  
  1088.  
  1089. GLboolean made_current = GL_FALSE;
  1090.  
  1091. void resize(Widget w, XtPointer data, XtPointer callData)
  1092. {
  1093.     Dimension wid, ht;
  1094.  
  1095.     if(made_current) {
  1096.     XtVaGetValues(w, XmNwidth, &wid, XmNheight, &ht, NULL);
  1097.     glViewport(0,0, (GLint) wid, (GLint) ht);
  1098.     check_error("glViewport");
  1099.     image.wid = wid;
  1100.     image.ht = ht;
  1101.     make_image(&image);
  1102.     }
  1103. }
  1104.  
  1105. void map_state_changed(Widget w, XtPointer data, XEvent *event, Boolean *cont)
  1106. {
  1107.     switch(event->type) {
  1108.     case MapNotify:
  1109.     break;
  1110.     case UnmapNotify:
  1111.     break;
  1112.     }
  1113. }
  1114.  
  1115. void get_filename(Widget w, XtPointer data, XtPointer callData)
  1116. {
  1117.     char *filename;
  1118.  
  1119.     XmFileSelectionBoxCallbackStruct *cbs =
  1120.     (XmFileSelectionBoxCallbackStruct *) callData;
  1121.  
  1122.     if(cbs->reason == XmCR_OK) {
  1123.     if(!XmStringGetLtoR(cbs->value, XmFONTLIST_DEFAULT_TAG, &filename))
  1124.         return; /* internal error */
  1125.  
  1126.     strcpy(image.filename, filename);
  1127.     XtFree(filename);
  1128.     create_from_file(&image);
  1129.     }
  1130.     XtPopdown(XtParent(w));
  1131. }
  1132.  
  1133. void cancel_file(Widget w, XtPointer data, XtPointer callData)
  1134. {
  1135.     XtPopdown(XtParent(w));
  1136.     return;
  1137. }
  1138.  
  1139. /*
  1140. ** Set the type of image to work on
  1141. */
  1142. void set_image_contents(Widget w, XtPointer data, XtPointer callData)
  1143. {
  1144.     Widget dialog;
  1145.     XmString dir;
  1146.  
  1147.     image.contents = (ImageContents)data;
  1148.  
  1149.     switch((ImageContents)data) {
  1150.     case SQUARES:
  1151.     create_squares(&image);
  1152.     break;
  1153.     case CHECKERBOARD:
  1154.     create_checkerboard(&image);
  1155.     break;
  1156.     case FILES:
  1157.     dir = XmStringCreateLocalized("/usr/demos/data/images/*.rgb"); /**/
  1158.     dialog = XmCreateFileSelectionDialog(toplevel, "imagefile", NULL, 0);
  1159.     XtAddCallback(dialog, XmNokCallback, get_filename, NULL);
  1160.     XtAddCallback(dialog, XmNcancelCallback, get_filename, NULL);
  1161.     XtSetSensitive(XmSelectionBoxGetChild(dialog, XmDIALOG_HELP_BUTTON),
  1162.                False);
  1163.     XmFileSelectionDoSearch(dialog, dir);
  1164.     XtManageChild(dialog);
  1165.     XmStringFree(dir);
  1166.     break;
  1167.     }
  1168. }
  1169.  
  1170. void set_image_format(Widget w, XtPointer data, XtPointer callData)
  1171. {
  1172.     switch((int)data) {
  1173.     case 0: /* RGBA */
  1174.     image.format = GL_RGBA;
  1175.     break;
  1176.     case 1: /* RGB */
  1177.     image.format = GL_RGB;
  1178.     break;
  1179.     case 2: /* Luminance */
  1180.     image.format = GL_LUMINANCE;
  1181.     break;
  1182.     case 3: /* Luminance-Alpha */
  1183.     image.format = GL_LUMINANCE_ALPHA;
  1184.     break;
  1185.     case 4: /* Intensity */
  1186.     image.format = GL_INTENSITY_EXT;
  1187.     break;
  1188.     }
  1189.     make_image(&image);
  1190. }
  1191.  
  1192. void set_image_type(Widget w, XtPointer data, XtPointer callData)
  1193. {
  1194.     switch((int)data) {
  1195.     case 0: 
  1196.     image.type = GL_BYTE;
  1197.     break;
  1198.     case 1: 
  1199.     image.type = GL_UNSIGNED_BYTE;
  1200.     break;
  1201.     case 2: 
  1202.     image.type = GL_SHORT;
  1203.     break;
  1204.     case 3: 
  1205.     image.type = GL_UNSIGNED_SHORT;
  1206.     break;
  1207.     case 4: 
  1208.     image.type = GL_INT;
  1209.     break;
  1210.     case 5: 
  1211.     image.type = GL_UNSIGNED_INT;
  1212.     break;
  1213.     case 6: 
  1214.     image.type = GL_FLOAT;
  1215.     break;
  1216.     }
  1217.     make_image(&image);
  1218. }
  1219.  
  1220.  
  1221. void set_filter_format(Widget w, XtPointer data, XtPointer callData)
  1222. {
  1223.     switch((int)data) {
  1224.     case 0: /* RGBA */
  1225.     filter.format = GL_RGBA;
  1226.     break;
  1227.     case 1: /* RGB */
  1228.     filter.format = GL_RGB;
  1229.     break;
  1230.     case 2: /* Luminance */
  1231.     filter.format = GL_LUMINANCE;
  1232.     break;
  1233.     case 3: /* Luminance-Alpha */
  1234.     filter.format = GL_LUMINANCE_ALPHA;
  1235.     break;
  1236.     case 4: /* Intensity */
  1237.     filter.format = GL_INTENSITY_EXT;
  1238.     break;
  1239.     }
  1240.     make_filter(&filter);
  1241. }
  1242.  
  1243. void set_filter_type(Widget w, XtPointer data, XtPointer callData)
  1244. {
  1245.     switch((int)data) {
  1246.     case 0: 
  1247.     filter.type = GL_BYTE;
  1248.     break;
  1249.     case 1: 
  1250.     filter.type = GL_UNSIGNED_BYTE;
  1251.     break;
  1252.     case 2: 
  1253.     filter.type = GL_SHORT;
  1254.     break;
  1255.     case 3: 
  1256.     filter.type = GL_UNSIGNED_SHORT;
  1257.     break;
  1258.     case 4: 
  1259.     filter.type = GL_INT;
  1260.     break;
  1261.     case 5: 
  1262.     filter.type = GL_UNSIGNED_INT;
  1263.     break;
  1264.     case 6: 
  1265.     filter.type = GL_FLOAT;
  1266.     break;
  1267.     }
  1268.     make_filter(&filter);
  1269. }
  1270.  
  1271. void set_filter_contents(Widget w, XtPointer data, XtPointer callData)
  1272. {
  1273.     switch((int)data) {
  1274.     case 0: /* Box Filter */
  1275.     create_box(&filter);
  1276.     break;
  1277.     case 1: /* Laplace Filter */
  1278.     create_laplace(&filter);
  1279.     break;
  1280.     case 2: /* Sobel Filter */
  1281.     create_sobel(&filter);
  1282.     break;
  1283.     default:
  1284.     break;
  1285.     }
  1286. }
  1287.  
  1288. /*
  1289. ** Read mouse (or any other) input events to the drawing window.
  1290. ** for now, it is used to specify the source and dest of copy pixels
  1291. */
  1292. void mouse_input(Widget w, XtPointer client_data, XtPointer call_data)
  1293. {
  1294.     GLint x,y;
  1295.     static int push_state = 0; /* 0 source, 1 dest */
  1296.     XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)call_data;
  1297.     XEvent *event = cbs->event;
  1298.     GLfloat sx, sy;
  1299.  
  1300.     
  1301.     sx = 2.0/(GLfloat)image.wid;
  1302.     sy = 2.0/(GLfloat)image.ht;
  1303.  
  1304. /*    glBlendEquationEXT(GL_LOGIC_OP); 
  1305.  
  1306.     glEnable(GL_BLEND);
  1307. */
  1308.     if(cbs->reason == XmCR_INPUT) {
  1309.     if(event->xany.type == ButtonPress) {
  1310.         if(push_state) { /* lower left corner of dest */
  1311.         x = event->xbutton.x - (GLint)image.wid / 2;
  1312.         y =(GLint)image.ht - 1 - event->xbutton.y - (GLint)image.ht / 2;
  1313.         image.rasterposx =  2 * x / (GLfloat)image.wid;
  1314.         image.rasterposy =  2 * y / (GLfloat)image.ht;
  1315.         glBegin(GL_LINES);
  1316.         glVertex2f(x * sx - .1, y * sy);
  1317.         glVertex2f(x * sx + .1, y * sy);
  1318.         glVertex2f(x * sx, y * sy - .1);
  1319.         glVertex2f(x * sx, y * sy + .1);
  1320.         glEnd();
  1321.         check_error("glBegin/glEnd");
  1322.         } else { /* lower left corner of source */
  1323.         image.x = event->xbutton.x;
  1324.         image.y = (image.height - 1) - event->xbutton.y;
  1325.         }
  1326.     } else if (event->xany.type == ButtonRelease) {
  1327.         if(push_state) { /* ignore */
  1328.         push_state = ~push_state;
  1329.         } else { /* upper right corner of source */
  1330.         image.width = event->xbutton.x - image.x;
  1331.         image.height = image.ht - 1 - event->xbutton.y - image.y;
  1332.         push_state = ~push_state;
  1333.         }
  1334.     }
  1335.     }
  1336. /*
  1337.     glDisable(GL_BLEND);
  1338. */    
  1339. }
  1340.  
  1341.  
  1342. Display     *dpy;
  1343. XtAppContext app;
  1344. GLXContext   ctx;
  1345.  
  1346. main(int argc, char *argv[])
  1347. {
  1348.     XVisualInfo *vis;
  1349.     XmString rgba, rgb, l, la, intens;
  1350.     XmString fubyt, fbyt, fusht, fsht, fuinteg, finteg, fflt;
  1351.     XmString iubyt, ibyt, iusht, isht, iuinteg, iinteg, iflt;
  1352.     XmString fformat, ftype, fcont; 
  1353.     XmString iformat, itype, icont;
  1354.     XmString box, laplace, sobel;
  1355.     XmString squares, checks, files;
  1356.     static int vattribs[] = { GLX_RGBA, 0};
  1357.     int screen;
  1358.  
  1359.     XtSetLanguageProc(NULL, NULL, NULL);
  1360.  
  1361.     toplevel = XtAppInitialize(&app, "SampleCode", 
  1362.                    NULL, 0, 
  1363.                    &argc, argv,
  1364.                    fallbackResources, NULL, 
  1365.                    0);
  1366.  
  1367.     dpy = XtDisplay(toplevel);
  1368.     screen = DefaultScreen(dpy);
  1369.  
  1370.    if (!(vis = glXChooseVisual(dpy, screen, vattribs)))  {
  1371.        XtAppError(app, "desired visual can't be found");
  1372.    }
  1373.  
  1374.    /* get context */
  1375.    if (!(ctx = glXCreateContext(dpy, vis, 0, GL_TRUE))) {
  1376.        XtAppError(app, "couldn't create context");
  1377.    }
  1378.  
  1379.     XtAddEventHandler(toplevel, StructureNotifyMask, False,
  1380.               map_state_changed, NULL);
  1381.  
  1382.  
  1383.     form = XtVaCreateManagedWidget("form", 
  1384.                    xmFormWidgetClass, toplevel,
  1385.                    NULL);
  1386.  
  1387.     frame = XtVaCreateManagedWidget("frame",
  1388.                     xmFrameWidgetClass, form,
  1389.                     XmNtopAttachment, XmATTACH_FORM,
  1390.                     XmNleftAttachment, XmATTACH_FORM,
  1391.                     XmNrightAttachment, XmATTACH_FORM,
  1392.                     NULL);
  1393.  
  1394.     glxarea = XtVaCreateManagedWidget("glxarea", 
  1395.                       glwMDrawingAreaWidgetClass, frame, 
  1396.                       GLwNvisualInfo, vis, 
  1397.                       NULL);
  1398.     XtAddCallback(glxarea, XmNexposeCallback, clear_screen, NULL);
  1399.     XtAddCallback(glxarea, XmNresizeCallback, resize, NULL);
  1400.     XtAddCallback(glxarea, XmNinputCallback, mouse_input, NULL);
  1401.  
  1402.     control = XtVaCreateManagedWidget("ControlPanel",
  1403.                       xmFormWidgetClass, form,
  1404.                       XmNtopAttachment, XmATTACH_WIDGET,
  1405.                       XmNtopWidget, frame,
  1406.                       XmNleftAttachment, XmATTACH_FORM,
  1407.                       XmNrightAttachment, XmATTACH_FORM,
  1408.                       XmNbottomAttachment, XmATTACH_FORM,
  1409.                       NULL);
  1410.  
  1411.     enables = XtVaCreateManagedWidget("Enables",
  1412.                       xmRowColumnWidgetClass, control,
  1413.                       XmNtopAttachment, XmATTACH_FORM,
  1414.                       XmNleftAttachment, XmATTACH_FORM,
  1415.                       NULL);
  1416.  
  1417.     
  1418.     (void)XtVaCreateManagedWidget("title",
  1419.                   xmLabelWidgetClass, enables,
  1420.                   XtVaTypedArg, XmNlabelString, XmRString,
  1421.                   "Enables", sizeof("Enables"),
  1422.                   NULL);
  1423.  
  1424.  
  1425.     enabletex1d  = XtVaCreateManagedWidget("Tex1d",
  1426.                       xmToggleButtonWidgetClass, enables,
  1427.                       NULL);
  1428.     XtAddCallback(enabletex1d, XmNvalueChangedCallback, enable_tex_1d, NULL);
  1429.  
  1430.     enabletex2d  = XtVaCreateManagedWidget("Tex2d",
  1431.                       xmToggleButtonWidgetClass, enables,
  1432.                       NULL);
  1433.     XtAddCallback(enabletex2d, XmNvalueChangedCallback, enable_tex_2d, NULL);
  1434.  
  1435.  
  1436.     enable1d  = XtVaCreateManagedWidget("Conv1d",
  1437.                       xmToggleButtonWidgetClass, enables,
  1438.                       NULL);
  1439.     XtAddCallback(enable1d, XmNvalueChangedCallback, enable_1d, NULL);
  1440.  
  1441.     enable2d  = XtVaCreateManagedWidget("Conv2d",
  1442.                       xmToggleButtonWidgetClass, enables,
  1443.                       NULL);
  1444.     XtAddCallback(enable2d, XmNvalueChangedCallback, enable_2d, NULL);
  1445.  
  1446.     enableSep2d  = XtVaCreateManagedWidget("Sep2d",
  1447.                       xmToggleButtonWidgetClass, enables,
  1448.                       NULL);
  1449.     XtAddCallback(enableSep2d, XmNvalueChangedCallback, enable_sep_2d, NULL);
  1450.  
  1451.  
  1452.     actions = XtVaCreateManagedWidget("Actions",
  1453.                       xmRowColumnWidgetClass, control,
  1454.                       XmNtopAttachment, XmATTACH_FORM,
  1455.                       XmNrightAttachment, XmATTACH_FORM,
  1456.                       XmNleftWidget, enables,
  1457.                       NULL);
  1458.  
  1459.     draw = XtVaCreateManagedWidget("DrawPixels",
  1460.                       xmPushButtonWidgetClass, actions,
  1461.                       NULL);
  1462.     XtAddCallback(draw, XmNactivateCallback, draw_pix, NULL);
  1463.  
  1464.     readit = XtVaCreateManagedWidget("ReadPixels",
  1465.                     xmPushButtonWidgetClass, actions,
  1466.                     NULL);
  1467.     XtAddCallback(readit, XmNactivateCallback, read_pix, NULL);
  1468.  
  1469.     copy = XtVaCreateManagedWidget("CopyPixels",
  1470.                     xmPushButtonWidgetClass, actions,
  1471.                     NULL);
  1472.     XtAddCallback(copy, XmNactivateCallback, copy_pix, NULL);
  1473.  
  1474.     texmap = XtVaCreateManagedWidget("TexureMap",
  1475.                       xmPushButtonWidgetClass, actions,
  1476.                       NULL);
  1477.     XtAddCallback(texmap, XmNactivateCallback, draw_tex, NULL);
  1478.  
  1479.  
  1480.     load = XtVaCreateManagedWidget("New Image",
  1481.                     xmPushButtonWidgetClass, actions,
  1482.                     NULL);
  1483.     XtAddCallback(load, XmNactivateCallback, load_image, NULL);
  1484.  
  1485.  
  1486.     makeconv1d = XtVaCreateManagedWidget("Conv 1d",
  1487.                       xmPushButtonWidgetClass, actions,
  1488.                       NULL);
  1489.     XtAddCallback(makeconv1d, XmNactivateCallback, make_conv_1d, NULL);
  1490.  
  1491.     makeconv2d = XtVaCreateManagedWidget("Conv 2d",
  1492.                       xmPushButtonWidgetClass, actions,
  1493.                       NULL);
  1494.     XtAddCallback(makeconv2d, XmNactivateCallback, make_conv_2d, NULL);
  1495.  
  1496.     makesep2d  = XtVaCreateManagedWidget("Sep 2d",
  1497.                       xmPushButtonWidgetClass, actions,
  1498.                       NULL);
  1499.     XtAddCallback(makesep2d, XmNactivateCallback, make_sep_2d, NULL);
  1500.  
  1501.  
  1502.     getconv1dfilter  = XtVaCreateManagedWidget("Get Conv 1d",
  1503.                          xmPushButtonWidgetClass, actions,
  1504.                          NULL);
  1505.     XtAddCallback(getconv1dfilter, XmNactivateCallback, 
  1506.           get_conv_1d_filter, NULL);
  1507.  
  1508.     getconv2dfilter  = XtVaCreateManagedWidget("Get Conv 2d",
  1509.                          xmPushButtonWidgetClass, actions,
  1510.                          NULL);
  1511.     XtAddCallback(getconv2dfilter, XmNactivateCallback, 
  1512.           get_conv_2d_filter, NULL);
  1513.  
  1514.  
  1515.     getsepfilter  = XtVaCreateManagedWidget("Get Sep 2d",
  1516.                          xmPushButtonWidgetClass, actions,
  1517.                          NULL);
  1518.     XtAddCallback(getsepfilter, XmNactivateCallback, get_sep_filter, NULL);
  1519.  
  1520.     copyfilter1d  = XtVaCreateManagedWidget("Copy 1d",
  1521.                          xmPushButtonWidgetClass, actions,
  1522.                          NULL);
  1523.     XtAddCallback(copyfilter1d, XmNactivateCallback, copy_filter_1d, NULL);
  1524.  
  1525.     copyfilter2d  = XtVaCreateManagedWidget("Copy 2d",
  1526.                          xmPushButtonWidgetClass, actions,
  1527.                          NULL);
  1528.     XtAddCallback(copyfilter2d, XmNactivateCallback, copy_filter_2d, NULL);
  1529.  
  1530.     newlist  = XtVaCreateManagedWidget("glNewList",
  1531.                          xmPushButtonWidgetClass, actions,
  1532.                          NULL);
  1533.     XtAddCallback(newlist, XmNactivateCallback, new_list, NULL);
  1534.  
  1535.     endlist  = XtVaCreateManagedWidget("glEndList",
  1536.                          xmPushButtonWidgetClass, actions,
  1537.                          NULL);
  1538.     XtAddCallback(endlist, XmNactivateCallback, end_list, NULL);
  1539.  
  1540.     calllist  = XtVaCreateManagedWidget("glCallList",
  1541.                          xmPushButtonWidgetClass, actions,
  1542.                          NULL);
  1543.     XtAddCallback(calllist, XmNactivateCallback, call_list, NULL);
  1544.  
  1545.  
  1546.  
  1547.     filters = XtVaCreateManagedWidget("Filters",
  1548.                       xmRowColumnWidgetClass, control,
  1549.                       XmNtopAttachment, XmATTACH_WIDGET,
  1550.                       XmNleftAttachment, XmATTACH_FORM,
  1551.                       XmNtopWidget, enables,
  1552.                       NULL);
  1553.  
  1554.     (void)XtVaCreateManagedWidget("title",
  1555.                   xmLabelWidgetClass, filters,
  1556.                   XtVaTypedArg, XmNlabelString, XmRString,
  1557.                   "Filter", sizeof("Filter"),
  1558.                   NULL);
  1559.  
  1560.  
  1561.  
  1562.     fwidth = XtVaCreateManagedWidget("Width",
  1563.                      xmScaleWidgetClass, filters,
  1564.                      XtVaTypedArg, XmNtitleString, XmRString,
  1565.                      "Width", sizeof("Width"),
  1566.                      XmNmaximum, 11,
  1567.                      XmNminimum, 1,
  1568.                      XmNvalue, 3,
  1569.                      XmNshowValue, True,
  1570.                      XmNorientation, XmHORIZONTAL,
  1571.                      NULL);
  1572.  
  1573.     fheight = XtVaCreateManagedWidget("Height",
  1574.                      xmScaleWidgetClass, filters,
  1575.                      XtVaTypedArg, XmNtitleString, XmRString,
  1576.                      "Height", sizeof("Height"),
  1577.                      XmNmaximum, 11,
  1578.                      XmNminimum, 1,
  1579.                      XmNvalue, 3,
  1580.                      XmNshowValue, True,
  1581.                      XmNorientation, XmHORIZONTAL,
  1582.                      NULL);
  1583.  
  1584.  
  1585.     pzoom = XtVaCreateManagedWidget("Zoom",
  1586.                       xmRowColumnWidgetClass, control,
  1587.                       XmNtopAttachment, XmATTACH_WIDGET,
  1588.                       XmNrightAttachment, XmATTACH_FORM,
  1589.                       XmNtopWidget, actions,
  1590.                       NULL);
  1591.  
  1592.  
  1593.     (void)XtVaCreateManagedWidget("title",
  1594.                   xmLabelWidgetClass, pzoom,
  1595.                   XtVaTypedArg, XmNlabelString, XmRString,
  1596.                   "Zoom", sizeof("Zoom"),
  1597.                   NULL);
  1598.  
  1599.  
  1600.     xzoom = XtVaCreateManagedWidget("XZoom",
  1601.                     xmScaleWidgetClass, pzoom,
  1602.                     XtVaTypedArg, XmNtitleString, XmRString,
  1603.                     "ZoomX", sizeof("ZoomX"),
  1604.                     XmNdecimalPoints, 2,
  1605.                     XmNmaximum, 400,
  1606.                     XmNminimum, -200,
  1607.                     XmNvalue, 100,
  1608.                     XmNshowValue, True,
  1609.                     XmNorientation, XmHORIZONTAL,
  1610.                     NULL);
  1611.  
  1612.     yzoom = XtVaCreateManagedWidget("YZoom",
  1613.                     xmScaleWidgetClass, pzoom,
  1614.                     XtVaTypedArg, XmNtitleString, XmRString,
  1615.                     "ZoomY", sizeof("ZoomY"),
  1616.                     XmNdecimalPoints, 2,
  1617.                     XmNmaximum, 400,
  1618.                     XmNminimum, -200,
  1619.                     XmNvalue, 100,
  1620.                     XmNshowValue, True,
  1621.                     XmNorientation, XmHORIZONTAL,
  1622.                     NULL);
  1623.  
  1624.  
  1625.     fformat = XmStringCreateLocalized("FFormat");
  1626.     rgba = XmStringCreateLocalized("RGBA");
  1627.     rgb = XmStringCreateLocalized("RGB");
  1628.     l = XmStringCreateLocalized("L");
  1629.     la = XmStringCreateLocalized("LA");
  1630.     intens = XmStringCreateLocalized("I");
  1631.  
  1632.     filter_format = 
  1633.     XmVaCreateSimpleOptionMenu(filters, "FilterFormat",
  1634.                    fformat, 'F', 1, set_filter_format, 
  1635.                    XmVaPUSHBUTTON, rgba, 'R', NULL, NULL,
  1636.                    XmVaPUSHBUTTON, rgb, 'B', NULL, NULL,
  1637.                    XmVaPUSHBUTTON, l, 'L', NULL, NULL,
  1638.                    XmVaPUSHBUTTON, la, 'A', NULL, NULL,
  1639.                    XmVaPUSHBUTTON, intens, 'I', NULL, NULL,
  1640.                    NULL);
  1641.  
  1642.     XmStringFree(fformat);
  1643.     XmStringFree(rgba);
  1644.     XmStringFree(rgb);
  1645.     XmStringFree(l);
  1646.     XmStringFree(la);
  1647.     XmStringFree(intens);
  1648.  
  1649.     XtManageChild(filter_format);
  1650.  
  1651.  
  1652.     ftype = XmStringCreateLocalized("FType");
  1653.     fubyt = XmStringCreateLocalized("UBYTE");
  1654.     fbyt = XmStringCreateLocalized("BYTE");
  1655.     fusht = XmStringCreateLocalized("USHORT");
  1656.     fsht = XmStringCreateLocalized("SHORT");
  1657.     fuinteg = XmStringCreateLocalized("UINT");
  1658.     finteg = XmStringCreateLocalized("INT");
  1659.     fflt = XmStringCreateLocalized("FLOAT");
  1660.  
  1661.     filter_type = 
  1662.     XmVaCreateSimpleOptionMenu(filters, "FilterType",
  1663.                    ftype, 'T', 6, set_filter_type, 
  1664.                    XmVaPUSHBUTTON, fbyt, 'b', NULL, NULL,
  1665.                    XmVaPUSHBUTTON, fubyt, 'B', NULL, NULL,
  1666.                    XmVaPUSHBUTTON, fsht, 's', NULL, NULL,
  1667.                    XmVaPUSHBUTTON, fusht, 'S', NULL, NULL,
  1668.                    XmVaPUSHBUTTON, finteg, 'i', NULL, NULL,
  1669.                    XmVaPUSHBUTTON, fuinteg, 'I', NULL, NULL,
  1670.                    XmVaPUSHBUTTON, fflt, 'F', NULL, NULL,
  1671.                    NULL);
  1672.  
  1673.     XmStringFree(ftype);
  1674.     XmStringFree(fubyt);
  1675.     XmStringFree(fbyt);
  1676.     XmStringFree(fusht);
  1677.     XmStringFree(fsht);
  1678.     XmStringFree(fuinteg);
  1679.     XmStringFree(finteg);
  1680.     XmStringFree(fflt);
  1681.  
  1682.     XtManageChild(filter_type);
  1683.  
  1684.  
  1685.  
  1686.     fcont = XmStringCreateLocalized("FContents");
  1687.     box = XmStringCreateLocalized("Box");
  1688.     laplace = XmStringCreateLocalized("LaPlace");
  1689.     sobel = XmStringCreateLocalized("Sobel");
  1690.  
  1691.     filter_contents = 
  1692.     XmVaCreateSimpleOptionMenu(filters, "FilterContents",
  1693.                    fcont, 'F', 0, set_filter_contents, 
  1694.                    XmVaPUSHBUTTON, box, 'B', NULL, NULL,
  1695.                    XmVaPUSHBUTTON, laplace, 'L', NULL, NULL,
  1696.                    XmVaPUSHBUTTON, sobel, 'S', NULL, NULL,
  1697.                    NULL);
  1698.  
  1699.     XmStringFree(fcont);
  1700.     XmStringFree(laplace);
  1701.     XmStringFree(sobel);
  1702.     XmStringFree(box);
  1703.  
  1704.     XtManageChild(filter_contents);
  1705.  
  1706.     icont = XmStringCreateLocalized("IContents");
  1707.     squares = XmStringCreateLocalized("Squares");
  1708.     checks = XmStringCreateLocalized("CheckerBoard");
  1709.     files = XmStringCreateLocalized("File...");
  1710.  
  1711.     image_contents = 
  1712.     XmVaCreateSimpleOptionMenu(filters, "ImageContents",
  1713.                    icont, 'I', 0, set_image_contents, 
  1714.                    XmVaPUSHBUTTON, squares, 'S', NULL, NULL,
  1715.                    XmVaPUSHBUTTON, checks, 'C', NULL, NULL,
  1716.                    XmVaPUSHBUTTON, files, 'F', NULL, NULL,
  1717.                    NULL);
  1718.  
  1719.     XmStringFree(icont);
  1720.     XmStringFree(checks);
  1721.     XmStringFree(squares);
  1722.     XmStringFree(files);
  1723.  
  1724.     XtManageChild(image_contents);
  1725.  
  1726.     itype = XmStringCreateLocalized("IType");
  1727.     iubyt = XmStringCreateLocalized("UBYTE");
  1728.     ibyt = XmStringCreateLocalized("BYTE");
  1729.     iusht = XmStringCreateLocalized("USHORT");
  1730.     isht = XmStringCreateLocalized("SHORT");
  1731.     iuinteg = XmStringCreateLocalized("UINT");
  1732.     iinteg = XmStringCreateLocalized("INT");
  1733.     iflt = XmStringCreateLocalized("FLOAT");
  1734.  
  1735.     image_type = 
  1736.     XmVaCreateSimpleOptionMenu(filters, "ImageType",
  1737.                    itype, 'I', 6, set_image_type, 
  1738.                    XmVaPUSHBUTTON, ibyt, 'b', NULL, NULL,
  1739.                    XmVaPUSHBUTTON, iubyt, 'B', NULL, NULL,
  1740.                    XmVaPUSHBUTTON, isht, 's', NULL, NULL,
  1741.                    XmVaPUSHBUTTON, iusht, 'S', NULL, NULL,
  1742.                    XmVaPUSHBUTTON, iinteg, 'i', NULL, NULL,
  1743.                    XmVaPUSHBUTTON, iuinteg, 'I', NULL, NULL,
  1744.                    XmVaPUSHBUTTON, iflt, 'F', NULL, NULL,
  1745.                    NULL);
  1746.  
  1747.     XmStringFree(itype);
  1748.     XmStringFree(iubyt);
  1749.     XmStringFree(ibyt);
  1750.     XmStringFree(iusht);
  1751.     XmStringFree(isht);
  1752.     XmStringFree(iuinteg);
  1753.     XmStringFree(iinteg);
  1754.     XmStringFree(iflt);
  1755.  
  1756.     XtManageChild(image_type);
  1757.  
  1758.     
  1759.     iformat = XmStringCreateLocalized("IFormat");
  1760.     rgba = XmStringCreateLocalized("RGBA");
  1761.     rgb = XmStringCreateLocalized("RGB");
  1762.     l = XmStringCreateLocalized("L");
  1763.     la = XmStringCreateLocalized("LA");
  1764.     intens = XmStringCreateLocalized("I");
  1765.  
  1766.     image_format = 
  1767.     XmVaCreateSimpleOptionMenu(filters, "ImageFormat",
  1768.                    iformat, 'I', 1, set_image_format, 
  1769.                    XmVaPUSHBUTTON, rgba, 'R', NULL, NULL,
  1770.                    XmVaPUSHBUTTON, rgb, 'B', NULL, NULL,
  1771.                    XmVaPUSHBUTTON, l, 'L', NULL, NULL,
  1772.                    XmVaPUSHBUTTON, la, 'A', NULL, NULL,
  1773.                    XmVaPUSHBUTTON, intens, 'I', NULL, NULL,
  1774.                    NULL);
  1775.  
  1776.     XmStringFree(iformat);
  1777.     XmStringFree(rgba);
  1778.     XmStringFree(rgb);
  1779.     XmStringFree(l);
  1780.     XmStringFree(la);
  1781.     XmStringFree(intens);
  1782.  
  1783.     XtManageChild(image_format);
  1784.  
  1785.  
  1786.  
  1787.     XtRealizeWidget(toplevel);
  1788.  
  1789.     glXMakeCurrent(dpy, XtWindow(glxarea), ctx);
  1790.     made_current = GL_TRUE;
  1791.     
  1792.     glDisable(GL_DITHER);
  1793.  
  1794.     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  1795.  
  1796.    /* Default Enables */
  1797.  
  1798.     check_error("Clear Errors");
  1799.  
  1800.     image.wid = 256;
  1801.     image.ht = 256;
  1802.     image.x = 0;
  1803.     image.y = 0;
  1804.     image.width = 128;
  1805.     image.height = 128;
  1806.     image.rasterposx = 0.0;
  1807.     image.rasterposy = 0.0;
  1808.     image.contents = SQUARES;
  1809.     image.type = GL_FLOAT;
  1810.     image.format = GL_RGB;
  1811.     make_image(&image);
  1812.  
  1813.     filter.width = 3;
  1814.     filter.height = 3;
  1815.     filter.format = GL_RGB;
  1816.     filter.type = GL_FLOAT;
  1817.     filter.internalformat = GL_RGB;
  1818.     filter.get_target = GL_CONVOLUTION_2D_EXT;
  1819.     filter.get_format = GL_RGBA;
  1820.     filter.get_type = GL_FLOAT;
  1821.     filter.contents = BOX;
  1822.     make_filter(&filter);
  1823.  
  1824.     XtAppMainLoop(app);
  1825. }
  1826.