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