1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "xim.h"
8 #include "xutil.h"
9 
10 /*********************************************************************/
11 /***** 22 Aug 1998: modified to allow for 3 and 4 byte visuals,  *****/
12 /*****              and for either possible byte order -- RW Cox *****/
13 /*****                                                           *****/
14 /***** 11 Feb 1999: added ability to deal with MRI_rgb images    *****/
15 /*********************************************************************/
16 
17 /*------------------------------------------------------------------------*/
18 /*! Free an XImage created by mri_to_XImage() or its kin.
19 --------------------------------------------------------------------------*/
20 
MCW_kill_XImage(XImage * image)21 void MCW_kill_XImage( XImage *image )
22 {
23 ENTRY("MCW_kill_XImage") ;
24    if( image != NULL ){
25       if( image->data != NULL ){
26          XtFree( image->data ) ; image->data = NULL ;
27       }
28       XDestroyImage( image ) ;
29    }
30    EXRETURN ;
31 }
32 
33 /*-------------------------------------------------------------------------*/
34 /*! Create an XImage from an MRI_IMAGE of shorts or rgbs:
35     - values >= 0 draw from the "image" palette
36     - values <  0 draw from the "overlay" palette (stored in dc)
37 ---------------------------------------------------------------------------*/
38 
mri_to_XImage(MCW_DC * dc,MRI_IMAGE * im)39 XImage * mri_to_XImage( MCW_DC *dc , MRI_IMAGE *im )
40 {
41    int  w2, width, height ;
42    unsigned char *Image;
43    XImage        *ximage;
44    int  border ;        /* 22 Aug 1998 */
45 
46    register int     i , hw , sk , k ;
47    register short *sar ;
48    register Pixel *ppix , *npix ;
49    register unsigned char *ptr;
50 
51 ENTRY("mri_to_XImage") ;
52 
53    if( !im || !dc) {
54      fprintf(stderr,"\n*** Most ILLEGAL image input to mri_to_XImage\n") ;
55      EXIT(1) ;
56    }
57 
58    if( im->kind == MRI_rgb  ) RETURN( rgb_to_XImage(dc,im)  ) ;  /* 11 Feb 1999 */
59    if( im->kind == MRI_rgba ) RETURN( rgba_to_XImage(dc,im) ) ;  /* 20 Feb 2020 */
60 
61    if( im->kind != MRI_short ){
62      fprintf(stderr,"\n*** ILLEGAL image input to mri_to_XImage\n") ;
63      EXIT(1) ;
64    }
65    sar  = MRI_SHORT_PTR(im) ;
66    ppix = dc->pix_im ;       /* array for positive pixels */
67    npix = dc->ovc->pix_ov ;  /* array for negative pixels */
68 
69    width  = im->nx ;
70    height = im->ny ;
71 
72    w2 = width * dc->byper ;  /* rowlength in bytes */
73 
74    Image = (unsigned char *) XtMalloc( (size_t) (w2*height) );
75 
76    ximage = XCreateImage( dc->display , dc->visual , dc->depth ,
77                           ZPixmap , 0 , (char *)Image , width,height , 8 , w2 );
78 
79    if( ximage == NULL ){
80      fprintf(stderr,"\n*** CANNOT create new XImage for display\n") ;
81      EXIT(1) ;
82    }
83 
84    border = ximage->byte_order ;          /* 22 Aug 1998 */
85 
86    ptr = Image;
87    k   = 0;
88    hw  = height * width ;
89 
90    switch( dc->byper ){
91 
92       case 1:                             /* 1 byte data goes into Image */
93          for( i=0 ; i < hw ; i++ ){
94             sk = sar[k++] ;
95             *ptr++ = (sk >= 0) ? (ppix[sk]  & 0xff)
96                                : (npix[-sk] & 0xff) ;
97          }
98       break ;
99 
100       case 2:                             /* 2 byte data goes into Image */
101          if( border == MSBFirst ){        /* 22 Aug 1998 */
102             for( i=0 ; i < hw ; i++ ){
103                sk = sar[k++] ;
104                if( sk >= 0 ){
105                   *ptr++ = (ppix[sk] >> 8) & 0xff ;  /* MSB */
106                   *ptr++ = (ppix[sk])      & 0xff ;  /* LSB */
107                } else {
108                   *ptr++ = (npix[-sk] >> 8) & 0xff ;
109                   *ptr++ = (npix[-sk])      & 0xff ;
110                }
111             }
112          } else {                          /* LSBFirst */
113             for( i=0 ; i < hw ; i++ ){
114                sk = sar[k++] ;
115                if( sk >= 0 ){
116                   *ptr++ = (ppix[sk])      & 0xff ;  /* LSB */
117                   *ptr++ = (ppix[sk] >> 8) & 0xff ;  /* MSB */
118                } else {
119                   *ptr++ = (npix[-sk])      & 0xff ;
120                   *ptr++ = (npix[-sk] >> 8) & 0xff ;
121                }
122             }
123          }
124       break ;
125 
126       case 3:                            /* 3 & 4 byte data: 22 Aug 1998 */
127          if( border == MSBFirst ){
128             for( i=0 ; i < hw ; i++ ){
129                sk = sar[k++] ;
130                if( sk >= 0 ){
131                   *ptr++ = (ppix[sk] >> 16) & 0xff ;  /* MSB */
132                   *ptr++ = (ppix[sk] >>  8) & 0xff ;
133                   *ptr++ = (ppix[sk])       & 0xff ;  /* LSB */
134                } else {
135                   *ptr++ = (npix[-sk] >> 16) & 0xff ;
136                   *ptr++ = (npix[-sk] >>  8) & 0xff ;
137                   *ptr++ = (npix[-sk])       & 0xff ;
138                }
139             }
140          } else {                          /* LSBFirst */
141             for( i=0 ; i < hw ; i++ ){
142                sk = sar[k++] ;
143                if( sk >= 0 ){
144                   *ptr++ = (ppix[sk])       & 0xff ;  /* LSB */
145                   *ptr++ = (ppix[sk] >>  8) & 0xff ;
146                   *ptr++ = (ppix[sk] >> 16) & 0xff ;  /* MSB */
147                } else {
148                   *ptr++ = (npix[-sk])       & 0xff ;
149                   *ptr++ = (npix[-sk] >>  8) & 0xff ;
150                   *ptr++ = (npix[-sk] >> 16) & 0xff ;
151                }
152             }
153          }
154       break ;
155 
156       case 4:
157          if( border == MSBFirst ){
158             for( i=0 ; i < hw ; i++ ){
159                sk = sar[k++] ;
160                if( sk >= 0 ){
161                   *ptr++ = (ppix[sk] >> 24) & 0xff ;  /* MSB */
162                   *ptr++ = (ppix[sk] >> 16) & 0xff ;
163                   *ptr++ = (ppix[sk] >>  8) & 0xff ;
164                   *ptr++ = (ppix[sk])       & 0xff ;  /* LSB */
165                } else {
166                   *ptr++ = (npix[-sk] >> 24) & 0xff ;
167                   *ptr++ = (npix[-sk] >> 16) & 0xff ;
168                   *ptr++ = (npix[-sk] >>  8) & 0xff ;
169                   *ptr++ = (npix[-sk])       & 0xff ;
170                }
171             }
172          } else {                          /* LSBFirst */
173             for( i=0 ; i < hw ; i++ ){
174                sk = sar[k++] ;
175                if( sk >= 0 ){
176                   *ptr++ = (ppix[sk])       & 0xff ;  /* LSB */
177                   *ptr++ = (ppix[sk] >>  8) & 0xff ;
178                   *ptr++ = (ppix[sk] >> 16) & 0xff ;
179                   *ptr++ = (ppix[sk] >> 24) & 0xff ;  /* MSB */
180                } else {
181                   *ptr++ = (npix[-sk])       & 0xff ;
182                   *ptr++ = (npix[-sk] >>  8) & 0xff ;
183                   *ptr++ = (npix[-sk] >> 16) & 0xff ;
184                   *ptr++ = (npix[-sk] >> 24) & 0xff ;
185                }
186             }
187          }
188       break ;
189 
190       default:
191          fprintf(stderr,
192                  "\n*** ILLEGAL value of display bytes/pix=%d in mri_to_XImage\n",
193                  dc->byper);
194          EXIT(1) ;
195    }
196 
197    RETURN( ximage ) ;
198 }
199 
200 /*--------------------------------------------------------------------------*/
201 /*! - Input:  an XImage of one size
202     - Output: an XImage of another size
203     - method: nearest neighbor resampling
204 ----------------------------------------------------------------------------*/
205 
resize_XImage(MCW_DC * dc,XImage * image,int new_width,int new_height)206 XImage * resize_XImage( MCW_DC *dc , XImage *image ,
207                         int new_width , int new_height )
208 {
209    static int *lt = NULL ;       /* lookup table stuff */
210    static int old_width = -1 ;
211 
212    register int iy, ex, ey, iW, iH, w2 ;
213    char         *ximag;
214    char         *Ep, *El, *Ip, *Il, *Id , *Ed ; /* d=data, l=row, p=pixel */
215    int          Erow , Irow ;
216 
217    XImage *emage ;  /* to be output image */
218 
219    /*** sanity check ***/
220 
221 ENTRY("resize_XImage") ;
222 
223    if( new_width <= 0 || new_height <= 0 ){
224       fprintf(stderr ,
225               "\n***ILLEGAL new width %d or height %d in resize\n",
226               new_width , new_height ) ;
227       EXIT(1) ;
228    }
229 
230    /*** data about input image ***/
231 
232    iW = image->width ;                /* input width and height */
233    iH = image->height ;
234 
235    if( iW == new_width && iH == new_height ){ /* very special case */
236         RETURN( image ) ;
237    }
238 
239    /*** create emage of the appropriate size ***/
240 
241    w2    = new_width * dc->byper ;
242    ximag = (char *) XtMalloc( (size_t) (w2 * new_height) );
243 
244    if( ximag == NULL ){
245       fprintf(stderr,"\n***CANNOT allocate memory for resizing XImage\n") ;
246       EXIT(1) ;
247    }
248 
249    emage = XCreateImage( dc->display , dc->visual , dc->depth ,
250                          ZPixmap, 0, ximag, new_width,new_height, 8, w2 ) ;
251 
252    if( emage == NULL ){
253       fprintf(stderr,"\n*** CANNOT create new XImage for resizing\n") ;
254       EXIT(1) ;
255    }
256 
257    /*** make lookup table for xnew -> xold ***/
258 
259    /*** Notice that this table will never be de-allocated or shrink;
260         it will grow larger when the images grow larger, as needed. ***/
261 
262    if( new_width > old_width ){
263       lt = (int *) XtRealloc( (char *)lt,(size_t)(new_width * sizeof(int)) );
264       old_width = new_width ;
265    }
266 
267    for( ex=0 ; ex < new_width ; ex++ )
268       lt[ex] = MAP_XY(ex,new_width,iW) * dc->byper ;
269 
270    /*** get ready to go ***/
271 
272    Ed = (char *) emage->data ; Erow = emage->bytes_per_line ;
273    Id = (char *) image->data ; Irow = image->bytes_per_line ;
274 
275    switch( dc->byper ){
276 
277       case 1:                                 /* 1 byte per pixel */
278          for( ey=0 ; ey < new_height ; ey++ ){
279 
280             iy = MAP_XY(ey,new_height,iH) ;   /* row index in input image */
281             Il = Id + Irow * iy ;             /* start of that row */
282             El = Ed + Erow * ey ;             /* start of row in output */
283             Ep = El ;
284             for( ex=0 ; ex < new_width ; ex++ ){
285                Ip = Il + lt[ex] ;             /* data pointer in input */
286                *Ep++ = *Ip ;
287             }
288          }
289       break ;
290 
291       case 2:                                 /* 2 bytes per pixel */
292          for( ey=0 ; ey < new_height ; ey++ ){
293 
294             iy = MAP_XY(ey,new_height,iH) ;   /* row index in input image */
295             Il = Id + Irow * iy ;             /* start of that row */
296             El = Ed + Erow * ey ;             /* start of row in output */
297             Ep = El ;
298             for( ex=0 ; ex < new_width ; ex++ ){
299                Ip = Il + lt[ex] ;             /* data pointer in input */
300                *Ep++ = *Ip ;
301                *Ep++ = *(Ip+1) ;
302             }
303          }
304       break ;
305 
306       case 3:                                 /* 3 & 4 added 22 Aug 1998 */
307          for( ey=0 ; ey < new_height ; ey++ ){
308 
309             iy = MAP_XY(ey,new_height,iH) ;   /* row index in input image */
310             Il = Id + Irow * iy ;             /* start of that row */
311             El = Ed + Erow * ey ;             /* start of row in output */
312             Ep = El ;
313             for( ex=0 ; ex < new_width ; ex++ ){
314                Ip = Il + lt[ex] ;             /* data pointer in input */
315                *Ep++ = *Ip ;
316                *Ep++ = *(Ip+1) ;
317                *Ep++ = *(Ip+2) ;
318             }
319          }
320       break ;
321 
322       case 4:
323          for( ey=0 ; ey < new_height ; ey++ ){
324 
325             iy = MAP_XY(ey,new_height,iH) ;   /* row index in input image */
326             Il = Id + Irow * iy ;             /* start of that row */
327             El = Ed + Erow * ey ;             /* start of row in output */
328             Ep = El ;
329             for( ex=0 ; ex < new_width ; ex++ ){
330                Ip = Il + lt[ex] ;             /* data pointer in input */
331                *Ep++ = *Ip ;
332                *Ep++ = *(Ip+1) ;
333                *Ep++ = *(Ip+2) ;
334                *Ep++ = *(Ip+3) ;
335             }
336          }
337       break ;
338 
339       default:
340          fprintf(stderr,"\n***ILLEGAL bytes/pix=%d for resizing\n",dc->byper) ;
341          EXIT(1) ;
342    }
343 
344    RETURN( emage ) ;
345 }
346 
347 /*---------------------------------------------------------------------------*/
348 /*! - input  = XImage (with Pixel values from dc)
349     - output = RGB or Grayscale image
350     - code   = mask of values indicating optional processing:
351 
352           - (code & X2M_USE_CMAP) != 0 means use the entire colormap
353                                   == 0 means use only Pixels in dc
354 
355           - (code & X2M_FORCE_RGB)!= 0 means output is always RGB format
356                                   == 0 means output might be byte format
357                                        (grayscale) if all pixels are gray
358 -----------------------------------------------------------------------------*/
359 
XImage_to_mri(MCW_DC * dc,XImage * ximage,int code)360 MRI_IMAGE * XImage_to_mri( MCW_DC *dc , XImage *ximage , int code )
361 {
362    int nx , ny , npix , ii,jj , kk , allgray , lsize ;
363    Pixel pp ;
364    byte *rgb , *gray ;
365    byte rr,gg,bb ;
366    byte *ptr ;
367    XColor *xc ;
368    MRI_IMAGE *outim ;
369    int  border ;        /* 22 Aug 1998 */
370 
371    int use_cmap  = ((code & X2M_USE_CMAP ) != 0) ;  /* 03 Apr 2001 */
372    int force_rgb = ((code & X2M_FORCE_RGB) != 0) ;
373 
374 ENTRY("XImage_to_mri") ;
375 
376    if( ximage == NULL || ximage->data == NULL ) RETURN( NULL ) ;
377 
378 #if 0
379 fprintf(stderr,
380         "XImage bitmap_unit   =%3d  bitmap_pad=%3d  depth =%3d\n"
381         "       bytes_per_line=%3d  width     =%3d  height=%3d\n"
382         "       bits_per_pixel=%3d  xoffset   =%3d\n" ,
383  ximage->bitmap_unit    , ximage->bitmap_pad , ximage->depth ,
384  ximage->bytes_per_line , ximage->width      , ximage->height ,
385  ximage->bits_per_pixel , ximage->xoffset ) ;
386 #endif
387 
388    nx = ximage->width ; ny = ximage->height ; npix = nx * ny ;
389 
390    lsize = ximage->bytes_per_line ;
391 
392    ptr = (byte *) ximage->data ;        /* pointer to pixels */
393 
394    rgb = (byte *) malloc( sizeof(byte) * 3*npix ) ;
395    if( rgb == NULL ){
396       fprintf(stderr,"\n*** malloc failure in XImage_to_mri\n") ;
397       EXIT(1) ;
398    }
399 
400    border = ximage->byte_order ;           /* 22 Aug 1998 */
401 
402    switch( dc->byper ){
403 
404       case 1:                              /* 1 byte per pixel */
405          kk = 0 ; allgray = !force_rgb ;
406          for( jj=0 ; jj < ny ; jj++ ){
407             for( ii=0 ; ii < nx ; ii++ ){
408                pp = ptr[ii+jj*lsize] ;                       /* pixel value */
409                xc = DCpix_to_XColor( dc , pp , use_cmap ) ;  /* XColor */
410                rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
411                gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
412                bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
413                allgray = allgray && (rr==gg) && (gg=bb) ;
414             }
415          }
416       break ;
417 
418       case 2:                               /* 2 bytes per pixel */
419          kk = 0 ; allgray = !force_rgb ;
420          for( jj=0 ; jj < ny ; jj++ ){
421             for( ii=0 ; ii < nx ; ii++ ){
422                if( border == MSBFirst )
423                   pp = (ptr[2*ii+jj*lsize]   << 8) | ptr[2*ii+jj*lsize+1] ;
424                else
425                   pp = (ptr[2*ii+jj*lsize+1] << 8) | ptr[2*ii+jj*lsize] ;
426 
427                xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
428                rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
429                gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
430                bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
431                allgray = allgray && (rr==gg) && (gg=bb) ;
432             }
433          }
434       break ;
435 
436       case 3:                               /* 3 & 4 added 22 Aug 1998 */
437          kk = 0 ; allgray = !force_rgb ;
438          for( jj=0 ; jj < ny ; jj++ ){
439             for( ii=0 ; ii < nx ; ii++ ){
440                if( border == MSBFirst )
441                   pp = (ptr[3*ii+jj*lsize]   << 16) |
442                        (ptr[3*ii+jj*lsize+1] <<  8) | ptr[3*ii+jj*lsize+2] ;
443                else
444                   pp = (ptr[3*ii+jj*lsize+2] << 16) |
445                        (ptr[3*ii+jj*lsize+1] <<  8) | ptr[3*ii+jj*lsize] ;
446 
447                xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
448                rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
449                gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
450                bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
451                allgray = allgray && (rr==gg) && (gg=bb) ;
452             }
453          }
454       break ;
455 
456       case 4:
457          kk = 0 ; allgray = !force_rgb ;
458          for( jj=0 ; jj < ny ; jj++ ){
459             for( ii=0 ; ii < nx ; ii++ ){
460                if( border == MSBFirst )
461                   pp = (ptr[4*ii+jj*lsize]   << 24) | (ptr[4*ii+jj*lsize+1] << 16) |
462                        (ptr[4*ii+jj*lsize+2] <<  8) |  ptr[4*ii+jj*lsize+3] ;
463                else
464                   pp = (ptr[4*ii+jj*lsize+3] << 24) | (ptr[4*ii+jj*lsize+2] << 16) |
465                        (ptr[4*ii+jj*lsize+1] <<  8) |  ptr[4*ii+jj*lsize] ;
466 
467                xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
468                rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
469                gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
470                bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
471                allgray = allgray && (rr==gg) && (gg=bb) ;
472             }
473          }
474       break ;
475 
476       default:
477          fprintf(stderr,
478                  "\n*** ILLEGAL value of bytes/pix=%d in XImage_to_mri\n",
479                  dc->byper);
480          EXIT(1) ;
481    }
482 
483    /*** if all pixels are gray, return a grayscale image ***/
484 
485    if( allgray ){
486 
487       gray = (byte *) malloc( sizeof(byte) * npix ) ;
488       if( gray == NULL ){
489          fprintf(stderr,"\n*** malloc failure in XImage_to_mri\n") ;
490          EXIT(1) ;
491       }
492       for( ii=0 , kk=0 ; ii < npix ; ii++ , kk+=3) gray[ii] = rgb[kk] ;
493       free(rgb) ;
494       outim = mri_new_vol_empty( nx , ny , 1 , MRI_byte ) ;
495       mri_fix_data_pointer( gray , outim ) ;
496 
497    } else {
498 
499    /*** not all gray --> return color RGB image ***/
500 
501       outim = mri_new_vol_empty( nx , ny , 1 , MRI_rgb ) ;
502       mri_fix_data_pointer( rgb , outim ) ;
503    }
504 
505    RETURN( outim ) ;
506 }
507 
508 /*-----------------------------------------------------------------------*/
509 /*  Convert an array of X11 Pixel values to an XImage for display.
510     Adapted from mri_to_XImage by RWCox -- 11 Feb 1999
511 -------------------------------------------------------------------------*/
512 
pixar_to_XImage(MCW_DC * dc,int nx,int ny,Pixel * par)513 XImage * pixar_to_XImage( MCW_DC *dc, int nx, int ny, Pixel *par )
514 {
515    int  w2, width, height , border ;
516    unsigned char *Image ;
517    XImage        *ximage ;
518    register int i , hw  ;
519    register unsigned char *ptr;
520 
521    /*-- sanity checks --*/
522 
523 ENTRY("pixar_to_XImage") ;
524 
525    if( dc == NULL || nx < 1 || ny < 1 || par == NULL ) RETURN( NULL ) ;
526 
527    width = nx ; height = ny ;
528 
529    w2 = width * dc->byper ;  /* rowlength in bytes */
530 
531    Image = (unsigned char *) XtMalloc( (size_t) (w2*height) );
532    if( Image == NULL ) RETURN( NULL ) ;
533 
534    ximage = XCreateImage( dc->display , dc->visual , dc->depth ,
535                           ZPixmap , 0 , (char *)Image , width,height , 8 , w2 );
536    if( ximage == NULL ){ XtFree((char *)Image) ; RETURN( NULL ) ; }
537 
538    border = ximage->byte_order ;  /* byte order */
539 
540    ptr = Image ;                  /* pointer to image bytes */
541    hw  = height * width ;         /* total number of pixels */
542 
543    switch( dc->byper ){           /* load data into Image */
544 
545       case 1:                             /* 1 byte data goes into Image */
546          for( i=0 ; i < hw ; i++ ){
547             *ptr++ = par[i] & 0xff ;
548          }
549       break ;
550 
551       case 2:                             /* 2 byte data goes into Image */
552          if( border == MSBFirst ){
553             for( i=0 ; i < hw ; i++ ){
554                *ptr++ = (par[i] >> 8) & 0xff ;  /* MSB */
555                *ptr++ = (par[i]     ) & 0xff ;  /* LSB */
556             }
557          } else {                          /* LSBFirst */
558             for( i=0 ; i < hw ; i++ ){
559                *ptr++ = (par[i]     ) & 0xff ;  /* LSB */
560                *ptr++ = (par[i] >> 8) & 0xff ;  /* MSB */
561             }
562          }
563       break ;
564 
565       case 3:                            /* 3 byte data */
566          if( border == MSBFirst ){
567             for( i=0 ; i < hw ; i++ ){
568                *ptr++ = (par[i] >> 16) & 0xff ;  /* MSB */
569                *ptr++ = (par[i] >>  8) & 0xff ;
570                *ptr++ = (par[i]      ) & 0xff ;  /* LSB */
571             }
572          } else {                           /* LSBFirst */
573             for( i=0 ; i < hw ; i++ ){
574                *ptr++ = (par[i]      ) & 0xff ;  /* LSB */
575                *ptr++ = (par[i] >>  8) & 0xff ;
576                *ptr++ = (par[i] >> 16) & 0xff ;  /* MSB */
577             }
578          }
579       break ;
580 
581       case 4:                            /* 4 byte data */
582          if( border == MSBFirst ){
583             for( i=0 ; i < hw ; i++ ){
584                *ptr++ = (par[i] >> 24) & 0xff ;  /* MSB */
585                *ptr++ = (par[i] >> 16) & 0xff ;
586                *ptr++ = (par[i] >>  8) & 0xff ;
587                *ptr++ = (par[i]      ) & 0xff ;  /* LSB */
588             }
589          } else {                           /* LSBFirst */
590             for( i=0 ; i < hw ; i++ ){
591                *ptr++ = (par[i]      ) & 0xff ;  /* LSB */
592                *ptr++ = (par[i] >>  8) & 0xff ;
593                *ptr++ = (par[i] >> 16) & 0xff ;
594                *ptr++ = (par[i] >> 24) & 0xff ;  /* MSB */
595             }
596          }
597       break ;
598 
599       default:
600          fprintf(stderr,
601                  "\n*** ILLEGAL value of display bytes/pix=%d in pixar_to_XImage\n",
602                  dc->byper);
603          EXIT(1) ;
604    }
605 
606    RETURN( ximage ) ;
607 }
608 
609 /*-------------------------------------------------------------------*/
610 #undef INLINE
611 #ifdef __GNUC__
612 # define INLINE inline
613 #else
614 # define INLINE /*nada*/
615 #endif
616 /*-----------------------------------------------------------------------*/
617 /*! Local copy of function from display.c, hopefully for speed.
618     This function converts the color (rr,gg,bb) byte triple to
619     an X11 Pixel for the given TrueColor (tc) display,
620     whose properties are stored in the MCW_DC (cf. display.c).
621 *//*---------------------------------------------------------------------*/
622 
tc_rgb_to_pixel(MCW_DC * dc,byte rr,byte gg,byte bb)623 static INLINE Pixel tc_rgb_to_pixel( MCW_DC *dc, byte rr, byte gg, byte bb )
624 {
625    static MCW_DC *dcold=NULL ;
626    DC_colordef *cd = dc->cdef ;
627    static unsigned long pold=0 ;
628    static byte rold=0 , gold=0 , bold=0 ;
629    unsigned long r , g , b ;
630 
631    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
632 
633    if( rr == 0   && gg == 0   && bb == 0   ) return 0 ;          /* common */
634    if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ;  /* cases  */
635 
636    if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
637      return (Pixel) pold ;
638 
639    rold = rr ; gold = gg ; bold = bb ; dcold = dc ;            /* OK, remember for next time */
640 
641    /* X11 TrueColor (tc) is very general,
642         which makes the code below slightly mysterious.
643       Each color component (r,g,b) gets certain bit locations in a
644         Pixel = unsigned long = 32 bits
645       So given byte rr (say), it has to be shifted left or right to the
646         correct location in the Pixel and then masked off to make sure the
647         bits set don't stray outside their allotted space.
648       That's what the next line of code does, producing the Pixel for the
649         red color only.
650       The shifts and masks are set in the MCW_DC struct, in display.c, and
651         are obtained from the X11 XVisualInfo for the X11 Display being used. */
652 
653    r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
654                        : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
655 
656    g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
657                        : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
658 
659    b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
660                        : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
661 
662    pold = r | g | b ;  /* assemble color from components */
663    return (Pixel)pold ;
664 }
665 
666 /*----------------------------------------------------------------------------*/
667 
668 static XImage * rgb_to_XImage_simple( MCW_DC *, MRI_IMAGE * ) ;
669 static XImage * rgb_to_XImage_clever( MCW_DC *, MRI_IMAGE * ) ;
670 
671 /*----------------------------------------------------------------------------*/
672 /*! Convert an MRI_IMAGE of rgb values to an XImage for display.
673 ------------------------------------------------------------------------------*/
674 
rgb_to_XImage(MCW_DC * dc,MRI_IMAGE * im)675 XImage * rgb_to_XImage( MCW_DC *dc , MRI_IMAGE *im )
676 {
677    switch( dc->visual_class ){
678     case TrueColor:   return rgb_to_XImage_simple(dc,im) ;
679     case PseudoColor: return rgb_to_XImage_clever(dc,im) ;
680    }
681    return NULL ;
682 }
683 
684 /*----------------------------------------------------------------------------*/
685 
rgba_to_XImage(MCW_DC * dc,MRI_IMAGE * im)686 XImage * rgba_to_XImage( MCW_DC *dc , MRI_IMAGE *im ) /* 13 Feb 2020 */
687 {
688    MRI_IMAGE *qim = mri_to_rgb(im) ;                  /* brute force */
689    XImage    *pim = rgb_to_XImage( dc , qim ) ;
690    mri_free(qim) ;
691    return pim ;
692 }
693 
694 /*----------------------------------------------------------------------------*/
695 /*! Convert an MRI_IMAGE of rgb bytes to an XImage (TrueColor visual only)
696 ------------------------------------------------------------------------------*/
697 
rgb_to_XImage_simple(MCW_DC * dc,MRI_IMAGE * im)698 static XImage * rgb_to_XImage_simple( MCW_DC *dc , MRI_IMAGE *im )
699 {
700    int nxy , ii ;
701    byte *rgb ;
702    Pixel *par ;
703    XImage *xim ;
704 
705 ENTRY("rgb_to_XImage_simple") ;
706 
707    /*-- sanity check --*/
708 
709    if( dc == NULL || im == NULL || im->kind != MRI_rgb ) RETURN( NULL ) ;
710 
711    nxy = im->nx * im->ny ;
712    rgb = MRI_RGB_PTR(im) ;
713 
714    par = (Pixel *) malloc(sizeof(Pixel)*nxy); if( par == NULL ) RETURN(NULL) ;
715 
716    /* convert each RGB triple to an X11 Pixel */
717 
718    for( ii=0 ; ii < nxy ; ii++ )
719      par[ii] = tc_rgb_to_pixel( dc , rgb[3*ii], rgb[3*ii+1], rgb[3*ii+2] ) ;
720 
721    /* convert the Pixel array to an XImage,
722       which can be pushed to a window for actual visibility */
723 
724    xim = pixar_to_XImage( dc , im->nx , im->ny , par ) ;
725 
726    /* toss the Pixel array and return the XImage */
727 
728    free(par) ; RETURN( xim ) ;
729 }
730 
731 /*-----------------------------------------------------------------------*/
732 /*! Convert an MRI_IMAGE of rgb bytes to an XImage (general visual).
733     Here, "clever" means that the colors in the image are sorted
734     to bring identical colors together, so that the number of
735     distinct conversions from RGB triples to Pixels is minimized.
736     Although this function works with TrueColor, it is slower than the
737     "simple" function above - due to the sorting overhead.
738     But this function is faster for PseudoColor, as the sorting
739     overhead is less than the PseudoColor RGB->Pixel conversion cost.
740 -------------------------------------------------------------------------*/
741 
rgb_to_XImage_clever(MCW_DC * dc,MRI_IMAGE * im)742 static XImage * rgb_to_XImage_clever( MCW_DC *dc , MRI_IMAGE *im )
743 {
744    int nxy , ii , c ;
745    byte *rgb , r,g,b ;
746    Pixel *par , p=0 ;
747    XImage *xim ;
748    int *col_ar , *ii_ar ;
749 
750 ENTRY("rgb_to_XImage_clever") ;
751 
752    /*-- sanity check --*/
753 
754    if( dc == NULL || im == NULL || im->kind != MRI_rgb ) RETURN( NULL ) ;
755 
756    nxy = im->nx * im->ny ;
757    rgb = MRI_RGB_PTR(im) ;
758 
759    col_ar = (int *)  malloc( sizeof(int)   * nxy ) ;
760    ii_ar  = (int *)  malloc( sizeof(int)   * nxy ) ;
761    par    = (Pixel *)malloc( sizeof(Pixel) * nxy ) ;
762 
763    if( col_ar == NULL )                             RETURN( NULL );
764    if( ii_ar  == NULL ){ free(col_ar);              RETURN( NULL ); }
765    if( par    == NULL ){ free(col_ar); free(ii_ar); RETURN( NULL ); }
766 
767    for( ii=0 ; ii < nxy ; ii++ ){  /* convert RGB triples to ints */
768       ii_ar[ii]  = ii ;            /* and save original location  */
769       col_ar[ii] = rgb[3*ii] << 16 | rgb[3*ii+1] << 8 | rgb[3*ii+2] ;
770    }
771 
772    qsort_intint( nxy , col_ar , ii_ar ) ; /* sort to bring like colors together */
773 
774    c = -1 ; /* a color that can't occur */
775 
776    for( ii=0 ; ii < nxy ; ii++ ){
777       if( col_ar[ii] != c ){         /* have a new color, so compute its pixel */
778          c = col_ar[ii] ;
779          r = (c >> 16) & 0xff ; g = (c >> 8) & 0xff ; b = c & 0xff ;
780          p = DC_rgb_to_pixel( dc , r,g,b ) ; /* in display.c */
781       }
782       par[ii_ar[ii]] = p ;           /* store it where it came from */
783    }
784 
785    free(col_ar) ; free(ii_ar) ;      /* toss some trash */
786 
787    /* convert Pixel array to an XImage, for actual display to X11 */
788 
789    xim = pixar_to_XImage( dc , im->nx , im->ny , par ) ;
790 
791    free(par) ; RETURN( xim ) ;
792 }
793 
794 /*--------------------------------------------------------------------------*/
795 /* Fill a rectangle with zeroes (black) in an XImage [25 Jun 2013]. */
796 /*--------------------------------------------------------------------------*/
797 
rectzero_XImage(MCW_DC * dc,XImage * image,int x1,int y1,int x2,int y2)798 void rectzero_XImage( MCW_DC *dc , XImage *image ,
799                       int x1, int y1, int x2, int y2 )
800 {
801    int jj , iW , iH , iR ;
802    size_t bx ;
803    char *iD , *jL ;
804 
805 ENTRY("rectzero_XImage") ;
806 
807    if( dc == NULL || image == NULL ) EXRETURN ;
808 
809    iW = image->width ; iH = image->height ;
810 
811    /* munge so that rect limits are reasonable */
812 
813    if( x1 <   0 && x2 <   0 ) EXRETURN ;  /* outside the image? */
814    if( y1 <   0 && y2 <   0 ) EXRETURN ;
815    if( x1 >= iW && x2 >= iW ) EXRETURN ;
816    if( y1 >= iH && y2 >= iH ) EXRETURN ;
817 
818    if( x1 <   0 ) x1 = 0    ; if( x2 < 0   ) x2 = 0    ;
819    if( x1 >= iW ) x1 = iW-1 ; if( x2 >= iW ) x2 = iW-1 ;
820    if( x1 >  x2 ){ jj = x1 ; x1 = x2 ; x2 = jj ; }
821 
822    if( y1 <   0 ) y1 = 0    ; if( y2 < 0   ) y2 = 0    ;
823    if( y1 >= iH ) y1 = iH-1 ; if( y2 >= iH ) y2 = iW-1 ;
824    if( y1 >  y2 ){ jj = y1 ; y1 = y2 ; y2 = jj ; }
825 
826    iD = (char *)image->data ;     /* data inside image */
827    iR = image->bytes_per_line ;   /* number of bytes in an image row */
828    bx = (x2-x1+1)*dc->byper ;     /* number of bytes to zero in one row */
829 
830    for( jj=y1 ; jj <= y2 ; jj++ ){
831      jL = iD + iR * jj ;                 /* ptr to image data in jj-th row */
832      memset( jL + x1*dc->byper , 0 , bx ) ;
833    }
834 
835    EXRETURN ;
836 }
837 
838 /**************************************************************************/
839 /********** 26 Jun 2003: stuff for snapping a Widget to an image **********/
840 
841 static int     badsnap = 0 ;
842 static MCW_DC *snap_dc = NULL ;
843 
844 /*! X11 error handler for when XGetImage fails. */
845 
SNAP_errhandler(Display * d,XErrorEvent * x)846 static int SNAP_errhandler( Display *d , XErrorEvent *x )
847 {
848   fprintf(stderr,"** X11 error trying to snapshot window!\n");
849   badsnap = 1 ; return 0 ;
850 }
851 
852 /*--------------------------------------------------------------*/
853 /*! Grab the image from a widget's window.  [20 Jun 2003]
854 ----------------------------------------------------------------*/
855 
SNAP_grab_image(Widget w,MCW_DC * dc)856 MRI_IMAGE * SNAP_grab_image( Widget w , MCW_DC *dc )
857 {
858    XImage * xim ;
859    MRI_IMAGE * tim ;
860    Window win ;
861    Widget wpar=w ;
862    XWindowAttributes wa ;
863    int (*old_handler)(Display *, XErrorEvent *) ;
864 
865 ENTRY("SNAP_grab_image") ;
866 
867    if( dc == NULL )                          RETURN(NULL) ;
868 
869    if( w == NULL ){
870      win = RootWindow( dc->display , dc->screen_num ) ;
871    } else {
872      if( !XtIsWidget(w)   ||
873          !XtIsRealized(w) ||
874          !XtIsManaged(w)    )                RETURN(NULL) ;
875      win = XtWindow(w) ;
876      if( win == (Window)0 )                  RETURN(NULL) ;
877 
878      while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ;  /* find top */
879 
880      /*** Raise the window and SUMA will redisplay
881           entering an infernal loop. ZSS Mon Jun 30/03 ***/
882 #if 0
883      XRaiseWindow( dc->display , XtWindow(wpar) ) ;    /* make it visible */
884 #endif
885      XFlush( dc->display ) ;
886      XmUpdateDisplay( w ) ;
887      if( !MCW_widget_visible(w) )            RETURN(NULL) ;
888    }
889 
890    RWC_sleep(20) ;                                       /* allow refresh */
891    XGetWindowAttributes( dc->display , win , &wa ) ;      /* get win size */
892    xim = NULL ; badsnap = 0 ;
893    old_handler = XSetErrorHandler( SNAP_errhandler ) ;
894    xim = XGetImage( dc->display , win ,
895                     0,0 , wa.width,wa.height,
896                     (unsigned long)(-1), ZPixmap ) ;
897    (void) XSetErrorHandler( old_handler ) ;
898    if( badsnap ){
899      if( xim != NULL ) MCW_kill_XImage(xim) ;
900      RETURN(NULL) ;
901    }
902    if( xim == NULL ) RETURN(NULL) ;
903 
904    tim = XImage_to_mri( dc , xim , X2M_USE_CMAP | X2M_FORCE_RGB ) ;
905    MCW_kill_XImage(xim) ;
906    RETURN(tim) ;
907 }
908 
909 /*----------------------------------------------------------------------*/
910 /*! Call this function to get a snapshot of a widget and save
911     it into a PPM file. See also ISQ_snapfile2()
912 ------------------------------------------------------------------------*/
913 
ISQ_snapfile(Widget w)914 int ISQ_snapfile( Widget w )
915 {
916    MRI_IMAGE *tim ;
917    Window win ;
918    char fname[64] , *eee , prefix[32] ;
919    int ii ; static int last_ii=1 ;
920 
921 ENTRY("ISQ_snapfile") ;
922 
923    if( w == NULL || !XtIsWidget(w) )         RETURN(-1) ;
924    if( !XtIsRealized(w) || !XtIsManaged(w) ) RETURN(-1) ;
925    win = XtWindow(w); if( win == (Window)0 ) RETURN(-1) ;
926 
927    /* create display context if we don't have one */
928 
929    if( snap_dc == NULL ){
930      if( first_dc != NULL ) snap_dc = first_dc ;
931      else                   snap_dc = MCW_new_DC( w, 4,0, NULL,NULL, 1.0,0 );
932    }
933 
934    /* try to get image */
935 
936    tim = SNAP_grab_image( w , snap_dc ) ;
937    if( tim == NULL )                         RETURN(-1) ;
938 
939    eee = getenv("AFNI_SNAPFILE_PREFIX") ;
940    if( eee == NULL ){
941      strcpy(prefix,"S_") ;
942    } else {
943      strncpy(prefix,eee,30) ; prefix[30] = '\0' ; strcat(prefix,"_") ;
944      if( !THD_filename_ok(prefix) ) strcpy(prefix,"S_") ;
945    }
946    for( ii=last_ii ; ii <= 999999 ; ii++ ){
947      sprintf(fname,"%s%06d.ppm",prefix,ii) ;
948      if( ! THD_is_ondisk(fname) ) break ;
949    }
950    if( ii <= 999999 ) mri_write_pnm( fname , tim ) ;
951    mri_free(tim) ; last_ii = ii ;
952    RETURN(0) ;
953 }
954 
955 /*------------------------------------------------------*/
956 /* A variant on ISQ_snapfile that allows direct control
957    of filename                                          */
958 /*------------------------------------------------------*/
959 
ISQ_snapfile2(Widget w,char * fout)960 int ISQ_snapfile2( Widget w , char *fout)
961 {
962    MRI_IMAGE *tim ;
963    Window win ;
964    char fname[64] , *eee , prefix[32] ;
965    int ii ; static int last_ii=1 ;
966 
967 ENTRY("ISQ_snapfile2") ;
968 
969    if( w == NULL || !XtIsWidget(w) ) {
970       ERROR_message("ISQ_snapfile2: %p is not a valid widget", w);
971       RETURN(-1) ;
972    }
973    if( !XtIsRealized(w) ){
974      ERROR_message("ISQ_snapfile2: widget not realized") ;
975      RETURN(-1) ;
976    }
977    if( !XtIsManaged(w) ){
978      ERROR_message("ISQ_snapfile2: widget not managed") ;
979      RETURN(-1) ;
980    }
981    win = XtWindow(w); if( win == (Window)0 ) {
982       ERROR_message("ISQ_snapfile2: widget doesn't have a window :(") ;
983       RETURN(-1) ;
984    }
985 
986    /* create display context if we don't have one */
987 
988    if( snap_dc == NULL ){
989      if( first_dc != NULL ) snap_dc = first_dc ;
990      else                   snap_dc = MCW_new_DC( w, 4,0, NULL,NULL, 1.0,0 );
991    }
992 
993    /* try to get image */
994 
995    tim = SNAP_grab_image( w , snap_dc ) ;
996    if( tim == NULL ) {
997       ERROR_message("ISQ_snapfile2: Failed to grab image");
998       RETURN(-1) ;
999    }
1000    if (!fout) {
1001       eee = getenv("AFNI_SNAPFILE_PREFIX") ;
1002       if( eee == NULL ){
1003          strcpy(prefix,"S_") ;
1004       } else {
1005          strncpy(prefix,eee,30) ; prefix[30] = '\0' ; strcat(prefix,"_") ;
1006          if( !THD_filename_ok(prefix) ) strcpy(prefix,"S_") ;
1007       }
1008       for( ii=last_ii ; ii <= 999999 ; ii++ ){
1009          sprintf(fname,"%s%06d.ppm",prefix,ii) ;
1010          if( ! THD_is_ondisk(fname) ) break ;
1011       }
1012       if( ii <= 999999 ){
1013         INFO_message("snapping PNM image %s",fname) ;
1014         mri_write_pnm( fname , tim ) ;
1015       }
1016       last_ii = ii ;
1017    } else {
1018              if (STRING_HAS_SUFFIX(fout, ".jpg")) {
1019          INFO_message("snapping jpg image %s",fout) ;
1020          mri_write_jpg( fout , tim ) ;
1021       } else if (STRING_HAS_SUFFIX(fout, ".pnm")) {
1022          INFO_message("snapping png image %s",fout) ;
1023          mri_write_pnm( fout , tim ) ;
1024       } else if (STRING_HAS_SUFFIX(fout, ".png")) {
1025          INFO_message("snapping png image %s",fout) ;
1026          mri_write_png( fout , tim ) ;
1027       } else if (STRING_HAS_SUFFIX(fout, ".1D")) {
1028          INFO_message("snapping 1D file %s",fout) ;
1029          mri_write_1D( fout , tim ) ;
1030       } else {
1031          snprintf(fname,59,"%s", fout);
1032          strcat(fname,".jpg");
1033          WARNING_message(
1034            "ISQ_snapfile2: Format not recognized, saving in jpg format to %s",
1035            fname ) ;
1036          mri_write_jpg( fname , tim ) ;
1037       }
1038    }
1039    mri_free(tim) ;
1040    RETURN(0) ;
1041 }
1042 
1043 /*-----------------------------------------------------------------------*/
1044 static MCW_DC       *cur_dc  = NULL ;
1045 static Display      *cur_dpy = NULL ;
1046 static Window        cur_w   = (Window)0 ;
1047 static GC            cur_GC ;
1048 static XGCValues     cur_gcv ;
1049 
memplot_to_X11_set_DC(MCW_DC * dc)1050 void memplot_to_X11_set_DC( MCW_DC *dc ){ cur_dc = dc ; return ; }
1051 
1052 /* function to plot a coxplot MEM_plotdata struct (set of lines)
1053    directly into an X11 window -- probably is not used anywhere?
1054    -- OK, it actually IS used, via macro X11_SET_NEW_PLOT, in several codes */
1055 
memplot_to_X11_funfunfun(Display * dpy,Window w,MEM_plotdata * mp,int start,int end,int mask)1056 void memplot_to_X11_funfunfun( Display *dpy , Window w , MEM_plotdata *mp ,
1057                                int start , int end , int mask )
1058 {
1059    MRI_IMAGE *im ; byte *imp ;
1060    int nx=0 , ny=0 , did_dup=0 ;
1061    XImage *xim ;
1062 
1063    if( cur_dpy != dpy ){
1064      cur_gcv.function   = GXcopy ;
1065      cur_gcv.fill_style = FillSolid ;
1066      cur_GC             = XCreateGC( dpy , w , GCFunction|GCFillStyle , &cur_gcv ) ;
1067      cur_dpy            = dpy ;
1068    }
1069    cur_w = getwin_from_XDBE(dpy,w) ;
1070 
1071    drawable_geom( dpy,cur_w , &nx,&ny,NULL ) ;
1072 /* INFO_message("memplot_to_X11_funfunfun: nx=%d ny=%d",nx,ny) ; */
1073    if( nx < 19 || ny < 19 ) return ;
1074 
1075    if( nx < 2048 && ny < 2048 ){ nx *= 2; ny *= 2; did_dup = 1; }
1076 
1077    im  = mri_new( nx , ny , MRI_rgb ) ;
1078    imp = MRI_RGB_PTR(im) ; memset( imp , 255 , 3*nx*ny ) ; /* white-ize */
1079    set_memplot_RGB_box(0,0,0,0) ;
1080    memplot_to_mri_set_dothick(1) ;
1081    memplot_to_RGB_sef( im , mp , 0 , 0 , 1 ) ;
1082    memplot_to_mri_set_dothick(0) ;
1083    if( did_dup ){
1084      MRI_IMAGE *qim = mri_downsize_by2(im) ; mri_free(im) ; im = qim ;
1085    }
1086 
1087    xim = rgb_to_XImage( cur_dc , im ) ; mri_free(im) ;
1088    XPutImage( dpy , w , cur_GC , xim , 0,0,0,0 , xim->width , xim->height ) ;
1089    MCW_kill_XImage(xim) ;
1090    return ;
1091 }
1092