//
//  Title:  Bitmap Image Class Implementation
//
//  Copyright 1997-1999, Colosseum Builders, Inc.
//  All rights reserved.
//
//  Colosseum Builders, Inc. makes no warranty, expressed or implied
//  with regards to this software. It is provided as is.
//
//  Author:  John M. Miano (miano@colosseumbuilders.com)
//
//  Date:    March 15, 1999
//
//  Version: 3
//
//  Description:
//
//    BitmapImage and related class definitions.
//
//  Revision History:
//
//    Nov 1999 - Switched to a more system-neutal internal format
//               using 4-bytes per pixel. This allows
//               us to add an alpha channel.
//

#include "bitmapimage.h"
#include <algorithm>
using namespace std ;
using namespace Colosseum ;

const BitmapImage::Pixel ZEROPIXEL = { 0, 0, 0, 0 } ;
const int MAXPIXELVALUE = 0xFF ;
namespace Colosseum
{
//
//  Description:
//
//    Default Constructor
//
BitmapImage::BitmapImage ()
: image_data (0),
  image_height (0),
  image_width (0)
{
  return ;
}


BitmapImage::BitmapImage (unsigned int initialwidth,
                          unsigned int initialheight,
                          BitmapImage::Pixel background)
: image_data (0),
  image_height (0),
  image_width (0)
{
  setSize (initialwidth, initialheight) ;
  fill (image_data, image_data + image_size, background) ;
  return ;
}

//
//  Description:
//
//    Copy Constructor
//
BitmapImage::BitmapImage (const BitmapImage &source)
: image_data  (0)
{
  doCopy (source) ;
  return ;
}

//
//  Description:
//
//    Assignment Operator
//
//  Parameters:
//    source:  The object to copy
//
BitmapImage &BitmapImage::operator=(const BitmapImage &source)
{
  if (&source == this)
    return *this ;

  doCopy (source) ;
  return *this ;
}


//
//  Description:
//
//    Class Destructor
//
BitmapImage::~BitmapImage ()
{
  delete [] image_data ; image_data = 0 ;
  return ;
}

//
//  Description:
//
//    Common copy function for use by the copy constructor and assignment
//    operator.
//
//  Parameters:
//    source:  The object to copy
//
void BitmapImage::doCopy (const BitmapImage &source)
{
  image_width = source.image_width ;
  image_height = source.image_height ;
  delete [] image_data ;
  image_data = new Pixel [image_width * image_height] ;
  copy (source.image_data, source.image_data + image_width * image_height, image_data) ;
  return ;
}

//
//  Description:
//
//    This function allocates space to hold an image of the specified size.
//    The colormap (if used) and the image data are all set to zeros.
//
//  Parameters:
//    cc: Number of colors. Ignored for 24-bit bitmaps
//    bits: Number of bits per pixel.
//    ww, hh: Bitmap size
//
void BitmapImage::setSize (unsigned int ww,     // Width
                           unsigned int hh)     // Height
{
  image_height = hh ;
  image_width = ww ;
  image_size = image_height * image_width ;
  delete [] image_data ;
  image_data = new Pixel [image_size] ;
  fill (image_data, image_data + image_size, ZEROPIXEL) ;
  return ;
}

//
//  Description:
//
//    This function clears out the image.
//
void BitmapImage::clearImage ()
{
  delete [] image_data ; image_data = 0 ;
  image_height = image_width = 0 ;
  return ;
}

//
//  Description:
//
//    This function performs an alpha merge of another
//    image to this one.
//
//  Parameters:
//
//    image: The image to merge
//    xpos, ypos: The location to place the new image.
//
void BitmapImage::mergeImage (const BitmapImage &image,
                              int xpos, int ypos)
{
  // In the loop we map the source to the destination.
  const Pixel *src = &image [0] ;
  for (int srcrow = 0, dstrow = ypos ;
       srcrow < image.getHeight () ;
       ++ srcrow, ++ dstrow)
  {
    Pixel *dst = &image_data [dstrow * image_width + xpos] ;
    for (int srccol = 0, dstcol = xpos ;
         srccol < image.getWidth () ;
         ++ srccol, ++ dstcol, ++ src, ++ dst)
    {
      // Ensure that the current pixel is not off the edge of the destination.
      if (dstrow < image_height && dstrow >= 0 && dstcol < image_width && dstcol >= 0)
      {
        dst->red = (src->alpha * src->red + (MAXPIXELVALUE - src->alpha) * dst->red)
                 / MAXPIXELVALUE ;
        dst->green = (src->alpha * src->green + (MAXPIXELVALUE - src->alpha) * dst->green)
                 / MAXPIXELVALUE ;
        dst->blue = (src->alpha * src->blue + (MAXPIXELVALUE - src->alpha) * dst->blue)
                 / MAXPIXELVALUE ;
        if (src->alpha > dst->alpha)
          dst->alpha = src->alpha ;
      }
    }
  }
}

//
// Description:
//
//  Class Copy Constructor
//
BitmapImageCoder::BitmapImageCoder (const BitmapImageCoder &source)
: progress_function (source.progress_function),
  progress_data (source.progress_data)
{
  return ;
}
//
// Description:
//
//  Class assignment operator
//
BitmapImageCoder &BitmapImageCoder::operator=(
                                const BitmapImageCoder &source)
{
  if (this == &source)
    return *this ;

  progress_function = source.progress_function ;
  progress_data = source.progress_data ;
  return *this ;
}
//
// Description:
//
//  This function assigns a progress function and progress data
//  to an encoder or decoder.
//    
void BitmapImageCoder::setProgressFunction (PROGRESSFUNCTION func,
                                                   void *data)
{
  progress_function = func ;
  progress_data = data ;
  return ;
}


} // End Namespace Colosseum
