Logo Search packages:      
Sourcecode: afterstep version File versions

imencdec.c

/*
 * Copyright (c) 2000,2001,2004 Sasha Vasko <sasha at aftercode.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


#undef LOCAL_DEBUG
#undef DO_CLOCKING
#ifndef NO_DEBUG_OUTPUT
#undef DEBUG_RECTS
#undef DEBUG_RECTS2
#endif

#ifdef _WIN32
#include "win32/config.h"
#else
#include "config.h"
#endif


#include <string.h>
#ifdef DO_CLOCKING
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif

#ifdef _WIN32
# include "win32/afterbase.h"
#else
# include "afterbase.h"
#endif
#include "asvisual.h"
#include "blender.h"
#include "asimage.h"
#include "imencdec.h"

static void decode_asscanline_native( ASImageDecoder *imdec, unsigned int skip, int y );
static void decode_asscanline_ximage( ASImageDecoder *imdec, unsigned int skip, int y );
static void decode_asscanline_argb32( ASImageDecoder *imdec, unsigned int skip, int y );

void decode_image_scanline_normal( ASImageDecoder *imdec );
void decode_image_scanline_beveled( ASImageDecoder *imdec );
void decode_image_scl_bevel_solid( ASImageDecoder *imdec );


Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format );
Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format );

void encode_image_scanline_asim( ASImageOutput *imout, ASScanline *to_store );
void encode_image_scanline_xim( ASImageOutput *imout, ASScanline *to_store );
void encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store );
void encode_image_scanline_argb32( ASImageOutput *imout, ASScanline *to_store );

static struct ASImageFormatHandlers
{
      Bool (*check_create_asim_format)( ASVisual *asv, ASImage *im, ASAltImFormats format );
      void (*encode_image_scanline)( ASImageOutput *imout, ASScanline *to_store );
}asimage_format_handlers[ASA_Formats] =
{
      { NULL, encode_image_scanline_asim },
      { create_image_xim, encode_image_scanline_xim },
      { create_image_xim, encode_image_scanline_mask_xim },
      { create_image_xim, encode_image_scanline_xim },
      { create_image_xim, encode_image_scanline_mask_xim },
      { create_image_xim, encode_image_scanline_xim },
      { create_image_argb32, encode_image_scanline_argb32 },
      { NULL, NULL }                             /* vector of doubles */
};



void output_image_line_top( ASImageOutput *, ASScanline *, int );
void output_image_line_fine( ASImageOutput *, ASScanline *, int );
void output_image_line_fast( ASImageOutput *, ASScanline *, int );
void output_image_line_direct( ASImageOutput *, ASScanline *, int );


/* *********************************************************************
 * quality control: we support several levels of quality to allow for
 * smooth work on older computers.
 * *********************************************************************/
static int asimage_quality_level = ASIMAGE_QUALITY_GOOD;


Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format )
{
      Bool scratch = False, do_alpha = False ; 
      XImage **dst ;
      if( format == ASA_ScratchXImageAndAlpha ) 
      {     
            format = ASA_ScratchXImage ;
            do_alpha = True ;
      }

      if( format == ASA_ScratchXImage || format == ASA_ScratchMaskXImage ) 
      {     
            scratch = True ;
            format = (format - ASA_ScratchXImage ) + ASA_XImage ;
      }           
      dst = (format == ASA_MaskXImage )? &(im->alt.mask_ximage):&(im->alt.ximage);
      if( *dst == NULL )
      {
            int depth = 0 ;
            if( format == ASA_MaskXImage )
                  depth = get_flags(im->flags, ASIM_XIMAGE_8BIT_MASK )? 8: 1;
            if( scratch )
                  *dst = create_visual_scratch_ximage( asv, im->width, im->height, depth );
            else
                  *dst = create_visual_ximage( asv, im->width, im->height, depth );
            if( *dst == NULL )
                  show_error( "Unable to create %sXImage for the visual %d",
                                (format == ASA_MaskXImage )?"mask ":"",
                                    asv->visual_info.visualid );
      }
      return ( *dst != NULL );
}

Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format )
{
      if( im->alt.argb32 == NULL )
            im->alt.argb32 = safemalloc( im->width*im->height*sizeof(ARGB32) );
      return True;
}

/*************************************************************************/
/* low level routines ****************************************************/
static void
asimage_dup_line (ASImage * im, ColorPart color, unsigned int y1, unsigned int y2, unsigned int length)
{
      ASStorageID *part = im->channels[color];
      if (part[y2] != 0)
      {     
            forget_data(NULL, part[y2]);
            part[y2] = 0 ;
      }
      if( part[y1] )
            part[y2] = dup_data(NULL, part[y1] );
}

void
asimage_erase_line( ASImage * im, ColorPart color, unsigned int y )
{
      if( !AS_ASSERT(im) )
      {
            ASStorageID *part = im->channels[color];
            if( color < IC_NUM_CHANNELS )
            {
                  if( part[y] )
                  {
                        forget_data( NULL, part[y] );
                        part[y] = 0;
                  }
            }else
            {
                  int c ;
                  for( c = 0 ; c < IC_NUM_CHANNELS ; c++ )
                  {
                        part = im->channels[color];
                        if( part[y] )
                              forget_data( NULL, part[y] );
                        part[y] = 0;
                  }
            }
      }
}


/* for consistency sake : */
inline void
copy_component( register CARD32 *src, register CARD32 *dst, int *unused, int len )
{
#if 1
#ifdef CARD64
      CARD64 *dsrc = (CARD64*)src;
      CARD64 *ddst = (CARD64*)dst;
#else
      double *dsrc = (double*)src;
      double *ddst = (double*)dst;
#endif
      register int i = 0;

      len += len&0x01;
      len = len>>1 ;
      do
      {
            ddst[i] = dsrc[i];
      }while(++i < len );
#else
      register int i = 0;

      len += len&0x01;
      do
      {
            dst[i] = src[i];
      }while(++i < len );
#endif
}

static inline int
set_component( register CARD32 *src, register CARD32 value, int offset, int len )
{
      register int i ;
      for( i = offset ; i < len ; ++i )
            src[i] = value;
      return len-offset;
}



static inline void
divide_component( register CARD32 *src, register CARD32 *dst, CARD16 ratio, int len )
{
      register int i = 0;
      len += len&0x00000001;                     /* we are 8byte aligned/padded anyways */
      if( ratio == 2 )
      {
#ifdef HAVE_MMX
            if( asimage_use_mmx )
            {
                  double *ddst = (double*)&(dst[0]);
                  double *dsrc = (double*)&(src[0]);
                  len = len>>1;
                  do{
                        asm volatile
                      (
                        "movq %1, %%mm0  \n\t" // load 8 bytes from src[i] into MM0
                        "psrld $1, %%mm0 \n\t" // MM0=src[i]>>1
                        "movq %%mm0, %0  \n\t" // store the result in dest
                              : "=m" (ddst[i]) // %0
                              : "m"  (dsrc[i]) // %1
                  );
                  }while( ++i < len );
            }else
#endif
                  do{
                        dst[i] = src[i] >> 1;
                        dst[i+1] = src[i+1]>> 1;
                        i += 2 ;
                  }while( i < len );
      }else
      {
            do{
                  register int c1 = src[i];
                  register int c2 = src[i+1];
                  dst[i] = c1/ratio;
                  dst[i+1] = c2/ratio;
                  i+=2;
            }while( i < len );
      }
}





/* ******************** ASImageDecoder ****************************/
ASImageDecoder *
start_image_decoding( ASVisual *asv,ASImage *im, ASFlagType filter,
                                int offset_x, int offset_y,
                                unsigned int out_width,
                                unsigned int out_height,
                                ASImageBevel *bevel )
{
      ASImageDecoder *imdec = NULL;

      if( asv == NULL )
            asv = get_default_asvisual();

      if( AS_ASSERT(filter) || AS_ASSERT(asv))
            return NULL;
      if( im != NULL )
            if( im->magic != MAGIC_ASIMAGE )
            {
#ifdef LOCAL_DEBUG
                  ASImage **tmp = NULL;
                  *tmp = im ;                        /* segfault !!!!! */
#endif
                  im = NULL ;
            }

      if( im == NULL )
      {
            offset_x = offset_y = 0 ;
            if( AS_ASSERT(out_width)|| AS_ASSERT(out_height))
                  return NULL ;
      }else
      {
            if( offset_x < 0 )
                  offset_x = (int)im->width + (offset_x%(int)im->width);
            else
                  offset_x %= im->width ;
            if( offset_y < 0 )
                  offset_y = (int)im->height + (offset_y%(int)im->height);
            else
                  offset_y %= im->height ;
            if( out_width == 0 )
                  out_width = im->width ;
            if( out_height == 0 )
                  out_height = im->height ;

      }

      imdec = safecalloc( 1, sizeof(ASImageDecoder));
      imdec->asv = asv ;
      imdec->im = im ;
      imdec->filter = filter ;
      imdec->offset_x = offset_x ;
      imdec->out_width = out_width;
      imdec->offset_y = offset_y ;
      imdec->out_height = out_height;
      imdec->next_line = offset_y ;
      imdec->back_color = (im != NULL)?im->back_color:ARGB32_DEFAULT_BACK_COLOR ;
    imdec->bevel = bevel ;
      if( bevel )
      {
            if( bevel->left_outline > MAX_BEVEL_OUTLINE )
                  bevel->left_outline = MAX_BEVEL_OUTLINE ;
            if( bevel->top_outline > MAX_BEVEL_OUTLINE )
                  bevel->top_outline = MAX_BEVEL_OUTLINE ;
            if( bevel->right_outline > MAX_BEVEL_OUTLINE )
                  bevel->right_outline = MAX_BEVEL_OUTLINE ;
            if( bevel->bottom_outline > MAX_BEVEL_OUTLINE )
                  bevel->bottom_outline = MAX_BEVEL_OUTLINE ;
            if( bevel->left_inline > out_width )
                  bevel->left_inline = MAX((int)out_width,0) ;
            if( bevel->top_inline > out_height )
                  bevel->top_inline = MAX((int)out_height,0) ;
            if( bevel->left_inline+bevel->right_inline > (int)out_width )
                  bevel->right_inline = MAX((int)out_width-(int)bevel->left_inline,0) ;
            if( bevel->top_inline+bevel->bottom_inline > (int)out_height )
                  bevel->bottom_inline = MAX((int)out_height-(int)bevel->top_inline,0) ;

            if( bevel->left_outline == 0 && bevel->right_outline == 0 &&
                  bevel->top_outline == 0 && bevel->bottom_outline == 0 &&
                  bevel->left_inline == 0 && bevel->left_inline == 0 &&
                  bevel->top_inline == 0 && bevel->bottom_inline == 0 )
                  imdec->bevel = bevel = NULL ;
      }
      if( bevel )
      {
            imdec->bevel_left   = bevel->left_outline ;
            imdec->bevel_top    = bevel->top_outline ;
            imdec->bevel_right  = imdec->bevel_left + (int)out_width ;
            imdec->bevel_bottom = imdec->bevel_top  + (int)out_height;
            imdec->bevel_h_addon  = bevel->left_outline+ bevel->right_outline;
            imdec->bevel_v_addon  = bevel->top_outline + bevel->bottom_outline;

            imdec->decode_image_scanline = decode_image_scanline_beveled ;
      }else
            imdec->decode_image_scanline = decode_image_scanline_normal ;

      prepare_scanline(out_width+imdec->bevel_h_addon, 0, &(imdec->buffer), asv->BGR_mode );
    imdec->buffer.back_color = (im != NULL)?im->back_color:ARGB32_DEFAULT_BACK_COLOR ;

      imdec->decode_asscanline = decode_asscanline_native;
      if( im != NULL )
      {     
            if( get_flags( im->flags, ASIM_DATA_NOT_USEFUL ) )
            {
                  if( im->alt.ximage != NULL && !get_flags( im->flags, ASIM_XIMAGE_NOT_USEFUL) )
                  {
                        imdec->decode_asscanline = decode_asscanline_ximage;
                        imdec->xim_buffer = safecalloc(1, sizeof(ASScanline));
                        prepare_scanline(im->alt.ximage->width, 0, imdec->xim_buffer, asv->BGR_mode );
                  }else if( im->alt.argb32 != NULL )
                  {
                        imdec->decode_asscanline = decode_asscanline_argb32;
                  }      
            }
      }

      return imdec;
}

void
set_decoder_bevel_geom( ASImageDecoder *imdec, int x, int y,
                        unsigned int width, unsigned int height )
{
      if( imdec && imdec->bevel )
      {
            ASImageBevel *bevel = imdec->bevel ;
            int tmp ;
            if( imdec->im )
            {
                  if( width == 0 )
                        width = imdec->im->width ;
                  if( height == 0 )
                        height= imdec->im->height;
            }else
            {
                  if( width == 0 )
                        width = MAX( (int)imdec->out_width - x,0) ;
                  if( height == 0 )
                        height= MAX( (int)imdec->out_height - y,0) ;
            }
            /* Bevel should completely encompas output region */
            x = MIN(x,0);
            y = MIN(y,0);
            if( x+width < imdec->out_width )
                  width += (int)imdec->out_width - x ;
            if( y+height < imdec->out_height )
                  height += (int)imdec->out_height - y ;

            imdec->bevel_left = x ;
            imdec->bevel_top  = y ;
            imdec->bevel_right = x+(int)width ;
            imdec->bevel_bottom = y+(int)height ;


            imdec->bevel_h_addon  = MAX(imdec->bevel_left+(int)bevel->left_outline, 0) ;
            tmp = MAX(0, (int)imdec->out_width - imdec->bevel_right );
            imdec->bevel_h_addon += MIN( tmp, (int)bevel->right_outline);

            imdec->bevel_v_addon  = MAX(imdec->bevel_top+(int)bevel->top_outline, 0) ;
            tmp = MAX(0, (int)imdec->out_height - imdec->bevel_bottom );
            imdec->bevel_v_addon += MIN( tmp, (int)bevel->bottom_outline);
      }
}

void
set_decoder_shift( ASImageDecoder *imdec, int shift )
{
      if( shift != 0 )
            shift = 8 ;

      if( imdec )
            imdec->buffer.shift = shift ;
}

void set_decoder_back_color( ASImageDecoder *imdec, ARGB32 back_color )
{
      if( imdec )
      {
            imdec->back_color = back_color ;
            imdec->buffer.back_color = back_color ;
      }
}


void
stop_image_decoding( ASImageDecoder **pimdec )
{
      if( pimdec )
            if( *pimdec )
            {
                  free_scanline( &((*pimdec)->buffer), True );
                  if( (*pimdec)->xim_buffer )
                  {
                        free_scanline( (*pimdec)->xim_buffer, True );
                        free( (*pimdec)->xim_buffer );
                  }

                  free( *pimdec );
                  *pimdec = NULL;
            }
}

/* ******************** ASImageOutput ****************************/

ASImageOutput *
start_image_output( ASVisual *asv, ASImage *im, ASAltImFormats format,
                    int shift, int quality )
{
      register ASImageOutput *imout= NULL;

      if( im != NULL )
            if( im->magic != MAGIC_ASIMAGE )
            {
                  im = NULL ;
            }

      if( asv == NULL )
            asv = get_default_asvisual();

      if( AS_ASSERT(im) || AS_ASSERT(asv) )
            return imout;

      if( format < 0 || format == ASA_Vector || format >= ASA_Formats)
            return NULL;
      if( asimage_format_handlers[format].check_create_asim_format )
            if( !asimage_format_handlers[format].check_create_asim_format(asv, im, format) )
                  return NULL;

      imout = safecalloc( 1, sizeof(ASImageOutput));
      imout->asv = asv;
      imout->im = im ;

      imout->out_format = format ;
      imout->encode_image_scanline = asimage_format_handlers[format].encode_image_scanline;

      prepare_scanline( im->width, 0, &(imout->buffer[0]), asv->BGR_mode);
      prepare_scanline( im->width, 0, &(imout->buffer[1]), asv->BGR_mode);

      imout->chan_fill[IC_RED]   = ARGB32_RED8(im->back_color);
      imout->chan_fill[IC_GREEN] = ARGB32_GREEN8(im->back_color);
      imout->chan_fill[IC_BLUE]  = ARGB32_BLUE8(im->back_color);
      imout->chan_fill[IC_ALPHA] = ARGB32_ALPHA8(im->back_color);

      imout->available = &(imout->buffer[0]);
      imout->used        = NULL;
      imout->buffer_shift = shift;
      imout->next_line = 0 ;
      imout->bottom_to_top = 1 ;
      if( quality > ASIMAGE_QUALITY_TOP || quality < ASIMAGE_QUALITY_POOR )
            quality = asimage_quality_level;

      imout->quality = quality ;
      if( shift > 0 )
      {/* choose what kind of error diffusion we'll use : */
            switch( quality )
            {
                  case ASIMAGE_QUALITY_POOR :
                  case ASIMAGE_QUALITY_FAST :
                        imout->output_image_scanline = output_image_line_fast ;
                        break;
                  case ASIMAGE_QUALITY_GOOD :
                        imout->output_image_scanline = output_image_line_fine ;
                        break;
                  case ASIMAGE_QUALITY_TOP  :
                        imout->output_image_scanline = output_image_line_top ;
                        break;
            }
      }else /* no quanitzation - no error diffusion */
            imout->output_image_scanline = output_image_line_direct ;

      return imout;
}

void set_image_output_back_color( ASImageOutput *imout, ARGB32 back_color )
{
      if( imout )
      {
            imout->chan_fill[IC_RED]   = ARGB32_RED8  (back_color);
            imout->chan_fill[IC_GREEN] = ARGB32_GREEN8(back_color);
            imout->chan_fill[IC_BLUE]  = ARGB32_BLUE8 (back_color);
            imout->chan_fill[IC_ALPHA] = ARGB32_ALPHA8(back_color);
      }
}

void toggle_image_output_direction( ASImageOutput *imout )
{
      if( imout )
      {
            if( imout->bottom_to_top < 0 )
            {
                  if( imout->next_line >= (int)imout->im->height-1 )
                        imout->next_line = 0 ;
                  imout->bottom_to_top = 1 ;
            }else if( imout->next_line <= 0 )
            {
                  imout->next_line = (int)imout->im->height-1 ;
                  imout->bottom_to_top = -1 ;
            }
      }
}


void
stop_image_output( ASImageOutput **pimout )
{
      if( pimout )
      {
            register ASImageOutput *imout = *pimout;
            if( imout )
            {
                  if( imout->used )
                        imout->output_image_scanline( imout, NULL, 1);
                  free_scanline(&(imout->buffer[0]), True);
                  free_scanline(&(imout->buffer[1]), True);
                  free( imout );
                  *pimout = NULL;
            }
      }
}

/* diffusingly combine src onto self and dst, and rightbitshift src by quantization shift */
static inline void
best_output_filter( register CARD32 *line1, register CARD32 *line2, int unused, int len )
{/* we carry half of the quantization error onto the surrounding pixels : */
 /*        X    7/16 */
 /* 3/16  5/16  1/16 */
      register int i ;
      register CARD32 errp = 0, err = 0, c;
      c = line1[0];
      if( (c&0xFFFF0000)!= 0 )
            c = ( c&0x7F000000 )?0:0x0000FFFF;
      errp = c&QUANT_ERR_MASK;
      line1[0] = c>>QUANT_ERR_BITS ;
      line2[0] += (errp*5)>>4 ;

      for( i = 1 ; i < len ; ++i )
      {
            c = line1[i];
            if( (c&0xFFFF0000)!= 0 )
                  c = (c&0x7F000000)?0:0x0000FFFF;
            c += ((errp*7)>>4) ;
            err = c&QUANT_ERR_MASK;
            line1[i] = (c&0x7FFF0000)?0x000000FF:(c>>QUANT_ERR_BITS);
            line2[i-1] += (err*3)>>4 ;
            line2[i] += ((err*5)>>4)+(errp>>4);
            errp = err ;
      }
}

static inline void
fine_output_filter( register CARD32 *src, register CARD32 *dst, short ratio, int len )
{/* we carry half of the quantization error onto the following pixel and store it in dst: */
      register int i = 0;
      if( ratio <= 1 )
      {
            register int c = src[0];
          do
            {
                  if( (c&0xFFFF0000)!= 0 )
                        c = ( c&0x7F000000 )?0:0x0000FFFF;
                  dst[i] = c>>(QUANT_ERR_BITS) ;
                  if( ++i >= len )
                        break;
                  c = ((c&QUANT_ERR_MASK)>>1)+src[i];
            }while(1);
      }else if( ratio == 2 )
      {
            register CARD32 c = src[0];
          do
            {
                  c = c>>1 ;
                  if( (c&0xFFFF0000) != 0 )
                        c = ( c&0x7F000000 )?0:0x0000FFFF;
                  dst[i] = c>>(QUANT_ERR_BITS) ;
                  if( ++i >= len )
                        break;
                  c = ((c&QUANT_ERR_MASK)>>1)+src[i];
            }while( 1 );
      }else
      {
            register CARD32 c = src[0];
          do
            {
                  c = c/ratio ;
                  if( c&0xFFFF0000 )
                        c = ( c&0x7F000000 )?0:0x0000FFFF;
                  dst[i] = c>>(QUANT_ERR_BITS) ;
                  if( ++i >= len )
                        break;
                  c = ((c&QUANT_ERR_MASK)>>1)+src[i];
            }while(1);
      }
}

static inline void
fast_output_filter( register CARD32 *src, register CARD32 *dst, short ratio, int len )
{/*  no error diffusion whatsoever: */
      register int i = 0;
      if( ratio <= 1 )
      {
            for( ; i < len ; ++i )
            {
                  register CARD32 c = src[i];
                  if( (c&0xFFFF0000) != 0 )
                        dst[i] = ( c&0x7F000000 )?0:0x000000FF;
                  else
                        dst[i] = c>>(QUANT_ERR_BITS) ;
            }
      }else if( ratio == 2 )
      {
            for( ; i < len ; ++i )
            {
                  register CARD32 c = src[i]>>1;
                  if( (c&0xFFFF0000) != 0 )
                        dst[i] = ( c&0x7F000000 )?0:0x000000FF;
                  else
                        dst[i] = c>>(QUANT_ERR_BITS) ;
            }
      }else
      {
            for( ; i < len ; ++i )
            {
                  register CARD32 c = src[i]/ratio;
                  if( (c&0xFFFF0000) != 0 )
                        dst[i] = ( c&0x7F000000 )?0:0x000000FF;
                  else
                        dst[i] = c>>(QUANT_ERR_BITS) ;
            }
      }
}

static inline void
fine_output_filter_mod( register CARD32 *data, int unused, int len )
{/* we carry half of the quantization error onto the following pixel : */
      register int i ;
      register CARD32 err = 0, c;
      for( i = 0 ; i < len ; ++i )
      {
            c = data[i];
            if( (c&0xFFFF0000) != 0 )
                  c = ( c&0x7E000000 )?0:0x0000FFFF;
            c += err;
            err = (c&QUANT_ERR_MASK)>>1 ;
            data[i] = (c&0x00FF0000)?0x000000FF:c>>QUANT_ERR_BITS ;
      }
}

/* *********************************************************************/
/*                                   DECODER :                                              */
/* Low level drivers :                                                */
static void
decode_asscanline_native( ASImageDecoder *imdec, unsigned int skip, int y )
{
      int i ;
      ASScanline *scl = &(imdec->buffer);
      int count, width = scl->width-skip ;
      for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
            if( get_flags(imdec->filter, 0x01<<i) )
            {
                  register CARD32 *chan = scl->channels[i]+skip;
                  if( imdec->im )
                        count = fetch_data32( NULL, imdec->im->channels[i][y], chan, imdec->offset_x, width, 0, NULL);
                  else
                        count = 0 ;
                  if( scl->shift )
                  {
                        register int k  = 0;
                        for(; k < count ; k++ )
                              chan[k] = chan[k]<<8;
                  }
                  if( count < width )
                        set_component( chan, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
            }
      clear_flags( scl->flags, SCL_DO_ALL);
      set_flags( scl->flags, imdec->filter);
}

static void
decode_asscanline_argb32( ASImageDecoder *imdec, unsigned int skip, int y )
{
      ASScanline *scl = &(imdec->buffer);
      int count, width = scl->width-skip ;
      ARGB32 *row = imdec->im->alt.argb32 + y*imdec->im->width ;
      CARD32 *a = scl->alpha+skip;
      CARD32 *r = scl->red+skip;
      CARD32 *g = scl->green+skip;
      CARD32 *b = scl->blue+skip;
      int max_x = imdec->im->width ;

      if( get_flags( imdec->filter, SCL_DO_ALPHA ) )
      {
            int x = imdec->offset_x ; 
            for( count = 0 ; count < width ; ++count) 
            {     
                  a[count] = ARGB32_ALPHA8(row[x])<<scl->shift ;  
                  if( ++x >= max_x )      x = 0;
            }      
      }      
            
      if( get_flags( imdec->filter, SCL_DO_RED ) )
      {
            int x = imdec->offset_x ; 
            for( count = 0 ; count < width ; ++count) 
            {     
                  r[count] = ARGB32_RED8(row[x])<<scl->shift ;    
                  if( ++x >= max_x )      x = 0;
            }      
      }      
            
      if( get_flags( imdec->filter, SCL_DO_GREEN ) )
      {
            int x = imdec->offset_x ; 
            for( count = 0 ; count < width ; ++count) 
            {     
                  g[count] = ARGB32_GREEN8(row[x])<<scl->shift ;  
                  if( ++x >= max_x )      x = 0;
            }      
      }      
      if( get_flags( imdec->filter, SCL_DO_BLUE ) )
      {
            int x = imdec->offset_x ; 
            for( count = 0 ; count < width ; ++count) 
            {     
                  b[count] = ARGB32_BLUE8(row[x])<<scl->shift ;   
                  if( ++x >= max_x )      x = 0;
            }      
      }      

      clear_flags( scl->flags, SCL_DO_ALL);
      set_flags( scl->flags, imdec->filter);
}


static void
decode_asscanline_ximage( ASImageDecoder *imdec, unsigned int skip, int y )
{
      int i ;
      ASScanline *scl = &(imdec->buffer);
      XImage *xim = imdec->im->alt.ximage ;
      int count, width = scl->width-skip, xim_width = xim->width ;
      ASFlagType filter = imdec->filter ;
#if 1
      if( width > xim_width || imdec->offset_x > 0 )
      {/* need to tile :( */
            ASScanline *xim_scl = imdec->xim_buffer;
            int offset_x = imdec->offset_x%xim_width ;
/*fprintf( stderr, __FILE__ ":" __FUNCTION__ ": width=%d, xim_width=%d, skip = %d, offset_x = %d - tiling\n", width, xim->width, skip, imdec->offset_x );   */

            GET_SCANLINE(imdec->asv,xim,xim_scl,y,(unsigned char*)xim->data+xim->bytes_per_line*y);
            /* We also need to decode mask if we have one :*/
            if( (xim = imdec->im->alt.mask_ximage ) != NULL )
            {
#ifndef X_DISPLAY_MISSING
                  CARD32 *dst = xim_scl->alpha ;
                  register int x = MIN((int)xim_scl->width,xim->width);
                  if( xim->depth == 8 )
                  {
                        CARD8  *src = (CARD8*)xim->data+xim->bytes_per_line*y ;
                        while(--x >= 0 ) dst[x] = (CARD32)(src[x]);
                  }else
                  {
                        while(--x >= 0 ) dst[x] = (XGetPixel(xim, x, y) == 0)?0x00:0xFF;
                  }
#endif
            }
            for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
                  if( get_flags(filter, 0x01<<i) )
                  {
                        register CARD32 *src = xim_scl->channels[i]+offset_x ;
                        register CARD32 *dst = scl->channels[i]+skip;
                        register int k  = 0;
                        count = xim_width-offset_x ;
                        if( count > width )
                              count = width ;

#define COPY_TILE_CHAN(op) \
            for(; k < count ; k++ ) dst[k] = op; \
            while( k < width ) \
            {     src = xim_scl->channels[i]-k ; \
                  count = MIN(xim_width+k,width); \
                  for(; k < count ; k++ ) dst[k] = op; \
            }

                        if( scl->shift )
                        {
                              COPY_TILE_CHAN(src[k]<<8)
                        }else
                        {
                              COPY_TILE_CHAN(src[k])
                        }
                        count += k ;
                        if( count < width )
                              set_component( src, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
                  }
      }else
#endif
      {/* cool we can put data directly into buffer : */
/*fprintf( stderr, __FILE__ ":" __FUNCTION__ ":direct\n" ); */
            int old_offset = scl->offset_x ;
            scl->offset_x = skip ;
            GET_SCANLINE(imdec->asv,xim,scl,y,(unsigned char *)xim->data+xim->bytes_per_line*y);
            /* We also need to decode mask if we have one :*/
            if( (xim = imdec->im->alt.mask_ximage ) != NULL )
            {
#ifndef X_DISPLAY_MISSING
                  CARD32 *dst = scl->alpha+skip ;
                  register int x = MIN(width,xim_width);
                  if( xim->depth == 8 )
                  {
                        CARD8  *src = (CARD8*)xim->data+xim->bytes_per_line*y ;
                        while(--x >= 0 ) dst[x] = (CARD32)(src[x]);
                  }else
                  {
                        while(--x >= 0 ) dst[x] = (XGetPixel(xim, x, y) == 0)?0x00:0xFF;
                  }
#endif
            }
            count = MIN(width,xim_width);
            scl->offset_x = old_offset ;
            for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
                  if( get_flags(filter, 0x01<<i) )
                  {
                        register CARD32 *chan = scl->channels[i]+skip;
                        if( scl->shift )
                        {
                              register int k  = 0;
                              for(; k < count ; k++ )
                                    chan[k] = chan[k]<<8;
                        }
                        if( count < width )
                              set_component( chan, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
                  }
      }
      clear_flags( scl->flags,SCL_DO_ALL);
      set_flags( scl->flags,imdec->filter);
}

/***********************************************************************/
/* High level drivers :                                                */
void                                           /* normal (unbeveled) */
decode_image_scanline_normal( ASImageDecoder *imdec )
{
      int                      y = imdec->next_line;
      if( y - imdec->offset_y >= imdec->out_height )
      {
            imdec->buffer.flags = 0 ;
            imdec->buffer.back_color = imdec->back_color ;
            return ;
      }

      if( imdec->im )
            y %= imdec->im->height;
      imdec->decode_asscanline( imdec, 0, y );
      ++(imdec->next_line);
}

static inline void
draw_solid_bevel_line( register ASScanline *scl, int alt_left, int hi_end, int lo_start, int alt_right,
                                 ARGB32 bevel_color, ARGB32 shade_color, ARGB32 hi_corner, ARGB32 lo_corner )
{
      int channel ;
      for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
            if( get_flags(scl->flags, (0x01<<channel)) )
            {
                  if( hi_end > 0 )
                  {
                        set_component( scl->channels[channel],
                                            ARGB32_CHAN8(bevel_color,channel)<<scl->shift,
                                                0, hi_end );
                        if( alt_left > 0 )
                              scl->channels[channel][alt_left-1] =
                                            ARGB32_CHAN8(hi_corner,channel)<<scl->shift ;
                  }
                  if( lo_start < (int)scl->width )
                  {
                        set_component( scl->channels[channel],
                                            ARGB32_CHAN8(shade_color,channel)<<scl->shift,
                                            lo_start, scl->width );
                        if( alt_right < (int)scl->width && alt_right > 0 )
                              scl->channels[channel][scl->width - alt_right] =
                                          ARGB32_CHAN8(lo_corner,channel)<<scl->shift ;
                  }
            }
}
static inline void
draw_fading_bevel_sides( ASImageDecoder *imdec,
                                   int left_margin, int left_delta,
                                   int right_delta, int right_margin )
{
      register ASScanline *scl = &(imdec->buffer);
      ASImageBevel *bevel = imdec->bevel ;
      CARD32 ha_bevel = ARGB32_ALPHA8(bevel->hi_color);
      CARD32 ha_shade = ARGB32_ALPHA8(bevel->lo_color);
    CARD32 hda_bevel = (ha_bevel<<8)/(bevel->left_inline+1) ;
    CARD32 hda_shade = (ha_shade<<8)/(bevel->right_inline+1);
      int channel ;

      for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
            if( get_flags(scl->flags, (0x01<<channel)) )
            {
                  CARD32 chan_col = ARGB32_CHAN8(bevel->hi_color,channel)<<scl->shift ;
                  register CARD32 ca = hda_bevel*(left_delta+1) ;
                  register int i = MIN((int)scl->width, imdec->bevel_left+(int)bevel->left_inline-left_delta);
                  CARD32 *chan_img_start = scl->channels[channel] ;

                  while( --i >= left_margin )
                  {
                        chan_img_start[i] = (chan_img_start[i]*(255-(ca>>8))+chan_col*(ca>>8))>>8 ;
                        ca += hda_bevel ;
                  }
                  ca = hda_shade*(right_delta+1) ;
                  i =  MAX( left_margin, imdec->bevel_right + right_delta - (int)bevel->right_inline);
                  chan_col = ARGB32_CHAN8(bevel->lo_color,channel)<<scl->shift ;
                  while( ++i < right_margin )
                  {
                        chan_img_start[i] = (chan_img_start[i]*(255-(ca>>8))+chan_col*(ca>>8))>>8 ;
                        ca += hda_shade ;
                  }
            }
}

static inline void
draw_transp_bevel_sides( ASImageDecoder *imdec,
                                   int left_margin, int left_delta,
                                   int right_delta, int right_margin )
{
      register ASScanline *scl = &(imdec->buffer);
      ASImageBevel *bevel = imdec->bevel ;
      CARD32 ha_bevel = ARGB32_ALPHA8(bevel->hi_color)>>1;
      CARD32 ha_shade = ARGB32_ALPHA8(bevel->lo_color)>>1;
      int channel ;

      for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
            if( get_flags(scl->flags, (0x01<<channel)) )
            {
                  CARD32 chan_col = (ARGB32_CHAN8(bevel->hi_color,channel)<<scl->shift)*ha_bevel ;
                  register CARD32 ca = 255-ha_bevel ;
                  register int i = imdec->bevel_left+(int)bevel->left_inline-left_delta;
                  CARD32 *chan_img_start = scl->channels[channel] ;

                  while( --i >= left_margin )
                        chan_img_start[i] = (chan_img_start[i]*ca+chan_col)>>8 ;

                  ca = 255-ha_shade ;
                  i =  MAX( left_margin, imdec->bevel_right + right_delta - (int)bevel->right_inline);
                  chan_col = (ARGB32_CHAN8(bevel->lo_color,channel)<<scl->shift)*ha_shade ;
                  while( ++i < right_margin )
                        chan_img_start[i] = (chan_img_start[i]*ca+chan_col)>>8 ;
            }
}


static inline void
draw_transp_bevel_line ( ASImageDecoder *imdec,
                                   int left_delta, int right_delta,
                                     CARD32 ca,
                                     ARGB32 left_color, ARGB32 color, ARGB32 right_color )
{
      register ASScanline *scl = &(imdec->buffer);
      ASImageBevel *bevel = imdec->bevel ;
      int start_point = imdec->bevel_left+(int)bevel->left_inline-left_delta;
      int end_point   = imdec->bevel_right + right_delta - (int)bevel->right_inline;
      int channel ;
      CARD32 rev_ca = (255-(ca>>8));
      if( start_point < (int)scl->width && end_point > 0 )
      {
            for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
                  if( get_flags(scl->flags, (0x01<<channel)) )
                  {
                        CARD32 chan_col = (ARGB32_CHAN8(color,channel)<<scl->shift)*(ca>>8) ;
                        CARD32 *chan_img_start = scl->channels[channel] ;
                        register int i ;
                        int end_i;

                        if( start_point < 0 )
                              i = -1 ;
                        else
                        {
                              i = start_point-1 ;
                              if( i < (int)scl->width && i >= 0 )
                                    chan_img_start[i] = (chan_img_start[i]*rev_ca + ARGB32_CHAN8(left_color,channel)*(ca>>8))>>8 ;
                        }
                        if( end_point >= (int)scl->width )
                              end_i = scl->width ;
                        else
                        {
                              end_i = end_point ;
                              if( end_i >= 0 ) 
                                    chan_img_start[end_i] = (chan_img_start[end_i]*rev_ca + ARGB32_CHAN8(right_color,channel)*(ca>>8))>>8 ;
                        }
                        while( ++i < end_i )
                              chan_img_start[i] = (chan_img_start[i]*rev_ca+chan_col)>>8;
                  }
      }
}

void
decode_image_scanline_beveled( ASImageDecoder *imdec )
{
      register ASScanline *scl = &(imdec->buffer);
      int                      y_out = imdec->next_line- (int)imdec->offset_y;
      register ASImageBevel *bevel = imdec->bevel ;
      ARGB32 bevel_color = bevel->hi_color, shade_color = bevel->lo_color;
      int offset_shade = 0;

      scl->flags = 0 ;
      if( y_out < 0 || y_out > (int)imdec->out_height+imdec->bevel_v_addon )
      {
            scl->back_color = imdec->back_color ;
            return ;
      }


      set_flags( scl->flags, imdec->filter );
      if( y_out < imdec->bevel_top )
      {
            if( bevel->top_outline > 0 )
            {
                  register int line = y_out - (imdec->bevel_top - (int)bevel->top_outline);
                  int alt_left  = (line*bevel->left_outline/bevel->top_outline)+1 ;
                  int alt_right = (line*bevel->right_outline/bevel->top_outline)+1 ;

                  alt_left += MAX(imdec->bevel_left-(int)bevel->left_outline,0) ;
                  offset_shade = MAX(imdec->bevel_right+(int)bevel->right_outline-alt_right,0);

/*          fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n",
                                    __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width );
  */
                  if( (int)scl->width < imdec->bevel_right )
                        alt_right -= imdec->bevel_right-(int)scl->width ;
                  if( offset_shade > (int)scl->width )
                        offset_shade = scl->width ;
                  draw_solid_bevel_line( scl, alt_left, offset_shade, offset_shade, alt_right,
                                                bevel->hi_color, bevel->lo_color, bevel->hihi_color, bevel->hilo_color );
            }
      }else if( y_out >= imdec->bevel_bottom )
      {
            if( bevel->bottom_outline > 0 )
            {
                  register int line = bevel->bottom_outline - (y_out - imdec->bevel_bottom);
                  int alt_left  = (line*bevel->left_outline/bevel->bottom_outline)+1 ;
                  int alt_right = (line*bevel->right_outline/bevel->bottom_outline)+1 ;

                  alt_left += MAX(imdec->bevel_left-(int)bevel->left_outline,0) ;
                  offset_shade = MIN(alt_left, (int)scl->width );

                  if( (int)scl->width < imdec->bevel_right )
                        alt_right -= imdec->bevel_right-(int)scl->width ;

/*    fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n",
                               __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width );
  */
                  set_flags( scl->flags, imdec->filter );
                  draw_solid_bevel_line( scl, alt_left, alt_left, alt_left, alt_right,
                                                bevel->hi_color, bevel->lo_color,
                                                bevel->hilo_color, bevel->lolo_color );
            }
      }else
      {
            int left_margin = MAX(0, imdec->bevel_left);
            int right_margin = MIN((int)scl->width, imdec->bevel_right);
            int y = imdec->next_line-bevel->top_outline ;
            if( imdec->im )
                  y %= imdec->im->height ;

            if( left_margin < (int)scl->width )
                  imdec->decode_asscanline( imdec, left_margin, y );

            draw_solid_bevel_line( scl, -1, left_margin, right_margin, scl->width,
                                             bevel->hi_color, bevel->lo_color,
                                             bevel->hilo_color, bevel->lolo_color );
            if( left_margin < (int)scl->width )
            {
                  if( get_flags( bevel->type, BEVEL_SOLID_INLINE ) )
                  {
                        if( y_out < imdec->bevel_top+(int)bevel->top_inline)
                        {
                              register int line = y_out - imdec->bevel_top;
                              int left_delta  = bevel->left_inline-((line*bevel->left_inline/bevel->top_inline)) ;
                              int right_delta = bevel->right_inline-((line*bevel->right_inline/bevel->top_inline)-1) ;

                              draw_transp_bevel_sides( imdec, left_margin, left_delta,
                                                                  right_delta, right_margin );
                              draw_transp_bevel_line ( imdec, left_delta-1, right_delta-1,
                                                                  ARGB32_ALPHA8(bevel_color)<<7,
                                                                  bevel->hihi_color, bevel->hi_color, bevel->hilo_color );

                        }else if( y_out >= imdec->bevel_bottom - bevel->bottom_inline)
                        {
                              register int line = y_out - (imdec->bevel_bottom - bevel->bottom_inline);
                              int left_delta  = (line*bevel->left_inline/bevel->bottom_inline)+1 ;
                              int right_delta = (line*bevel->right_inline/bevel->bottom_inline)-1 ;

                              draw_transp_bevel_sides( imdec,     left_margin, left_delta,
                                                                  right_delta, right_margin );
                              draw_transp_bevel_line ( imdec, left_delta-1, right_delta,
                                                                  ARGB32_ALPHA8(shade_color)<<7,
                                                                  bevel->hilo_color, bevel->lo_color, bevel->lolo_color );

                        }else
                        {
                              draw_transp_bevel_sides( imdec, left_margin, 0, 0, right_margin );
                        }

                  }
                  else
                  {
/* fprintf( stderr, __FUNCTION__ ":%d: y_out = %d, imdec->bevel_top = %d, bevel->top_inline = %d\n",
                        __LINE__,  y_out, imdec->bevel_top, bevel->top_inline);
 */
 
                        if( y_out < imdec->bevel_top+bevel->top_inline)
                        {
                              register int line = y_out - imdec->bevel_top;
                              int left_delta  = bevel->left_inline-((line*bevel->left_inline/bevel->top_inline)) ;
                              int right_delta = bevel->right_inline-((line*bevel->right_inline/bevel->top_inline)-1) ;
                        CARD32 hda_bevel = (ARGB32_ALPHA8(bevel_color)<<8)/(bevel->left_inline+1) ;

                              draw_fading_bevel_sides( imdec,     left_margin, left_delta,
                                                                  right_delta, right_margin );
/* fprintf( stderr, __FUNCTION__ ":%d: left_delta = %d, right_delta = %d, left_inline = %d, right_inline = %d, bevel_left = %d, bevel_right = %d\n",
                        __LINE__,  left_delta, right_delta, bevel->left_inline, bevel->right_inline, imdec->bevel_left, imdec->bevel_right);
 */ 

                              draw_transp_bevel_line ( imdec, left_delta-1, right_delta-1,
                                                                  hda_bevel*(left_delta+1),
                                                                  bevel->hihi_color, bevel->hi_color, bevel->hilo_color );

                        }else if( y_out >= imdec->bevel_bottom - bevel->bottom_inline)
                        {
                              register int line = y_out - (imdec->bevel_bottom - bevel->bottom_inline);
                              int left_delta  = (line*bevel->left_inline/bevel->bottom_inline)+1 ;
                              int right_delta = (line*bevel->right_inline/bevel->bottom_inline)-1 ;
                        CARD32 hda_shade = (ARGB32_ALPHA8(shade_color)<<8)/(bevel->right_inline+1) ;

                              draw_fading_bevel_sides( imdec, left_margin, left_delta,
                                                                  right_delta, right_margin );

                              draw_transp_bevel_line ( imdec, left_delta-1, right_delta,
                                                                  hda_shade*(right_delta+1),
                                                                  bevel->hilo_color, bevel->lo_color, bevel->lolo_color );
                        }else
                        {
                              draw_fading_bevel_sides( imdec, left_margin, 0, 0, right_margin );
                        }
                  }
            }
      }
      ++(imdec->next_line);
}

/* *********************************************************************/
/*                                    ENCODER :                                                   */
inline static void
tile_ximage_line( XImage *xim, unsigned int line, int step, int range )
{
      register int i ;
      int xim_step = step*xim->bytes_per_line ;
      char *src_line = xim->data+xim->bytes_per_line*line ;
      char *dst_line = src_line+xim_step ;
      int max_i = MIN((int)xim->height,(int)line+range), min_i = MAX(0,(int)line-range) ;
      for( i = line+step ; i < max_i && i >= min_i ; i+=step )
      {
            memcpy( dst_line, src_line, xim->bytes_per_line );
            dst_line += xim_step ;
      }
}

void
encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store )
{
#ifndef X_DISPLAY_MISSING
      ASImage *im = imout->im ;
      register XImage *xim = im->alt.mask_ximage ;
      if( imout->next_line < xim->height && imout->next_line >= 0 )
      {
            if( get_flags(to_store->flags, SCL_DO_ALPHA) )
            {
                  CARD32 *a = to_store->alpha ;
                  register int x = MIN((unsigned int)(xim->width), to_store->width);
                  if( xim->depth == 8 )
                  {
                        CARD8 *dst = (CARD8*)xim->data+xim->bytes_per_line*imout->next_line ;
                        while( --x >= 0 )
                              dst[x] = (CARD8)(a[x]);
                  }else
                  {
                        unsigned int nl = imout->next_line ;
                        while( --x >= 0 )
                              XPutPixel( xim, x, nl, (a[x] >= 0x7F)?1:0 );
                  }
            }
            if( imout->tiling_step > 0 )
                  tile_ximage_line( xim, imout->next_line,
                                    imout->bottom_to_top*imout->tiling_step,
                                            (imout->tiling_range ? imout->tiling_range:imout->im->height) );
            imout->next_line += imout->bottom_to_top;
      }
#endif
}

void
encode_image_scanline_xim( ASImageOutput *imout, ASScanline *to_store )
{
      register XImage *xim = imout->im->alt.ximage ;
      if( imout->next_line < xim->height && imout->next_line >= 0 )
      {
            if( !get_flags(to_store->flags, SCL_DO_RED) )
                  set_component( to_store->red, ARGB32_RED8(to_store->back_color), 0, to_store->width );
            if( !get_flags(to_store->flags, SCL_DO_GREEN) )
                  set_component( to_store->green, ARGB32_GREEN8(to_store->back_color), 0, to_store->width );
            if( !get_flags(to_store->flags, SCL_DO_BLUE) )
                  set_component( to_store->blue , ARGB32_BLUE8(to_store->back_color), 0, to_store->width );
            PUT_SCANLINE(imout->asv, xim,to_store,imout->next_line,
                               (unsigned char*)xim->data+imout->next_line*xim->bytes_per_line);

            if( imout->tiling_step > 0 )
                  tile_ximage_line( imout->im->alt.ximage, imout->next_line,
                                    imout->bottom_to_top*imout->tiling_step,
                                            (imout->tiling_range ? imout->tiling_range:imout->im->height) );
            LOCAL_DEBUG_OUT( "flags = %lX", to_store->flags );
#if 1
            if( imout->out_format == ASA_ScratchXImageAndAlpha )
            {     
                  if( get_flags(to_store->flags, SCL_DO_ALPHA) && get_flags( imout->im->flags, ASIM_DATA_NOT_USEFUL ))
                  {
                        int bytes_count, i ;
                        int line = imout->next_line ;
                        bytes_count = asimage_add_line(imout->im, IC_ALPHA, to_store->channels[IC_ALPHA]+to_store->offset_x, line);
                        if( imout->tiling_step > 0 )
                        {
                              int range = (imout->tiling_range ? imout->tiling_range:imout->im->height);
                              int max_i = MIN((int)imout->im->height,line+range), min_i = MAX(0,line-range) ;
                              int step =  imout->bottom_to_top*imout->tiling_step;
                              for( i = line+step ; i < max_i && i >= min_i ; i+=step )
                              {
      /*                                  fprintf( stderr, "copy-encoding color %d, from lline %d to %d, %d bytes\n", color, imout->next_line, i, bytes_count );*/
                                    asimage_dup_line( imout->im, IC_ALPHA, line, i, bytes_count );
                              }
                        }
                  }      
            }
#endif
            imout->next_line += imout->bottom_to_top;
      }
}

void
encode_image_scanline_asim( ASImageOutput *imout, ASScanline *to_store )
{
LOCAL_DEBUG_CALLER_OUT( "imout->next_line = %d, imout->im->height = %d", imout->next_line, imout->im->height );
      if( imout->next_line < (int)imout->im->height && imout->next_line >= 0 )
      {
            CARD8 chan_fill[4];
            chan_fill[IC_RED]   = ARGB32_RED8  (to_store->back_color);
            chan_fill[IC_GREEN] = ARGB32_GREEN8(to_store->back_color);
            chan_fill[IC_BLUE]  = ARGB32_BLUE8 (to_store->back_color);
            chan_fill[IC_ALPHA] = ARGB32_ALPHA8(to_store->back_color);
            if( imout->tiling_step > 0 )
            {
                  int bytes_count ;
                  register int i, color ;
                  int line = imout->next_line ;
                  int range = (imout->tiling_range ? imout->tiling_range:imout->im->height);
                  int max_i = MIN((int)imout->im->height,line+range), min_i = MAX(0,line-range) ;
                  int step =  imout->bottom_to_top*imout->tiling_step;

                  for( color = 0 ; color < IC_NUM_CHANNELS ; color++ )
                  {
                        if( get_flags(to_store->flags,0x01<<color))
                              bytes_count = asimage_add_line(imout->im, color, to_store->channels[color]+to_store->offset_x, line);
                        else if( chan_fill[color] != imout->chan_fill[color] )
                              bytes_count = asimage_add_line_mono( imout->im, color, (CARD8)chan_fill[color], line);
                        else
                        {
                              asimage_erase_line( imout->im, color, line );
                              for( i = line+step ; i < max_i && i >= min_i ; i+=step )
                                    asimage_erase_line( imout->im, color, i );
                              continue;
                        }
                        for( i = line+step ; i < max_i && i >= min_i ; i+=step )
                        {
/*                                  fprintf( stderr, "copy-encoding color %d, from lline %d to %d, %d bytes\n", color, imout->next_line, i, bytes_count );*/
                              asimage_dup_line( imout->im, color, line, i, bytes_count );
                        }
                  }
            }else
            {
                  register int color ;
                  for( color = 0 ; color < IC_NUM_CHANNELS ; color++ )
                  {
                        if( get_flags(to_store->flags,0x01<<color))
                        {
                              LOCAL_DEBUG_OUT( "encoding line %d for component %d offset = %d ", imout->next_line, color, to_store->offset_x );
                              asimage_add_line(imout->im, color, to_store->channels[color]+to_store->offset_x, imout->next_line);
                        }else if( chan_fill[color] != imout->chan_fill[color] )
                        {
                              LOCAL_DEBUG_OUT( "filling line %d for component %d with value %X", imout->next_line, color, chan_fill[color] );
                              asimage_add_line_mono( imout->im, color, chan_fill[color], imout->next_line);
                        }else
                        {
                              LOCAL_DEBUG_OUT( "erasing line %d for component %d", imout->next_line, color );
                              asimage_erase_line( imout->im, color, imout->next_line );
                        }
                  }
            }
      }
      imout->next_line += imout->bottom_to_top;
}

inline static void
tile_argb32_line( ARGB32 *data, unsigned int line, int step, unsigned int width, unsigned int height, int range )
{
      register int i ;
      ARGB32 *src_line = data+width*line ;
      ARGB32 *dst_line = src_line+width ;
      int max_i = MIN((int)height,(int)line+range), min_i = MAX(0,(int)line-range) ;

      for( i = line+step ; i < max_i && i >= min_i ; i+=step )
      {
            memcpy( dst_line, src_line, width*sizeof(ARGB32));
            dst_line += step;
      }
}

void
encode_image_scanline_argb32( ASImageOutput *imout, ASScanline *to_store )
{
      register ARGB32 *data = imout->im->alt.argb32 ;
      if( imout->next_line < (int)imout->im->height && imout->next_line >= 0 )
      {
            register int x = imout->im->width;
            register CARD32 *alpha = to_store->alpha ;
            register CARD32 *red = to_store->red ;
            register CARD32 *green = to_store->green ;
            register CARD32 *blue = to_store->blue ;
            if( !get_flags(to_store->flags, SCL_DO_RED) )
                  set_component( red, ARGB32_RED8(to_store->back_color), 0, to_store->width );
            if( !get_flags(to_store->flags, SCL_DO_GREEN) )
                  set_component( green, ARGB32_GREEN8(to_store->back_color), 0, to_store->width );
            if( !get_flags(to_store->flags, SCL_DO_BLUE) )
                  set_component( blue , ARGB32_BLUE8(to_store->back_color), 0, to_store->width );

            data += x*imout->next_line ;
            if( !get_flags(to_store->flags, SCL_DO_ALPHA) )
                  while( --x >= 0 )
                        data[x] = MAKE_ARGB32( 0xFF, red[x], green[x], blue[x] );
            else
                  while( --x >= 0 )
                        data[x] = MAKE_ARGB32( alpha[x], red[x], green[x], blue[x] );

            if( imout->tiling_step > 0 )
                  tile_argb32_line( imout->im->alt.argb32, imout->next_line,
                                    imout->bottom_to_top*imout->tiling_step,
                                            imout->im->width, imout->im->height,
                                            (imout->tiling_range ? imout->tiling_range:imout->im->height));
            imout->next_line += imout->bottom_to_top;
      }
}


void
output_image_line_top( ASImageOutput *imout, ASScanline *new_line, int ratio )
{
      ASScanline *to_store = NULL ;
      /* caching and preprocessing line into our buffer : */
      if( new_line )
      {
            if( ratio > 1 )
            SCANLINE_FUNC_FILTERED(divide_component,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
            else
            SCANLINE_FUNC_FILTERED(copy_component,*(new_line),*(imout->available),NULL,imout->available->width);
            imout->available->flags = new_line->flags ;
            imout->available->back_color = new_line->back_color ;
      }
      /* copying/encoding previously cahced line into destination image : */
      if( imout->used != NULL )
      {
            if( new_line != NULL )
            SCANLINE_FUNC_FILTERED(best_output_filter,*(imout->used),*(imout->available),0,imout->available->width);
            else
            SCANLINE_MOD_FILTERED(fine_output_filter_mod,*(imout->used),0,imout->used->width);
            to_store = imout->used ;
      }
      if( to_store )
    {
            imout->encode_image_scanline( imout, to_store );
    }
      /* rotating the buffers : */
      if( imout->buffer_shift > 0 )
      {
            if( new_line == NULL )
                  imout->used = NULL ;
            else
                  imout->used = imout->available ;
            imout->available = &(imout->buffer[0]);
            if( imout->available == imout->used )
                  imout->available = &(imout->buffer[1]);
      }
}

void
output_image_line_fine( ASImageOutput *imout, ASScanline *new_line, int ratio )
{
      /* caching and preprocessing line into our buffer : */
    if( new_line )
      {
        SCANLINE_FUNC_FILTERED(fine_output_filter, *(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
            imout->available->flags = new_line->flags ;
            imout->available->back_color = new_line->back_color ;
/*      SCANLINE_MOD(print_component,*(imout->available),0, new_line->width ); */
            /* copying/encoding previously cached line into destination image : */
            imout->encode_image_scanline( imout, imout->available );
      }
}

void
output_image_line_fast( ASImageOutput *imout, ASScanline *new_line, int ratio )
{
      /* caching and preprocessing line into our buffer : */
      if( new_line )
      {
        SCANLINE_FUNC_FILTERED(fast_output_filter,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
            imout->available->flags = new_line->flags ;
            imout->available->back_color = new_line->back_color ;
            imout->encode_image_scanline( imout, imout->available );
      }
}

void
output_image_line_direct( ASImageOutput *imout, ASScanline *new_line, int ratio )
{
      /* caching and preprocessing line into our buffer : */
      if( new_line )
      {
        if( ratio > 1)
            {
            SCANLINE_FUNC_FILTERED(divide_component,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
                  imout->available->flags = new_line->flags ;
                  imout->available->back_color = new_line->back_color ;
                  imout->encode_image_scanline( imout, imout->available );
            }else
                  imout->encode_image_scanline( imout, new_line );
      }
}


Generated by  Doxygen 1.6.0   Back to index