/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#include "xim.h"
#include "xutil.h"
/*********************************************************************/
/***** 22 Aug 1998: modified to allow for 3 and 4 byte visuals, *****/
/***** and for either possible byte order -- RW Cox *****/
/***** *****/
/***** 11 Feb 1999: added ability to deal with MRI_rgb images *****/
/*********************************************************************/
/*------------------------------------------------------------------------*/
/*! Free an XImage created by mri_to_XImage() or its kin.
--------------------------------------------------------------------------*/
void MCW_kill_XImage( XImage *image )
{
ENTRY("MCW_kill_XImage") ;
if( image != NULL ){
if( image->data != NULL ){
XtFree( image->data ) ; image->data = NULL ;
}
XDestroyImage( image ) ;
}
EXRETURN ;
}
/*-------------------------------------------------------------------------*/
/*! Create an XImage from an MRI_IMAGE of shorts or rgbs:
- values >= 0 draw from the "image" palette
- values < 0 draw from the "overlay" palette (stored in dc)
---------------------------------------------------------------------------*/
XImage * mri_to_XImage( MCW_DC *dc , MRI_IMAGE *im )
{
int w2, width, height ;
unsigned char *Image;
XImage *ximage;
int border ; /* 22 Aug 1998 */
register int i , hw , sk , k ;
register short *sar ;
register Pixel *ppix , *npix ;
register unsigned char *ptr;
ENTRY("mri_to_XImage") ;
if( im->kind == MRI_rgb ) RETURN( rgb_to_XImage(dc,im) ) ; /* 11 Feb 1999 */
if( im->kind != MRI_short ){
fprintf(stderr,"\n*** ILLEGAL image input to mri_to_XImage\n") ;
EXIT(1) ;
}
sar = MRI_SHORT_PTR(im) ;
ppix = dc->pix_im ; /* array for positive pixels */
npix = dc->ovc->pix_ov ; /* array for negative pixels */
width = im->nx ;
height = im->ny ;
w2 = width * dc->byper ; /* rowlength in bytes */
Image = (unsigned char *) XtMalloc( (size_t) (w2*height) );
ximage = XCreateImage( dc->display , dc->visual , dc->depth ,
ZPixmap , 0 , Image , width,height , 8 , w2 ) ;
if( ximage == NULL ){
fprintf(stderr,"\n*** CANNOT create new XImage for display\n") ;
EXIT(1) ;
}
border = ximage->byte_order ; /* 22 Aug 1998 */
ptr = Image;
k = 0;
hw = height * width ;
switch( dc->byper ){
case 1: /* 1 byte data goes into Image */
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
*ptr++ = (sk >= 0) ? (ppix[sk] & 0xff)
: (npix[-sk] & 0xff) ;
}
break ;
case 2: /* 2 byte data goes into Image */
if( border == MSBFirst ){ /* 22 Aug 1998 */
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk] >> 8) & 0xff ; /* MSB */
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
} else {
*ptr++ = (npix[-sk] >> 8) & 0xff ;
*ptr++ = (npix[-sk]) & 0xff ;
}
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
*ptr++ = (ppix[sk] >> 8) & 0xff ; /* MSB */
} else {
*ptr++ = (npix[-sk]) & 0xff ;
*ptr++ = (npix[-sk] >> 8) & 0xff ;
}
}
}
break ;
case 3: /* 3 & 4 byte data: 22 Aug 1998 */
if( border == MSBFirst ){
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk] >> 16) & 0xff ; /* MSB */
*ptr++ = (ppix[sk] >> 8) & 0xff ;
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
} else {
*ptr++ = (npix[-sk] >> 16) & 0xff ;
*ptr++ = (npix[-sk] >> 8) & 0xff ;
*ptr++ = (npix[-sk]) & 0xff ;
}
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
*ptr++ = (ppix[sk] >> 8) & 0xff ;
*ptr++ = (ppix[sk] >> 16) & 0xff ; /* MSB */
} else {
*ptr++ = (npix[-sk]) & 0xff ;
*ptr++ = (npix[-sk] >> 8) & 0xff ;
*ptr++ = (npix[-sk] >> 16) & 0xff ;
}
}
}
break ;
case 4:
if( border == MSBFirst ){
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk] >> 24) & 0xff ; /* MSB */
*ptr++ = (ppix[sk] >> 16) & 0xff ;
*ptr++ = (ppix[sk] >> 8) & 0xff ;
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
} else {
*ptr++ = (npix[-sk] >> 24) & 0xff ;
*ptr++ = (npix[-sk] >> 16) & 0xff ;
*ptr++ = (npix[-sk] >> 8) & 0xff ;
*ptr++ = (npix[-sk]) & 0xff ;
}
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
sk = sar[k++] ;
if( sk >= 0 ){
*ptr++ = (ppix[sk]) & 0xff ; /* LSB */
*ptr++ = (ppix[sk] >> 8) & 0xff ;
*ptr++ = (ppix[sk] >> 16) & 0xff ;
*ptr++ = (ppix[sk] >> 24) & 0xff ; /* MSB */
} else {
*ptr++ = (npix[-sk]) & 0xff ;
*ptr++ = (npix[-sk] >> 8) & 0xff ;
*ptr++ = (npix[-sk] >> 16) & 0xff ;
*ptr++ = (npix[-sk] >> 24) & 0xff ;
}
}
}
break ;
default:
fprintf(stderr,
"\n*** ILLEGAL value of display bytes/pix=%d in mri_to_XImage\n",
dc->byper);
EXIT(1) ;
}
RETURN( ximage ) ;
}
/*--------------------------------------------------------------------------*/
/*! - Input: an XImage of one size
- Output: an XImage of another size
- method: nearest neighbor resampling
----------------------------------------------------------------------------*/
XImage * resize_XImage( MCW_DC *dc , XImage *image ,
int new_width , int new_height )
{
static int *lt = NULL ; /* lookup table stuff */
static int old_width = -1 ;
register int iy, ex, ey, iW, iH, w2 ;
char *ximag;
char *Ep, *El, *Ip, *Il, *Id , *Ed ; /* d=data, l=row, p=pixel */
int Erow , Irow ;
XImage *emage ; /* to be output image */
/*** sanity check ***/
ENTRY("resize_XImage") ;
if( new_width <= 0 || new_height <= 0 ){
fprintf(stderr ,
"\n***ILLEGAL new width %d or height %d in resize\n",
new_width , new_height ) ;
EXIT(1) ;
}
/*** data about input image ***/
iW = image->width ; /* input width and height */
iH = image->height ;
if( iW == new_width && iH == new_height ){ /* very special case */
RETURN( image ) ;
}
/*** create emage of the appropriate size ***/
w2 = new_width * dc->byper ;
ximag = (char *) XtMalloc( (size_t) (w2 * new_height) );
if( ximag == NULL ){
fprintf(stderr,"\n***CANNOT allocate memory for resizing XImage\n") ;
EXIT(1) ;
}
emage = XCreateImage( dc->display , dc->visual , dc->depth ,
ZPixmap, 0, ximag, new_width,new_height, 8, w2 ) ;
if( emage == NULL ){
fprintf(stderr,"\n*** CANNOT create new XImage for resizing\n") ;
EXIT(1) ;
}
/*** make lookup table for xnew -> xold ***/
/*** Notice that this table will never be de-allocated or shrink;
it will grow larger when the images grow larger, as needed. ***/
if( new_width > old_width ){
lt = (int *) XtRealloc( (char *)lt,(size_t)(new_width * sizeof(int)) );
old_width = new_width ;
}
for( ex=0 ; ex < new_width ; ex++ )
lt[ex] = MAP_XY(ex,new_width,iW) * dc->byper ;
/*** get ready to go ***/
Ed = (char *) emage->data ; Erow = emage->bytes_per_line ;
Id = (char *) image->data ; Irow = image->bytes_per_line ;
switch( dc->byper ){
case 1: /* 1 byte per pixel */
for( ey=0 ; ey < new_height ; ey++ ){
iy = MAP_XY(ey,new_height,iH) ; /* row index in input image */
Il = Id + Irow * iy ; /* start of that row */
El = Ed + Erow * ey ; /* start of row in output */
Ep = El ;
for( ex=0 ; ex < new_width ; ex++ ){
Ip = Il + lt[ex] ; /* data pointer in input */
*Ep++ = *Ip ;
}
}
break ;
case 2: /* 2 bytes per pixel */
for( ey=0 ; ey < new_height ; ey++ ){
iy = MAP_XY(ey,new_height,iH) ; /* row index in input image */
Il = Id + Irow * iy ; /* start of that row */
El = Ed + Erow * ey ; /* start of row in output */
Ep = El ;
for( ex=0 ; ex < new_width ; ex++ ){
Ip = Il + lt[ex] ; /* data pointer in input */
*Ep++ = *Ip ;
*Ep++ = *(Ip+1) ;
}
}
break ;
case 3: /* 3 & 4 added 22 Aug 1998 */
for( ey=0 ; ey < new_height ; ey++ ){
iy = MAP_XY(ey,new_height,iH) ; /* row index in input image */
Il = Id + Irow * iy ; /* start of that row */
El = Ed + Erow * ey ; /* start of row in output */
Ep = El ;
for( ex=0 ; ex < new_width ; ex++ ){
Ip = Il + lt[ex] ; /* data pointer in input */
*Ep++ = *Ip ;
*Ep++ = *(Ip+1) ;
*Ep++ = *(Ip+2) ;
}
}
break ;
case 4:
for( ey=0 ; ey < new_height ; ey++ ){
iy = MAP_XY(ey,new_height,iH) ; /* row index in input image */
Il = Id + Irow * iy ; /* start of that row */
El = Ed + Erow * ey ; /* start of row in output */
Ep = El ;
for( ex=0 ; ex < new_width ; ex++ ){
Ip = Il + lt[ex] ; /* data pointer in input */
*Ep++ = *Ip ;
*Ep++ = *(Ip+1) ;
*Ep++ = *(Ip+2) ;
*Ep++ = *(Ip+3) ;
}
}
break ;
default:
fprintf(stderr,"\n***ILLEGAL bytes/pix=%d for resizing\n",dc->byper) ;
EXIT(1) ;
}
RETURN( emage ) ;
}
/*---------------------------------------------------------------------------*/
/*! - input = XImage (with Pixel values from dc)
- output = RGB or Grayscale image
- code = mask of values indicating optional processing:
- (code & X2M_USE_CMAP) != 0 means use the entire colormap
== 0 means use only Pixels in dc
- (code & X2M_FORCE_RGB)!= 0 means output is always RGB format
== 0 means output might be byte format
(grayscale) if all pixels are gray
-----------------------------------------------------------------------------*/
MRI_IMAGE * XImage_to_mri( MCW_DC *dc , XImage *ximage , int code )
{
int nx , ny , npix , ii,jj , kk , allgray , lsize ;
Pixel pp ;
byte *rgb , *gray ;
byte rr,gg,bb ;
byte *ptr ;
XColor *xc ;
MRI_IMAGE *outim ;
int border ; /* 22 Aug 1998 */
int use_cmap = ((code & X2M_USE_CMAP ) != 0) ; /* 03 Apr 2001 */
int force_rgb = ((code & X2M_FORCE_RGB) != 0) ;
ENTRY("XImage_to_mri") ;
if( ximage == NULL || ximage->data == NULL ) RETURN( NULL ) ;
#if 0
fprintf(stderr,
"XImage bitmap_unit =%3d bitmap_pad=%3d depth =%3d\n"
" bytes_per_line=%3d width =%3d height=%3d\n"
" bits_per_pixel=%3d xoffset =%3d\n" ,
ximage->bitmap_unit , ximage->bitmap_pad , ximage->depth ,
ximage->bytes_per_line , ximage->width , ximage->height ,
ximage->bits_per_pixel , ximage->xoffset ) ;
#endif
nx = ximage->width ; ny = ximage->height ; npix = nx * ny ;
lsize = ximage->bytes_per_line ;
ptr = (byte *) ximage->data ; /* pointer to pixels */
rgb = (byte *) malloc( sizeof(byte) * 3*npix ) ;
if( rgb == NULL ){
fprintf(stderr,"\n*** malloc failure in XImage_to_mri\n") ;
EXIT(1) ;
}
border = ximage->byte_order ; /* 22 Aug 1998 */
switch( dc->byper ){
case 1: /* 1 byte per pixel */
kk = 0 ; allgray = !force_rgb ;
for( jj=0 ; jj < ny ; jj++ ){
for( ii=0 ; ii < nx ; ii++ ){
pp = ptr[ii+jj*lsize] ; /* pixel value */
xc = DCpix_to_XColor( dc , pp , use_cmap ) ; /* XColor */
rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
allgray = allgray && (rr==gg) && (gg=bb) ;
}
}
break ;
case 2: /* 2 bytes per pixel */
kk = 0 ; allgray = !force_rgb ;
for( jj=0 ; jj < ny ; jj++ ){
for( ii=0 ; ii < nx ; ii++ ){
if( border == MSBFirst )
pp = (ptr[2*ii+jj*lsize] << 8) | ptr[2*ii+jj*lsize+1] ;
else
pp = (ptr[2*ii+jj*lsize+1] << 8) | ptr[2*ii+jj*lsize] ;
xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
allgray = allgray && (rr==gg) && (gg=bb) ;
}
}
break ;
case 3: /* 3 & 4 added 22 Aug 1998 */
kk = 0 ; allgray = !force_rgb ;
for( jj=0 ; jj < ny ; jj++ ){
for( ii=0 ; ii < nx ; ii++ ){
if( border == MSBFirst )
pp = (ptr[3*ii+jj*lsize] << 16) |
(ptr[3*ii+jj*lsize+1] << 8) | ptr[3*ii+jj*lsize+2] ;
else
pp = (ptr[3*ii+jj*lsize+2] << 16) |
(ptr[3*ii+jj*lsize+1] << 8) | ptr[3*ii+jj*lsize] ;
xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
allgray = allgray && (rr==gg) && (gg=bb) ;
}
}
break ;
case 4:
kk = 0 ; allgray = !force_rgb ;
for( jj=0 ; jj < ny ; jj++ ){
for( ii=0 ; ii < nx ; ii++ ){
if( border == MSBFirst )
pp = (ptr[4*ii+jj*lsize] << 24) | (ptr[4*ii+jj*lsize+1] << 16) |
(ptr[4*ii+jj*lsize+2] << 8) | ptr[4*ii+jj*lsize+3] ;
else
pp = (ptr[4*ii+jj*lsize+3] << 24) | (ptr[4*ii+jj*lsize+2] << 16) |
(ptr[4*ii+jj*lsize+1] << 8) | ptr[4*ii+jj*lsize] ;
xc = DCpix_to_XColor( dc , pp , use_cmap ) ;
rr = rgb[kk++] = INTEN_TO_BYTE( xc->red ) ;
gg = rgb[kk++] = INTEN_TO_BYTE( xc->green ) ;
bb = rgb[kk++] = INTEN_TO_BYTE( xc->blue ) ;
allgray = allgray && (rr==gg) && (gg=bb) ;
}
}
break ;
default:
fprintf(stderr,
"\n*** ILLEGAL value of bytes/pix=%d in XImage_to_mri\n",
dc->byper);
EXIT(1) ;
}
/*** if all pixels are gray, return a grayscale image ***/
if( allgray ){
gray = (byte *) malloc( sizeof(byte) * npix ) ;
if( gray == NULL ){
fprintf(stderr,"\n*** malloc failure in XImage_to_mri\n") ;
EXIT(1) ;
}
for( ii=0 , kk=0 ; ii < npix ; ii++ , kk+=3) gray[ii] = rgb[kk] ;
free(rgb) ;
outim = mri_new_vol_empty( nx , ny , 1 , MRI_byte ) ;
mri_fix_data_pointer( gray , outim ) ;
} else {
/*** not all gray --> return color RGB image ***/
outim = mri_new_vol_empty( nx , ny , 1 , MRI_rgb ) ;
mri_fix_data_pointer( rgb , outim ) ;
}
RETURN( outim ) ;
}
/*-----------------------------------------------------------------------*/
/* Convert an array of X11 Pixel values to an XImage for display.
Adapted from mri_to_XImage by RWCox -- 11 Feb 1999
-------------------------------------------------------------------------*/
XImage * pixar_to_XImage( MCW_DC *dc, int nx, int ny, Pixel *par )
{
int w2, width, height , border ;
unsigned char *Image ;
XImage *ximage ;
register int i , hw ;
register unsigned char *ptr;
/*-- sanity checks --*/
ENTRY("pixar_to_XImage") ;
if( dc == NULL || nx < 1 || ny < 1 || par == NULL ) RETURN( NULL ) ;
width = nx ; height = ny ;
w2 = width * dc->byper ; /* rowlength in bytes */
Image = (unsigned char *) XtMalloc( (size_t) (w2*height) );
if( Image == NULL ) RETURN( NULL ) ;
ximage = XCreateImage( dc->display , dc->visual , dc->depth ,
ZPixmap , 0 , Image , width,height , 8 , w2 ) ;
if( ximage == NULL ){ XtFree((char *)Image) ; RETURN( NULL ) ; }
border = ximage->byte_order ; /* byte order */
ptr = Image ; /* pointer to image bytes */
hw = height * width ; /* total number of pixels */
switch( dc->byper ){ /* load data into Image */
case 1: /* 1 byte data goes into Image */
for( i=0 ; i < hw ; i++ ){
*ptr++ = par[i] & 0xff ;
}
break ;
case 2: /* 2 byte data goes into Image */
if( border == MSBFirst ){
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] >> 8) & 0xff ; /* MSB */
*ptr++ = (par[i] ) & 0xff ; /* LSB */
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] ) & 0xff ; /* LSB */
*ptr++ = (par[i] >> 8) & 0xff ; /* MSB */
}
}
break ;
case 3: /* 3 byte data */
if( border == MSBFirst ){
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] >> 16) & 0xff ; /* MSB */
*ptr++ = (par[i] >> 8) & 0xff ;
*ptr++ = (par[i] ) & 0xff ; /* LSB */
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] ) & 0xff ; /* LSB */
*ptr++ = (par[i] >> 8) & 0xff ;
*ptr++ = (par[i] >> 16) & 0xff ; /* MSB */
}
}
break ;
case 4: /* 4 byte data */
if( border == MSBFirst ){
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] >> 24) & 0xff ; /* MSB */
*ptr++ = (par[i] >> 16) & 0xff ;
*ptr++ = (par[i] >> 8) & 0xff ;
*ptr++ = (par[i] ) & 0xff ; /* LSB */
}
} else { /* LSBFirst */
for( i=0 ; i < hw ; i++ ){
*ptr++ = (par[i] ) & 0xff ; /* LSB */
*ptr++ = (par[i] >> 8) & 0xff ;
*ptr++ = (par[i] >> 16) & 0xff ;
*ptr++ = (par[i] >> 24) & 0xff ; /* MSB */
}
}
break ;
default:
fprintf(stderr,
"\n*** ILLEGAL value of display bytes/pix=%d in pixar_to_XImage\n",
dc->byper);
EXIT(1) ;
}
RETURN( ximage ) ;
}
/*-------------------------------------------------------------------*/
#undef INLINE
#ifdef __GNUC__
# define INLINE inline
#else
# define INLINE /*nada*/
#endif
/*-------------------------------------------------------------------*/
/*! Local copy of function from display.c, hopefully for speed.
---------------------------------------------------------------------*/
static INLINE Pixel tc_rgb_to_pixel( MCW_DC *dc, byte rr, byte gg, byte bb )
{
static MCW_DC *dcold=NULL ;
DC_colordef *cd = dc->cdef ;
static unsigned long pold=0 ;
static byte rold=0 , gold=0 , bold=0 ;
unsigned long r , g , b ;
if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
if( rr == 0 && gg == 0 && bb == 0 ) return 0 ; /* common */
if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ; /* cases */
if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
return (Pixel) pold ;
rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* OK, remember for next time */
r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
: (rr>>cd->rrshift) ; r = r & cd->rrmask ;
g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
: (gg>>cd->ggshift) ; g = g & cd->ggmask ;
b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
: (bb>>cd->bbshift) ; b = b & cd->bbmask ;
pold = r | g | b ; /* assemble color from components */
return (Pixel) pold ;
}
/*----------------------------------------------------------------------------*/
static XImage * rgb_to_XImage_simple( MCW_DC *, MRI_IMAGE * ) ;
static XImage * rgb_to_XImage_clever( MCW_DC *, MRI_IMAGE * ) ;
/*----------------------------------------------------------------------------*/
/*! Convert an MRI_IMAGE of rgb values to an XImage for display.
------------------------------------------------------------------------------*/
XImage * rgb_to_XImage( MCW_DC *dc , MRI_IMAGE *im )
{
switch( dc->visual_class ){
case TrueColor: return rgb_to_XImage_simple(dc,im) ;
case PseudoColor: return rgb_to_XImage_clever(dc,im) ;
}
return NULL ;
}
/*----------------------------------------------------------------------------*/
/*! Convert an MRI_IMAGE of rgb bytes to an XImage (TrueColor visual only)
------------------------------------------------------------------------------*/
static XImage * rgb_to_XImage_simple( MCW_DC *dc , MRI_IMAGE *im )
{
int nxy , ii ;
byte *rgb ;
Pixel *par ;
XImage *xim ;
ENTRY("rgb_to_XImage_simple") ;
/*-- sanity check --*/
if( dc == NULL || im == NULL || im->kind != MRI_rgb ) RETURN( NULL ) ;
nxy = im->nx * im->ny ;
rgb = MRI_RGB_PTR(im) ;
par = (Pixel *) malloc(sizeof(Pixel)*nxy); if( par == NULL ) RETURN(NULL) ;
for( ii=0 ; ii < nxy ; ii++ )
par[ii] = tc_rgb_to_pixel( dc , rgb[3*ii], rgb[3*ii+1], rgb[3*ii+2] ) ;
xim = pixar_to_XImage( dc , im->nx , im->ny , par ) ;
free(par) ; RETURN( xim ) ;
}
/*-----------------------------------------------------------------------*/
/*! Convert an MRI_IMAGE of rgb bytes to an XImage (general visual)
-------------------------------------------------------------------------*/
static XImage * rgb_to_XImage_clever( MCW_DC *dc , MRI_IMAGE *im )
{
int nxy , ii , c ;
byte *rgb , r,g,b ;
Pixel *par , p=0 ;
XImage *xim ;
int *col_ar , *ii_ar ;
ENTRY("rgb_to_XImage_clever") ;
/*-- sanity check --*/
if( dc == NULL || im == NULL || im->kind != MRI_rgb ) RETURN( NULL ) ;
nxy = im->nx * im->ny ;
rgb = MRI_RGB_PTR(im) ;
col_ar = (int *) malloc( sizeof(int) * nxy ) ;
ii_ar = (int *) malloc( sizeof(int) * nxy ) ;
par = (Pixel *)malloc( sizeof(Pixel) * nxy ) ;
if( col_ar == NULL ) RETURN( NULL );
if( ii_ar == NULL ){ free(col_ar); RETURN( NULL ); }
if( par == NULL ){ free(col_ar); free(ii_ar); RETURN( NULL ); }
for( ii=0 ; ii < nxy ; ii++ ){ /* convert RGB triples to ints */
ii_ar[ii] = ii ; /* and save original location */
col_ar[ii] = rgb[3*ii] << 16 | rgb[3*ii+1] << 8 | rgb[3*ii+2] ;
}
qsort_intint( nxy , col_ar , ii_ar ) ; /* sort to bring like colors together */
c = -1 ; /* a color that can't occur */
for( ii=0 ; ii < nxy ; ii++ ){
if( col_ar[ii] != c ){ /* have a new color, so compute its pixel */
c = col_ar[ii] ;
r = (c >> 16) & 0xff ; g = (c >> 8) & 0xff ; b = c & 0xff ;
p = DC_rgb_to_pixel( dc , r,g,b ) ;
}
par[ii_ar[ii]] = p ; /* store it where it came from */
}
free(col_ar) ; free(ii_ar) ; /* toss some trash */
xim = pixar_to_XImage( dc , im->nx , im->ny , par ) ;
free(par) ; RETURN( xim ) ;
}
/**************************************************************************/
/********** 26 Jun 2003: stuff for snapping a Widget to an image **********/
static int badsnap = 0 ;
static MCW_DC *snap_dc = NULL ;
/*! X11 error handler for when XGetImage fails. */
static int SNAP_errhandler( Display *d , XErrorEvent *x )
{
fprintf(stderr,"** X11 error trying to snapshot window!\n");
badsnap = 1 ; return 0 ;
}
/*--------------------------------------------------------------*/
/*! Grab the image from a widget's window. [20 Jun 2003]
----------------------------------------------------------------*/
MRI_IMAGE * SNAP_grab_image( Widget w , MCW_DC *dc )
{
XImage * xim ;
MRI_IMAGE * tim ;
Window win ;
Widget wpar=w ;
XWindowAttributes wa ;
int (*old_handler)(Display *, XErrorEvent *) ;
ENTRY("SNAP_grab_image") ;
if( dc == NULL ) RETURN(NULL) ;
if( w == NULL ){
win = RootWindow( dc->display , dc->screen_num ) ;
} else {
if( !XtIsWidget(w) ||
!XtIsRealized(w) ||
!XtIsManaged(w) ) RETURN(NULL) ;
win = XtWindow(w) ;
if( win == (Window)0 ) RETURN(NULL) ;
while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ; /* find top */
/*** Raise the window and SUMA will redisplay
entering an infernal loop. ZSS Mon Jun 30/03 ***/
#if 0
XRaiseWindow( dc->display , XtWindow(wpar) ) ; /* make it visible */
#endif
XFlush( dc->display ) ;
XmUpdateDisplay( w ) ;
if( !MCW_widget_visible(w) ) RETURN(NULL) ;
}
RWC_sleep(20) ; /* allow refresh */
XGetWindowAttributes( dc->display , win , &wa ) ; /* get win size */
xim = NULL ; badsnap = 0 ;
old_handler = XSetErrorHandler( SNAP_errhandler ) ;
xim = XGetImage( dc->display , win ,
0,0 , wa.width,wa.height,
(unsigned long)(-1), ZPixmap ) ;
(void) XSetErrorHandler( old_handler ) ;
if( badsnap ){
if( xim != NULL ) MCW_kill_XImage(xim) ;
RETURN(NULL) ;
}
if( xim == NULL ) RETURN(NULL) ;
tim = XImage_to_mri( dc , xim , X2M_USE_CMAP | X2M_FORCE_RGB ) ;
MCW_kill_XImage(xim) ;
RETURN(tim) ;
}
/*----------------------------------------------------------------------*/
/*! Call this function to get a snapshot of a widget and save
it into a PPM file.
------------------------------------------------------------------------*/
void ISQ_snapfile( Widget w )
{
MRI_IMAGE *tim ;
Window win ;
char fname[64] , *eee , prefix[32] ;
int ii ; static int last_ii=1 ;
ENTRY("ISQ_snapfile") ;
if( w == NULL || !XtIsWidget(w) ) EXRETURN ;
if( !XtIsRealized(w) || !XtIsManaged(w) ) EXRETURN ;
win = XtWindow(w); if( win == (Window)0 ) EXRETURN ;
/* create display context if we don't have one */
if( snap_dc == NULL ){
if( first_dc != NULL ) snap_dc = first_dc ;
else snap_dc = MCW_new_DC( w, 4,0, NULL,NULL, 1.0,0 );
}
/* try to get image */
tim = SNAP_grab_image( w , snap_dc ) ;
if( tim == NULL ) EXRETURN ;
eee = getenv("AFNI_SNAPFILE_PREFIX") ;
if( eee == NULL ){
strcpy(prefix,"S_") ;
} else {
strncpy(prefix,eee,30) ; prefix[30] = '\0' ; strcat(prefix,"_") ;
if( !THD_filename_ok(prefix) ) strcpy(prefix,"S_") ;
}
for( ii=last_ii ; ii <= 999999 ; ii++ ){
sprintf(fname,"%s%06d.ppm",prefix,ii) ;
if( ! THD_is_ondisk(fname) ) break ;
}
if( ii <= 999999 ) mri_write_pnm( fname , tim ) ;
mri_free(tim) ; last_ii = ii ;
EXRETURN ;
}
syntax highlighted by Code2HTML, v. 0.9.1