#include "mrilib.h"

/*-------------------------------------------------------------------------*/
/*! Composite a collection of MRI_rgb/MRI_rgba/MRI_byte images.
    The first image is on top, etc.  For MRI_rgb/MRI_byte images,
    the default opacity is alpha in 0..1.  Black (0,0,0) pixels on input
    are not overlaid (unless AFNI_OVERLAY_ZERO is YES).
    The output image is MRI_rgb; it is composited against a black backdrop.
---------------------------------------------------------------------------*/

MRI_IMAGE * mri_rgba_composite_array( MRI_IMARR *imar, float alpha )
{
   register int npix,ii,jj , nn,nim ;
   MRI_IMAGE *outim , *inim ;
   rgbyte *outar ;
   float  *usop  ;
   int reject_zero = !AFNI_yesenv("AFNI_OVERLAY_ZERO") ;

ENTRY("mri_rgba_composite") ;

   if( imar == NULL || IMARR_COUNT(imar) == 0 ) RETURN(NULL) ;

   if( alpha <= 0.0 || alpha > 1.0 ) alpha = 1.0 ;  /* default default */

   nim   = IMARR_COUNT(imar) ;
   outim = mri_new_conforming( IMARR_SUBIM(imar,0) , MRI_rgb ) ;
   outar = (rgbyte *) MRI_RGB_PTR(outim) ;          /* is all zero */
   npix  = outim->nvox ;

   usop  = (float *) malloc(sizeof(float)*npix) ;   /* used up opacity */
   for( ii=0 ; ii < npix ; ii++ ) usop[ii] = 0.0 ;

#undef  MAX_OPACITY
#define MAX_OPACITY 0.95

   for( nn=0 ; nn < nim ; nn++ ){
     inim = IMARR_SUBIM(imar,nn) ;
     if( inim->nvox < npix ) continue ;  /* bad */

     switch( inim->kind ){
       default: break ;   /* bad */

       case MRI_byte:{
         byte *inar = (byte *) MRI_BYTE_PTR(inim) , val ;
         register float opa ;
         for( ii=0 ; ii < npix ; ii++ ){
           if( reject_zero && inar[ii]==0 ) continue ;
           if( usop[ii] < MAX_OPACITY ){

             opa = alpha * (1.0-usop[ii]) ; usop[ii] += opa ;
             val = (byte)( opa * inar[ii] ) ;

             outar[ii].r += val ;
             outar[ii].g += val ;
             outar[ii].b += val ;
           }
         }
       }

       case MRI_rgb:{
         rgbyte *inar = (rgbyte *) MRI_RGB_PTR(inim) ;
         register float opa ;
         for( ii=0 ; ii < npix ; ii++ ){
           if( reject_zero && inar[ii].r==0
                           && inar[ii].g==0 && inar[ii].b==0 ) continue ;
           if( usop[ii] < MAX_OPACITY ){

             opa = alpha * (1.0-usop[ii]) ; usop[ii] += opa ;

             outar[ii].r += (byte)( opa * inar[ii].r ) ;
             outar[ii].g += (byte)( opa * inar[ii].g ) ;
             outar[ii].b += (byte)( opa * inar[ii].b ) ;
           }
         }
       }
       break ;

       case MRI_rgba:{
         rgba *inar = (rgba *) MRI_RGBA_PTR(inim) ;
         register float opa ;
         for( ii=0 ; ii < npix ; ii++ ){
           if( reject_zero && inar[ii].r==0
                           && inar[ii].g==0 && inar[ii].b==0 ) continue ;
           if( usop[ii] < MAX_OPACITY ){

             opa = 0.00392156*inar[ii].a * (1.0-usop[ii]) ; usop[ii] += opa ;

             outar[ii].r += (byte)( opa * inar[ii].r ) ;
             outar[ii].g += (byte)( opa * inar[ii].g ) ;
             outar[ii].b += (byte)( opa * inar[ii].b ) ;
           }
         }
       }
       break ;
     }
   }

   free(usop) ; RETURN(outim) ;
}

/*--------------------------------------------------------------------------*/
#include <stdarg.h>
/*--------------------------------------------------------------------------*/

MRI_IMAGE * mri_rgba_composite_VA( float alpha, ... )
{
   MRI_IMARR *imar=NULL ;
   MRI_IMAGE *im ;
   va_list vararg_ptr ;

   va_start( vararg_ptr , alpha ) ;

   while(1){
      im = va_arg( vararg_ptr , MRI_IMAGE * ) ;
      if( im == NULL ) break ;
      if( imar == NULL ) INIT_IMARR(imar) ;
      ADDTO_IMARR(imar,im) ;
   }

   va_end( vararg_ptr ) ;

   if( imar == NULL ) return NULL ;
   im = mri_rgba_composite_array( imar , alpha ) ;

   FREE_IMARR(imar) ; return im ;
}

/*--------------------------------------------------------------------------*/

MRI_IMAGE * mri_rgba_composite_two( float alpha, MRI_IMAGE *i1, MRI_IMAGE *i2 )
{
   MRI_IMARR *imar ; MRI_IMAGE *im ;
   INIT_IMARR(imar) ;
   ADDTO_IMARR(imar,i1) ; ADDTO_IMARR(imar,i2) ;
   im = mri_rgba_composite_array( imar , alpha ) ;
   FREE_IMARR(imar) ; return im ;
}
