//////////////////////////////////////////////////////////////////////////////
// Copyright 1994 Brad Pitzel
//
// Feel free to use/distribute/modify as long as credit/copyrights for myself 
// and contributors are included.
//////////////////////////////////////////////////////////////////////////////

#ifndef __BPbitmap__
#define __BPbitmap__

#include <stdlib.h>	// for NULL
#include <iostream.h>
#include <math.h>
#include <string.h>	// for memcpy

class Bitmap;
typedef Bitmap *BitmapPtr;

//////////////////////////////////////////////////////////////////////////
// Object to load various image formats.  Used by Bitmap class.
//
// ImageLoader is an abstract base class, i.e. you cannot instantiate
// objects directly from it (except as parameters in a function).
//
// Derive format specific classes from this class.
// eg: derive PcxImageLoader to handle .pcx files,  RawImageLoader for .raw
// files, etc..
//
// The load() function handles loading the image, palette, or both.
// This function is specificly coded for the file format, the rest
// of the class is generic.
//
// Derived classes need to define load() to set Vimage, Vpalette,
// Vwidth, Vheight, etc.., accordingly for a given image file format
//
// load() functions return EXIT_SUCCESS, or EXIT_FAILURE. (from stdlib.h)
// 
// load() can assume Vimage/Vpalette points to nothing upon entry. Must
// ensure Vimage (or Vpalette) is NULL after an image loading (or palette
// loading) error. 
//

// flags for telling load() what to load!
#define LOAD_IMAGE 1
#define LOAD_PALETTE 2

class ImageLoader
    {
    public:
	ImageLoader() : Vimage(NULL), Vpalette(NULL)
		{
		freeImage();
		freePalette();
		};

	virtual ~ImageLoader()
		{
		freeImage();
		freePalette();
		}

	// by default, load() tries to load both image and palette
	virtual int	load(const char *file, 
			     char flags= (LOAD_IMAGE|LOAD_PALETTE)
			    );

	// function to access the private variables.	
	// This funcs only return valid info if load() has
	// been successfully called first.
	int		width()  const { return Vwidth; }
	int		height() const { return Vheight; }
	unsigned char 	*image() const { return Vimage; }
	unsigned char *palette() const { return Vpalette; }
	int	numColors() 	 const { return VnumColors; }
	int	imageByteSize()  const { return VimageByteSize; }
	int	paletteByteSize()  const { return VpaletteByteSize; }

	// clear all private vars, free up allocated mem.
	void		freeImage();
	void		freePalette();

	// if we assign the image data from the loader to an external object
	// and the external object wants to manage the allocated memory
	// for the image, the ImageLoader shouldn't delete the mem.
	// You can prevent ImageLoader from freeing up the image or
	// palette memory by calling these functions:
	void releaseImageOwnership() { Vimage=NULL; }
	void releasePaletteOwnership() { Vpalette=NULL; }

    protected:
	// image specific load routine 
	// Must be defined by derived classes.
	virtual int	loadFile(const char *file, char flags)=0;

    	int		Vwidth;
    	int		Vheight;
    	int		VimageByteSize;		// size of image in bytes
    	int		VpaletteByteSize;	// size of palette in bytes
    	int		VnumColors;		// # of colors in palette
    	
	unsigned char 	*Vimage;	// image data
	unsigned char 	*Vpalette;	// palette data
    };


////////////////////////////////////////////////////////////////////////////
// What is this class for?
//
// Bitmap describes a simple bitmap object.  Rarely will you directly
// use this class. Rather, you should derive another class that defines more 
// functionality, ie add in put() functions for environment specific code 
// to display the bitmap on screen (or maybe in a window).
//
// A bitmap object is an image that can be displayed on screen.  It is defined
// by: the raw image data, and width/height/size attributes.
// The object takes care of allocating/deallocating memory for the image data
// automatically.
//
// There are functions for copying Bitmap objects, and for simple 90 degree
// rotations.

// Note: 'V' prefix indicates class variable

class Bitmap {
    public:
	Bitmap() : Vwidth(0), Vheight(0), Vsize(0),
		   Vimage(NULL), VallocImage(0) {};
    
        Bitmap(int w, int h) : Vwidth(w), Vheight(h), Vsize(w*h),
        		       Vimage(NULL), VallocImage(0) {};

        // copy constructor
	Bitmap( const Bitmap& b )
		{ 
		copy( b ); 
		}

	// destructor
	~Bitmap() 
		{ 
		if (VallocImage) delete [] Vimage; 
		}

	// Copy: make 'this' bitmap be a clone of bitmap 'b'
	void copy( const Bitmap& b );


	// Note:  The 90 degree rotate functions only work with square
	// bitmaps (width==height).
	
	// rotate bitmap 90 clockwise
	void rotc90();
	// rotate bitmap 90 counter-clockwise
	void rotcc90();

	// p is a pointer to a width*height sized buffer of colormap
	// values (0-255) that defines the bitmap. If you use this method
	// to assign image data to the bitmap, you are responsible for
	// managing the memory. Ie, if you allocated the memory that p points
	// to, make sure you deallocate it after the object is deleted.
	// (Also make sure you set the bitmaps width/height correctly).
	inline void setMap( unsigned char *p )
		{
		if (VallocImage) delete [] Vimage;
		VallocImage = 0; 
		Vimage = p; 
		}
		
	// if we set the bitmap from an ImageLoader object, then we are
	// responsible for managing the memory.
	void setMap( ImageLoader &IL )
		{
		if (VallocImage) delete [] Vimage;
		Vimage = IL.image();
		Vwidth = IL.width();
		Vheight= IL.height();
		Vsize  = Vwidth*Vheight;
		VallocImage = 0;
		
		if (Vimage!=NULL)
			{
			// Bitmap takes over memory management of image data
			VallocImage=1;
			IL.releaseImageOwnership();
			}
		}

	// returns a pointer to the bitmap's raw image data
	inline const unsigned char* map() const { return Vimage; }
	
	inline int  width() const 	{ return Vwidth; }
    	inline int  height() const	{ return Vheight; }
	inline int  size() const;

    protected:

        unsigned char   *Vimage;	// pointer to bitmap
    	char	VallocImage;	// flag: 1=mem was allocated for Vimage, 0 otherwise
        int	Vwidth;
        int	Vheight;
        int	Vsize;

	// allocates memory for the bitmap
	void	allocMem( int w, int h );

	// calc offset into bitmap given x,y co-ord
	int offset(int x, int y) const;

    };

inline int Bitmap::offset(int x, int y) const return r;
	{
	r = y*Vwidth+x;
	}


inline int Bitmap::size() const return r;
	{ 
	r = Vsize; 
	}

//////////////////////////////////////////////////////////////////////////
// 256 color Palette object - NOT COMPLETED OR USED
/*
typedef unsigned char Color[3];
typedef Color	ColorMap[256];
class Palette
    {
    public:
   	Palette() : Vpalette(NULL), Valloc(0)
   		{};
   		
   	void	set(PaletteData *p)
   		{
		this->free();
   		Vpalette = p;
   		Valloc = 0;
   		}
    
	PaletteData     
    
    private:
	void	free()
		{
		if (Valloc) delete [] Vpalette;
		Valloc=0;
		}

	PaletteData *Vpalette;
	char	Valloc;
	int	VpaletteByteSize;
	int	VnumColors;

    };
 */   




#endif
