Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#define XMD_H

#include <windows.h>
#include "ImageLib.h"
#include "png\png.h"
#include <math.h>
#include <tchar.h>
#include "..\PakLib\PakInterface.h"

extern "C"
{
#include "jpeg\jpeglib.h"
#include "jpeg\jerror.h"
}

//#include "jpeg2000/jasper.h"

using namespace ImageLib;

Image::Image()
{
        mWidth = 0;
        mHeight = 0;
        mBits = NULL;
}

Image::~Image()
{
        delete mBits;
}

int     Image::GetWidth()
{
        return mWidth;
}

int     Image::GetHeight()
{
        return mHeight;
}

unsigned long* Image::GetBits()
{
        return mBits;
}

//////////////////////////////////////////////////////////////////////////
// PNG Pak Support

static void png_pak_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
        png_size_t check;

        /* fread() returns 0 on error, so it is OK to store this in a png_size_t
        * instead of an int, which is what fread() actually returns.
        */

        check = (png_size_t)p_fread(data, (png_size_t)1, length,
                (PFILE*)png_ptr->io_ptr);

        if (check != length)
        {
                png_error(png_ptr, "Read Error");
        }
}

Image* GetPNGImage(const std::string& theFileName)
{
        png_structp png_ptr;
        png_infop info_ptr;
        unsigned int sig_read = 0;
        png_uint_32 width, height;
        int bit_depth, color_type, interlace_type;
        PFILE *fp;

        if ((fp = p_fopen(theFileName.c_str(), "rb")) == NULL)
                return NULL;

        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
          NULL, NULL, NULL);
        png_set_read_fn(png_ptr, (png_voidp)fp, png_pak_read_data);

        if (png_ptr == NULL)
        {
                p_fclose(fp);
                return NULL;
        }

        /* Allocate/initialize the memory for image information.  REQUIRED. */
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
                p_fclose(fp);
                png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
                return NULL;
        }

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

        if (setjmp(png_ptr->jmpbuf))
        {
                /* Free all of the memory associated with the png_ptr and info_ptr */
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                p_fclose(fp);
                /* If we get here, we had a problem reading the file */
                return NULL;
        }

        //png_init_io(png_ptr, fp);

        //png_ptr->io_ptr = (png_voidp)fp;

        png_read_info(png_ptr, info_ptr);
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, NULL, NULL);

        /* Add filler (or alpha) byte (before/after each RGB triplet) */
        png_set_expand(png_ptr);
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        //png_set_gray_1_2_4_to_8(png_ptr);
        png_set_palette_to_rgb(png_ptr);
        png_set_gray_to_rgb(png_ptr);
        png_set_bgr(png_ptr);

//      int aNumBytes = png_get_rowbytes(png_ptr, info_ptr) * height / 4;
        unsigned long* aBits = new unsigned long[width*height];
        unsigned long* anAddr = aBits;
        for (int i = 0; i < height; i++)
        {
                png_read_rows(png_ptr, (png_bytepp) &anAddr, NULL, 1);
                anAddr += width;
        }

        /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
        png_read_end(png_ptr, info_ptr);

        /* clean up after the read, and free any memory allocated - REQUIRED */
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

        /* close the file */
        p_fclose(fp);

        Image* anImage = new Image();
        anImage->mWidth = width;
        anImage->mHeight = height;
        anImage->mBits = aBits;

        return anImage;
}

Image* GetTGAImage(const std::string& theFileName)
{
        PFILE* aTGAFile = p_fopen(theFileName.c_str(), "rb");
        if (aTGAFile == NULL)
                return NULL;

        BYTE aHeaderIDLen;
        p_fread(&aHeaderIDLen, sizeof(BYTE), 1, aTGAFile);

        BYTE aColorMapType;
        p_fread(&aColorMapType, sizeof(BYTE), 1, aTGAFile);
       
        BYTE anImageType;
        p_fread(&anImageType, sizeof(BYTE), 1, aTGAFile);

        WORD aFirstEntryIdx;
        p_fread(&aFirstEntryIdx, sizeof(WORD), 1, aTGAFile);

        WORD aColorMapLen;
        p_fread(&aColorMapLen, sizeof(WORD), 1, aTGAFile);

        BYTE aColorMapEntrySize;
        p_fread(&aColorMapEntrySize, sizeof(BYTE), 1, aTGAFile);       

        WORD anXOrigin;
        p_fread(&anXOrigin, sizeof(WORD), 1, aTGAFile);

        WORD aYOrigin;
        p_fread(&aYOrigin, sizeof(WORD), 1, aTGAFile);

        WORD anImageWidth;
        p_fread(&anImageWidth, sizeof(WORD), 1, aTGAFile);     

        WORD anImageHeight;
        p_fread(&anImageHeight, sizeof(WORD), 1, aTGAFile);    

        BYTE aBitCount = 32;
        p_fread(&aBitCount, sizeof(BYTE), 1, aTGAFile);

        BYTE anImageDescriptor = 8 | (1<<5);
        p_fread(&anImageDescriptor, sizeof(BYTE), 1, aTGAFile);

        if ((aBitCount != 32) ||
                (anImageDescriptor != (8 | (1<<5))))
        {
                p_fclose(aTGAFile);
                return NULL;
        }

        Image* anImage = new Image();

        anImage->mWidth = anImageWidth;
        anImage->mHeight = anImageHeight;
        anImage->mBits = new unsigned long[anImageWidth*anImageHeight];

        p_fread(anImage->mBits, 4, anImage->mWidth*anImage->mHeight, aTGAFile);

        p_fclose(aTGAFile);

        return anImage;
}

int ReadBlobBlock(PFILE* fp, char* data)
{
        unsigned char aCount = 0;
        p_fread(&aCount, sizeof(char), 1, fp);
        p_fread(data, sizeof(char), aCount, fp);
        return aCount;
}

Image* GetGIFImage(const std::string& theFileName)
{
        #define BitSet(byte,bit)  (((byte) & (bit)) == (bit))
        #define LSBFirstOrder(x,y)  (((y) << 8) | (x))

        int
                opacity,
                status;

        register int i;

        register unsigned char *p;

        unsigned char
                background,
                c,
                flag,
                *global_colormap,
                header[1664],
                magick[12];

        unsigned int
                delay,
                dispose,
                global_colors,
                image_count,
                iterations;

        /*
        Open image file.
        */


        PFILE *fp;

        if ((fp = p_fopen(theFileName.c_str(), "rb")) == NULL)
                return NULL;
        /*
        Determine if this is a GIF file.
        */

        status=p_fread(magick, sizeof(char), 6, fp);

        if (((strncmp((char *) magick,"GIF87",5) != 0) &&
                (strncmp((char *) magick,"GIF89",5) != 0)))
                return NULL;

        global_colors=0;
        global_colormap=(unsigned char *) NULL;

        short pw;
        short ph;

        p_fread(&pw, sizeof(short), 1, fp);
        p_fread(&ph, sizeof(short), 1, fp);
        p_fread(&flag, sizeof(char), 1, fp);
        p_fread(&background, sizeof(char), 1, fp);
        p_fread(&c, sizeof(char), 1, fp);

        if (BitSet(flag,0x80))
        {
                /*
                opacity global colormap.
                */

                global_colors=1 << ((flag & 0x07)+1);
                global_colormap=new unsigned char[3*global_colors];
                if (global_colormap == (unsigned char *) NULL)
                return NULL;

                p_fread(global_colormap, sizeof(char), 3*global_colors, fp);
        }

        delay=0;
        dispose=0;
        iterations=1;
        opacity=(-1);
        image_count=0;

        for ( ; ; )
        {
                if (p_fread(&c, sizeof(char), 1, fp) == 0)
                break;

                if (c == ';')
                break;  /* terminator */
                if (c == '!')
                {
                        /*
                        GIF Extension block.
                        */

                        p_fread(&c, sizeof(char), 1, fp);

                        switch (c)
                        {
                        case 0xf9:
                                {
                                        /*
                                        Read Graphics Control extension.
                                        */

                                        while (ReadBlobBlock(fp,(char *) header) > 0);

                                        dispose=header[0] >> 2;
                                        delay=(header[2] << 8) | header[1];
                                        if ((header[0] & 0x01) == 1)
                                        opacity=header[3];
                                        break;
                                }
                        case 0xfe:
                                {
                                        char *comments;
                                        int length;

                                        /*
                                        Read Comment extension.
                                        */

                                        comments=(char *) NULL;
                                        for ( ; ; )
                                        {
                                                length=ReadBlobBlock(fp,(char *) header);
                                                if (length <= 0)
                                                break;
                                                if (comments == NULL)
                                                {
                                                        comments= new char[length+1];
                                                        if (comments != (char *) NULL)
                                                        *comments='\0';
                                                }

                                                header[length]='\0';
                                                strcat(comments,(char *) header);
                                        }
                                        if (comments == (char *) NULL)
                                                break;

                                        delete comments;
                                        break;
                                }
                        case 0xff:
                                {
                                        int
                                        loop;

                                        /*
                                        Read Netscape Loop extension.
                                        */

                                        loop=false;
                                        if (ReadBlobBlock(fp,(char *) header) > 0)
                                        loop=!strncmp((char *) header,"NETSCAPE2.0",11);
                                        while (ReadBlobBlock(fp,(char *) header) > 0)
                                        if (loop)
                                        iterations=(header[2] << 8) | header[1];
                                        break;
                                }
                        default:
                                {
                                        while (ReadBlobBlock(fp,(char *) header) > 0);
                                        break;
                                }
                        }
                }

                if (c != ',')
                        continue;

                if (image_count != 0)
                {
                        /*
                        Allocate next image structure.
                        */


                        /*AllocateNextImage(image_info,image);
                        if (image->next == (Image *) NULL)
                        {
                        DestroyImages(image);
                        return((Image *) NULL);
                        }
                        image=image->next;
                        MagickMonitor(LoadImagesText,TellBlob(image),image->filesize);*/

                }
                image_count++;

                short pagex;
                short pagey;
                short width;
                short height;
                int colors;
                bool interlaced;

                p_fread(&pagex, sizeof(short), 1, fp);
                p_fread(&pagey, sizeof(short), 1, fp);
                p_fread(&width, sizeof(short), 1, fp);
                p_fread(&height, sizeof(short), 1, fp);
                p_fread(&flag, sizeof(char), 1, fp);

                colors=!BitSet(flag,0x80) ? global_colors : 1 << ((flag & 0x07)+1);
                unsigned long* colortable = new unsigned long[colors];

                interlaced = BitSet(flag,0x40);

                delay=0;
                dispose=0;
                iterations=1;
                /*if (image_info->ping)
                {
                f (opacity >= 0)
                /image->matte=true;

                CloseBlob(image);
                return(image);
                }*/

                if ((width == 0) || (height == 0))
                        return NULL;
                /*
                Inititialize colormap.
                */

                /*if (!AllocateImageColormap(image,image->colors))
                ThrowReaderException(ResourceLimitWarning,"Memory allocation failed",
                image);*/

                if (!BitSet(flag,0x80))
                {
                        /*
                        Use global colormap.
                        */

                        p=global_colormap;
                        for (i=0; i < (int) colors; i++)
                        {
                                int r = *p++;
                                int g = *p++;
                                int b = *p++;

                                colortable[i] = 0xFF000000 | (r << 16) | (g << 8) | (b);
                        }

                        //image->background_color=
                        //image->colormap[Min(background,image->colors-1)];
                }
                else
                {
                        unsigned char
                        *colormap;

                        /*
                        Read local colormap.
                        */

                        colormap=new unsigned char[3*colors];

                        int pos = p_ftell(fp);
                        p_fread(colormap, sizeof(char), 3*colors, fp);

                        p=colormap;
                        for (i=0; i < (int) colors; i++)
                        {
                                int r = *p++;
                                int g = *p++;
                                int b = *p++;

                                colortable[i] = 0xFF000000 | (r << 16) | (g << 8) | (b);
                        }
                        delete colormap;
                }

                /*if (opacity >= (int) colors)
                {
                for (i=colors; i < (opacity+1); i++)
                {
                image->colormap[i].red=0;
                image->colormap[i].green=0;
                image->colormap[i].blue=0;
                }
                image->colors=opacity+1;
                }*/

                /*
                Decode image.
                */

                //status=DecodeImage(image,opacity,exception);

                //if (global_colormap != (unsigned char *) NULL)
                // LiberateMemory((void **) &global_colormap);
                if (global_colormap != NULL)
                {
                        delete [] global_colormap;
                        global_colormap = NULL;
                }

                //while (image->previous != (Image *) NULL)
                //    image=image->previous;

                #define MaxStackSize  4096
                #define NullCode  (-1)

                int
                        available,
                        bits,
                        code,
                        clear,
                        code_mask,
                        code_size,
                        count,
                        end_of_information,
                        in_code,
                        offset,
                        old_code,
                        pass,
                        y;

                register int
                        x;

                register unsigned int
                        datum;

                short
                        *prefix;

                unsigned char
                        data_size,
                        first,
                        *packet,
                        *pixel_stack,
                        *suffix,
                        *top_stack;

                /*
                Allocate decoder tables.
                */


                packet=new unsigned char[256];
                prefix=new short[MaxStackSize];
                suffix=new unsigned char [MaxStackSize];
                pixel_stack= new unsigned char[MaxStackSize+1];

                /*
                Initialize GIF data stream decoder.
                */

                p_fread(&data_size, sizeof(char), 1, fp);
                clear=1 << data_size;
                end_of_information=clear+1;
                available=clear+2;
                old_code=NullCode;
                code_size=data_size+1;
                code_mask=(1 << code_size)-1;
                for (code=0; code < clear; code++)
                {
                        prefix[code]=0;
                        suffix[code]=(unsigned char) code;
                }
                /*
                Decode GIF pixel stream.
                */

                datum=0;
                bits=0;
                c=0;
                count=0;
                first=0;
                offset=0;
                pass=0;
                top_stack=pixel_stack;

                unsigned long* aBits = new unsigned long[width*height];

                register unsigned char *c = NULL;

                for (y=0; y < (int) height; y++)
                {
                        //q=SetImagePixels(image,0,offset,width,1);
                        //if (q == (PixelPacket *) NULL)
                        //break;
                        //indexes=GetIndexes(image);

                        unsigned long* q = aBits + offset*width;



                        for (x=0; x < (int) width; )
                        {
                                if (top_stack == pixel_stack)
                                {
                                        if (bits < code_size)
                                        {
                                                /*
                                                Load bytes until there is enough bits for a code.
                                                */

                                                if (count == 0)
                                                {
                                                        /*
                                                        Read a new data block.
                                                        */

                                                        int pos = p_ftell(fp);

                                                        count=ReadBlobBlock(fp,(char *) packet);
                                                        if (count <= 0)
                                                        break;
                                                        c=packet;
                                                }
                                                datum+=(*c) << bits;
                                                bits+=8;
                                                c++;
                                                count--;
                                                continue;
                                        }
                                        /*
                                        Get the next code.
                                        */

                                        code=datum & code_mask;
                                        datum>>=code_size;
                                        bits-=code_size;
                                        /*
                                        Interpret the code
                                        */

                                        if ((code > available) || (code == end_of_information))
                                        break;
                                        if (code == clear)
                                        {
                                                /*
                                                Reset decoder.
                                                */

                                                code_size=data_size+1;
                                                code_mask=(1 << code_size)-1;
                                                available=clear+2;
                                                old_code=NullCode;
                                                continue;
                                        }
                                        if (old_code == NullCode)
                                        {
                                                *top_stack++=suffix[code];
                                                old_code=code;
                                                first=(unsigned char) code;
                                                continue;
                                        }
                                        in_code=code;
                                        if (code >= available)
                                        {
                                                *top_stack++=first;
                                                code=old_code;
                                        }
                                        while (code >= clear)
                                        {
                                                *top_stack++=suffix[code];
                                                code=prefix[code];
                                        }
                                        first=suffix[code];
                                        /*
                                        Add a new string to the string table,
                                        */

                                        if (available >= MaxStackSize)
                                                break;
                                        *top_stack++=first;
                                        prefix[available]=old_code;
                                        suffix[available]=first;
                                        available++;
                                        if (((available & code_mask) == 0) && (available < MaxStackSize))
                                        {
                                                code_size++;
                                                code_mask+=available;
                                        }
                                        old_code=in_code;
                                }
                                /*
                                Pop a pixel off the pixel stack.
                                */

                                top_stack--;

                                int index=(*top_stack);

                                *q=colortable[index];

                                if (index == opacity)
                                        *q = 0;

                                x++;
                                q++;
                        }

                        if (!interlaced)
                                offset++;
                        else
                        {
                                switch (pass)
                                {
                                case 0:
                                default:
                                        {
                                                offset+=8;
                                                if (offset >= height)
                                                {
                                                        pass++;
                                                        offset=4;
                                                }
                                                break;
                                        }
                                case 1:
                                        {
                                                offset+=8;
                                                if (offset >= height)
                                                {
                                                        pass++;
                                                        offset=2;
                                                }
                                                break;
                                        }
                                case 2:
                                        {
                                                offset+=4;
                                                if (offset >= height)
                                                {
                                                        pass++;
                                                        offset=1;
                                                }
                                                break;
                                        }
                                case 3:
                                        {
                                                offset+=2;
                                                break;
                                        }
                                }
                        }

                        if (x < width)
                                break;

                        /*if (image->previous == (Image *) NULL)
                        if (QuantumTick(y,image->rows))
                        MagickMonitor(LoadImageText,y,image->rows);*/

                }
                delete pixel_stack;
                delete suffix;
                delete prefix;
                delete packet;

                delete colortable;

                //if (y < image->rows)
                //failed = true;

                Image* anImage = new Image();

                anImage->mWidth = width;
                anImage->mHeight = height;
                anImage->mBits = aBits;

                //TODO: Change for animation crap
                p_fclose(fp);
                return anImage;
        }

        p_fclose(fp);

        return NULL;
}

typedef struct my_error_mgr * my_error_ptr;

struct my_error_mgr
{
  struct jpeg_error_mgr pub;    /* "public" fields */

  jmp_buf setjmp_buffer;        /* for return to caller */
};

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  (*cinfo->err->output_message) (cinfo);

  /* Return control to the setjmp point */
  longjmp(myerr->setjmp_buffer, 1);

}

bool ImageLib::WriteJPEGImage(const std::string& theFileName, Image* theImage)
{
        FILE *fp;

        if ((fp = fopen(theFileName.c_str(), "wb")) == NULL)
                return false;

        struct jpeg_compress_struct cinfo;
        struct my_error_mgr jerr;

        cinfo.err = jpeg_std_error(&jerr.pub);
        jerr.pub.error_exit = my_error_exit;

        if (setjmp(jerr.setjmp_buffer))
        {
                /* If we get here, the JPEG code has signaled an error.
                 * We need to clean up the JPEG object, close the input file, and return.
                 */

                jpeg_destroy_compress(&cinfo);
                fclose(fp);
                return false;
        }

        jpeg_create_compress(&cinfo);

        cinfo.image_width = theImage->mWidth;
        cinfo.image_height = theImage->mHeight;
        cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
    cinfo.optimize_coding = 1;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 80, TRUE);

        jpeg_stdio_dest(&cinfo, fp);

        jpeg_start_compress(&cinfo, true);

        int row_stride = theImage->GetWidth() * 3;

        unsigned char* aTempBuffer = new unsigned char[row_stride];

        unsigned long* aSrcPtr = theImage->mBits;

        for (int aRow = 0; aRow < theImage->mHeight; aRow++)
        {
                unsigned char* aDest = aTempBuffer;

                for (int aCol = 0; aCol < theImage->mWidth; aCol++)
                {
                        unsigned long src = *(aSrcPtr++);

                        *aDest++ = (src >> 16) & 0xFF;
                        *aDest++ = (src >>  8) & 0xFF;
                        *aDest++ = (src      ) & 0xFF;
                }

                jpeg_write_scanlines(&cinfo, &aTempBuffer, 1);
        }

        delete [] aTempBuffer;

        jpeg_finish_compress(&cinfo);
        jpeg_destroy_compress(&cinfo);

        fclose(fp);

        return true;
}

bool ImageLib::WritePNGImage(const std::string& theFileName, Image* theImage)
{
        png_structp png_ptr;
        png_infop info_ptr;

        FILE *fp;

        if ((fp = fopen(theFileName.c_str(), "wb")) == NULL)
                return false;

        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
          NULL, NULL, NULL);

        if (png_ptr == NULL)
        {
                fclose(fp);
                return false;
        }

        // Allocate/initialize the memory for image information.  REQUIRED.
        info_ptr = png_create_info_struct(png_ptr);
        if (info_ptr == NULL)
        {
                fclose(fp);
                png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
                return false;
        }

   // Set error handling if you are using the setjmp/longjmp method (this is
   // the normal method of doing things with libpng).  REQUIRED unless you
   // set up your own error handlers in the png_create_write_struct() earlier.

        if (setjmp(png_ptr->jmpbuf))
        {
                // Free all of the memory associated with the png_ptr and info_ptr
                png_destroy_write_struct(&png_ptr, &info_ptr);
                fclose(fp);
                // If we get here, we had a problem writeing the file
                return NULL;
        }

        png_init_io(png_ptr, fp);

        png_color_8 sig_bit;
        sig_bit.red = 8;
        sig_bit.green = 8;
        sig_bit.blue = 8;
        /* if the image has an alpha channel then */
        sig_bit.alpha = 8;
        png_set_sBIT(png_ptr, info_ptr, &sig_bit);
        png_set_bgr(png_ptr);

        png_set_IHDR(png_ptr, info_ptr, theImage->mWidth, theImage->mHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA,
       PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

        // Add filler (or alpha) byte (before/after each RGB triplet)
        //png_set_expand(png_ptr);
        //png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        //png_set_gray_1_2_4_to_8(png_ptr);
        //png_set_palette_to_rgb(png_ptr);
        //png_set_gray_to_rgb(png_ptr);

        png_write_info(png_ptr, info_ptr);

        for (int i = 0; i < theImage->mHeight; i++)
        {
                png_bytep aRowPtr = (png_bytep) (theImage->mBits + i*theImage->mWidth);
                png_write_rows(png_ptr, &aRowPtr, 1);
        }

        // write rest of file, and get additional chunks in info_ptr - REQUIRED
        png_write_end(png_ptr, info_ptr);

        // clean up after the write, and free any memory allocated - REQUIRED
        png_destroy_write_struct(&png_ptr, &info_ptr);

        // close the file
        fclose(fp);

        return true;
}

bool ImageLib::WriteTGAImage(const std::string& theFileName, Image* theImage)
{
        FILE* aTGAFile = fopen(theFileName.c_str(), "wb");
        if (aTGAFile == NULL)
                return false;

        BYTE aHeaderIDLen = 0;
        fwrite(&aHeaderIDLen, sizeof(BYTE), 1, aTGAFile);

        BYTE aColorMapType = 0;
        fwrite(&aColorMapType, sizeof(BYTE), 1, aTGAFile);
       
        BYTE anImageType = 2;
        fwrite(&anImageType, sizeof(BYTE), 1, aTGAFile);

        WORD aFirstEntryIdx = 0;
        fwrite(&aFirstEntryIdx, sizeof(WORD), 1, aTGAFile);

        WORD aColorMapLen = 0;
        fwrite(&aColorMapLen, sizeof(WORD), 1, aTGAFile);

        BYTE aColorMapEntrySize = 0;
        fwrite(&aColorMapEntrySize, sizeof(BYTE), 1, aTGAFile);

        WORD anXOrigin = 0;
        fwrite(&anXOrigin, sizeof(WORD), 1, aTGAFile);

        WORD aYOrigin = 0;
        fwrite(&aYOrigin, sizeof(WORD), 1, aTGAFile);

        WORD anImageWidth = theImage->mWidth;
        fwrite(&anImageWidth, sizeof(WORD), 1, aTGAFile);      

        WORD anImageHeight = theImage->mHeight;
        fwrite(&anImageHeight, sizeof(WORD), 1, aTGAFile);     

        BYTE aBitCount = 32;
        fwrite(&aBitCount, sizeof(BYTE), 1, aTGAFile); 

        BYTE anImageDescriptor = 8 | (1<<5);
        fwrite(&anImageDescriptor, sizeof(BYTE), 1, aTGAFile);

        fwrite(theImage->mBits, 4, theImage->mWidth*theImage->mHeight, aTGAFile);

        fclose(aTGAFile);

        return true;
}

bool ImageLib::WriteBMPImage(const std::string& theFileName, Image* theImage)
{
        FILE* aFile = fopen(theFileName.c_str(), "wb");
        if (aFile == NULL)
                return false;

        BITMAPFILEHEADER aFileHeader;
        BITMAPINFOHEADER aHeader;

        memset(&aFileHeader,0,sizeof(aFileHeader));
        memset(&aHeader,0,sizeof(aHeader));

        int aNumBytes = theImage->mWidth*theImage->mHeight*4;

        aFileHeader.bfType = ('M'<<8) | 'B';
        aFileHeader.bfSize = sizeof(aFileHeader) + sizeof(aHeader) + aNumBytes;
        aFileHeader.bfOffBits = sizeof(aHeader);

        aHeader.biSize = sizeof(aHeader);
        aHeader.biWidth = theImage->mWidth;
        aHeader.biHeight = theImage->mHeight;
        aHeader.biPlanes = 1;
        aHeader.biBitCount = 32;
        aHeader.biCompression = BI_RGB;

        fwrite(&aFileHeader,sizeof(aFileHeader),1,aFile);
        fwrite(&aHeader,sizeof(aHeader),1,aFile);
        DWORD *aRow = theImage->mBits + (theImage->mHeight-1)*theImage->mWidth;
        int aRowSize = theImage->mWidth*4;
        for (int i=0; i<theImage->mHeight; i++, aRow-=theImage->mWidth)
                fwrite(aRow,4,theImage->mWidth,aFile);

        fclose(aFile);
        return true;
}

//////////////////////////////////////////////////////////////////////////
// JPEG Pak Reader

typedef struct {
        struct jpeg_source_mgr pub;     /* public fields */

        PFILE * infile;         /* source stream */
        JOCTET * buffer;                /* start of buffer */
        boolean start_of_file;  /* have we gotten any data yet? */
} pak_source_mgr;

typedef pak_source_mgr * pak_src_ptr;

#define INPUT_BUF_SIZE 4096

METHODDEF(void) init_source (j_decompress_ptr cinfo)
{
        pak_src_ptr src = (pak_src_ptr) cinfo->src;
        src->start_of_file = TRUE;
}

METHODDEF(boolean) fill_input_buffer (j_decompress_ptr cinfo)
{
        pak_src_ptr src = (pak_src_ptr) cinfo->src;
        size_t nbytes;

        nbytes = p_fread(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
        //((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))

        if (nbytes <= 0) {
                if (src->start_of_file) /* Treat empty input file as fatal error */
                        ERREXIT(cinfo, JERR_INPUT_EMPTY);
                WARNMS(cinfo, JWRN_JPEG_EOF);
                /* Insert a fake EOI marker */
                src->buffer[0] = (JOCTET) 0xFF;
                src->buffer[1] = (JOCTET) JPEG_EOI;
                nbytes = 2;
        }

        src->pub.next_input_byte = src->buffer;
        src->pub.bytes_in_buffer = nbytes;
        src->start_of_file = FALSE;

        return TRUE;
}

METHODDEF(void) skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
        pak_src_ptr src = (pak_src_ptr) cinfo->src;

        if (num_bytes > 0) {
                while (num_bytes > (long) src->pub.bytes_in_buffer) {
                        num_bytes -= (long) src->pub.bytes_in_buffer;
                        (void) fill_input_buffer(cinfo);
                }
                src->pub.next_input_byte += (size_t) num_bytes;
                src->pub.bytes_in_buffer -= (size_t) num_bytes;
        }
}

METHODDEF(void) term_source (j_decompress_ptr cinfo)
{
        /* no work necessary here */
}

void jpeg_pak_src (j_decompress_ptr cinfo, PFILE* infile)
{
        pak_src_ptr src;

        /* The source object and input buffer are made permanent so that a series
        * of JPEG images can be read from the same file by calling jpeg_stdio_src
        * only before the first one.  (If we discarded the buffer at the end of
        * one image, we'd likely lose the start of the next one.)
        * This makes it unsafe to use this manager and a different source
        * manager serially with the same JPEG object.  Caveat programmer.
        */

        if (cinfo->src == NULL) {       /* first time for this JPEG object? */
                cinfo->src = (struct jpeg_source_mgr *)
                        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                        sizeof(pak_source_mgr));
                src = (pak_src_ptr) cinfo->src;
                src->buffer = (JOCTET *)
                        (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                        INPUT_BUF_SIZE * sizeof(JOCTET));
        }

        src = (pak_src_ptr) cinfo->src;
        src->pub.init_source = init_source;
        src->pub.fill_input_buffer = fill_input_buffer;
        src->pub.skip_input_data = skip_input_data;
        src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
        src->pub.term_source = term_source;
        src->infile = infile;
        src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
        src->pub.next_input_byte = NULL; /* until buffer loaded */
}


Image* GetJPEGImage(const std::string& theFileName)
{
        PFILE *fp;

        if ((fp = p_fopen(theFileName.c_str(), "rb")) == NULL)
                return NULL;

        struct jpeg_decompress_struct cinfo;
        struct my_error_mgr jerr;

        cinfo.err = jpeg_std_error(&jerr.pub);
        jerr.pub.error_exit = my_error_exit;

        if (setjmp(jerr.setjmp_buffer))
        {
                /* If we get here, the JPEG code has signaled an error.
                 * We need to clean up the JPEG object, close the input file, and return.
                 */

                jpeg_destroy_decompress(&cinfo);
                p_fclose(fp);
                return 0;
        }

        jpeg_create_decompress(&cinfo);
        jpeg_pak_src(&cinfo, fp);
        jpeg_read_header(&cinfo, TRUE);
        jpeg_start_decompress(&cinfo);
        int row_stride = cinfo.output_width * cinfo.output_components;

        unsigned char** buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);

        unsigned long* aBits = new unsigned long[cinfo.output_width*cinfo.output_height];
        unsigned long* q = aBits;

        if (cinfo.output_components==1)
        {
                while (cinfo.output_scanline < cinfo.output_height)
                {
                        jpeg_read_scanlines(&cinfo, buffer, 1);

                        unsigned char* p = *buffer;
                        for (int i = 0; i < cinfo.output_width; i++)
                        {
                                int r = *p++;
                                *q++ = 0xFF000000 | (r << 16) | (r << 8) | (r);
                        }
                }
        }
        else
        {
                while (cinfo.output_scanline < cinfo.output_height)
                {
                        jpeg_read_scanlines(&cinfo, buffer, 1);

                        unsigned char* p = *buffer;
                        for (int i = 0; i < cinfo.output_width; i++)
                        {
                                int r = *p++;
                                int g = *p++;
                                int b = *p++;

                                *q++ = 0xFF000000 | (r << 16) | (g << 8) | (b);
                        }
                }
        }

        Image* anImage = new Image();
        anImage->mWidth = cinfo.output_width;
        anImage->mHeight = cinfo.output_height;
        anImage->mBits = aBits;

        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);

        p_fclose(fp);

        return anImage;
}

#if 0
Image* GetJPEG2000Image(const std::string& theFileName)
{
        DWORD aTick = GetTickCount();

        static bool inited = false;
        if (!inited)
        {
                inited = true;
                jas_init();
        }

        jas_stream_t* aStream = jas_stream_fopen(theFileName.c_str(),"rb");
        if (!aStream)
                return NULL;

        // Read Image Header
        int aFormat = jas_image_getfmt(aStream);
        if (aFormat < 0)
        {
                jas_stream_close(aStream);
                return NULL;
        }

        jas_image_t* aJasImage = jas_image_decode(aStream,aFormat,NULL);
        if (!aJasImage)
        {
                jas_stream_close(aStream);
                return NULL;
        }

        DWORD aDecodeTime = GetTickCount() - aTick;

        int aNumComponents = jas_image_numcmpts(aJasImage);
        if (aNumComponents<1 || aNumComponents>4)
        {
                jas_stream_close(aStream);
                jas_image_destroy(aJasImage);
                return NULL;
        }

        int i;
        int aMaxWidth = 0;
        int aMaxHeight = 0;
        for (i=0; i<aNumComponents; i++)
        {
                int hstep = jas_image_cmpthstep(aJasImage,i);
                int numHSteps = jas_image_cmptwidth(aJasImage,i);

                int vstep = jas_image_cmptvstep(aJasImage,i);
                int numVSteps = jas_image_cmptheight(aJasImage,i);

                int aWidth = jas_image_cmpttlx(aJasImage,i) + hstep*numHSteps;
                int aHeight = jas_image_cmpttly(aJasImage,i) + vstep*numVSteps;

                if (aWidth > aMaxWidth)
                        aMaxWidth = aWidth;

                if (aHeight > aMaxHeight)
                        aMaxHeight = aHeight;
        }

        // Read Image Data
        Image *anImage = new Image;
        anImage->mWidth = aMaxWidth;
        anImage->mHeight = aMaxHeight;
        anImage->mBits = new unsigned long[aMaxWidth * aMaxHeight];
        memset(anImage->mBits,0,aMaxWidth * aMaxHeight*4);

        int aColorModel = jas_image_clrspc(aJasImage);

        for (i=0; i<aNumComponents; i++)
        {
                int hstep = jas_image_cmpthstep(aJasImage,i);
                int vstep = jas_image_cmptvstep(aJasImage,i);
                int numHSteps = jas_image_cmptwidth(aJasImage,i);
                int numVSteps = jas_image_cmptheight(aJasImage,i);
                int xorig = jas_image_cmpttlx(aJasImage,i);
                int yorig = jas_image_cmpttly(aJasImage,i);
                bool sign = jas_image_cmptsgnd(aJasImage,i)?true:false;

                jas_matrix_t* aMatrix = jas_matrix_create(1,numHSteps);
                if (!aMatrix)
                {
                        delete anImage;
                        jas_image_destroy(aJasImage);
                        jas_stream_close(aStream);

                        return NULL;
                }

                int aShift = 8 - jas_image_cmptprec(aJasImage,i);
                if (aShift<0)
                {
                        delete anImage;
                        jas_matrix_destroy(aMatrix);
                        jas_image_destroy(aJasImage);
                        jas_stream_close(aStream);

                        return NULL;
                }

                unsigned long* destRow = anImage->mBits + yorig*numVSteps*anImage->GetWidth() + xorig*numHSteps;

                // color model
                int aComponentType = jas_image_cmpttype(aJasImage,i);
                int aColorType = JAS_IMAGE_CT_COLOR(aComponentType);

                switch (aColorType)
                {
                        case JAS_IMAGE_CT_RGB_R: aShift += 16; break;
                        case JAS_IMAGE_CT_RGB_G: aShift += 8; break;
                        case JAS_IMAGE_CT_RGB_B: break;
                        default: aShift += 24; break;
                }

                for (int y=0; y<numVSteps; y++)
                {
                        if (jas_image_readcmpt(aJasImage,i,0,y,numHSteps,1,aMatrix) )
                        {
                                delete anImage;
                                jas_matrix_destroy(aMatrix);
                                jas_image_destroy(aJasImage);
                                jas_stream_close(aStream);

                                return NULL;                   
                        }

                        unsigned long* dest = destRow;
                        for (int x=0; x<numHSteps; x++)
                        {
                                int aVal = jas_matrix_getv(aMatrix,x);
                                if (sign)
                                        aVal = (unsigned char)(aVal + 128);

                                aVal <<= aShift;

                                unsigned long *destRowWriter = dest;
                                for (int j=0; j<vstep; j++)
                                {
                                        unsigned long *destWriter = destRowWriter;
                                        for (int k=0; k<hstep; k++)
                                                *destWriter++ |= aVal;

                                        destRowWriter += anImage->GetWidth();
                                }

                                dest += hstep;
                        }
                        destRow += vstep*anImage->GetWidth();
                }

                // release decoding matrix
                jas_matrix_destroy(aMatrix);
        }

        DWORD aReadTime = GetTickCount() - aTick;
        char aBuf[512];
        sprintf(aBuf,"%d %d\n",aDecodeTime,aReadTime);
        OutputDebugString(aBuf);


        if (aNumComponents < 4) // add 255 alpha
        {
                int aSize = anImage->GetWidth()*anImage->GetHeight();
                unsigned long *dest = anImage->mBits;
                for (i=0; i<aSize; i++)
                        *dest++ |= 0xff000000;
        }

        jas_image_destroy(aJasImage);
        jas_stream_close(aStream);

        return anImage;
}
#else

#include "j2k-codec\j2k-codec.h"

HMODULE gJ2KCodec = NULL;
std::string gJ2KCodecKey = "Your registration here";

void ImageLib::InitJPEG2000()
{
        gJ2KCodec = ::LoadLibrary(_T("j2k-codec.dll"));
}

void ImageLib::CloseJPEG2000()
{
        if (gJ2KCodec != NULL)
        {
                ::FreeLibrary(gJ2KCodec);
                gJ2KCodec = NULL;
        }
}

void ImageLib::SetJ2KCodecKey(const std::string& theKey)
{
        gJ2KCodecKey = theKey;
}

int __stdcall Pak_seek(void *data_source, int offset)
{
        return p_fseek((PFILE*) data_source, offset, SEEK_SET);
}

int __stdcall Pak_read(void *ptr, int size, void *data_source)
{
        return p_fread(ptr, 1, size, (PFILE*) data_source);
}

void __stdcall Pak_close(void *data_source)
{      
}

Image* GetJPEG2000Image(const std::string& theFileName)
{
        if (gJ2KCodec != NULL)
        {
                PFILE* aFP = p_fopen(theFileName.c_str(), "rb");
                if (aFP == NULL)
                        return NULL;

                static int (__stdcall *fJ2K_getVersion)() = NULL;
                static void (__stdcall *fJ2K_Unlock)(const char*) = NULL;
                static void* (__stdcall *fJ2K_OpenCustom)(void*, J2K_Callbacks*) = NULL;
                static void* (__stdcall *fJ2K_OpenFile)(const char*) = NULL;
                static void (__stdcall *fJ2K_Close)(void*) = NULL;
                static int (__stdcall *fJ2K_GetInfo)(void*, int*, int*, int*) = NULL;
                static int (__stdcall *fJ2K_GetResolutionDimensions)(void*, int, int*, int*) = NULL;
                static int (__stdcall *fJ2K_Decode)(void*, unsigned char**, int*, char*, int*) = NULL;
                static int (__stdcall *fJ2K_getLastError)() = NULL;
                static const char* (__stdcall *fJ2K_getErrorStr)(int) = NULL;
                static bool loadFuncs = true;

                if (loadFuncs)
                {
                        loadFuncs = false;
                        *((void**)&fJ2K_getVersion) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_getVersion@0");
                        *((void**)&fJ2K_Unlock) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_Unlock@4");
                        *((void**)&fJ2K_OpenCustom) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_OpenCustom@8");
                        *((void**)&fJ2K_OpenFile) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_OpenFile@4");
                        *((void**)&fJ2K_Close) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_Close@4");
                        *((void**)&fJ2K_GetInfo) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_GetInfo@16");
                        *((void**)&fJ2K_GetResolutionDimensions) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_GetResolutionDimensions@16");
                        *((void**)&fJ2K_Decode) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_Decode@20");
                        *((void**)&fJ2K_getLastError) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_getLastError@0");
                        *((void**)&fJ2K_getErrorStr) = (void*)::GetProcAddress(gJ2KCodec, "_J2K_getErrorStr@4");

                        // j2k guys didn't use declare the export names. yay! now we have to update these mangled names any time the DLL changes.

                        if (!(fJ2K_getVersion != NULL &&
                                  fJ2K_Unlock != NULL &&
                                  fJ2K_OpenCustom != NULL &&
                                  fJ2K_OpenFile != NULL &&
                                  fJ2K_Close != NULL &&
                                  fJ2K_GetInfo != NULL &&
                                  fJ2K_GetResolutionDimensions != NULL &&
                                  fJ2K_Decode != NULL &&
                                  fJ2K_getLastError != NULL &&
                                  fJ2K_getErrorStr != NULL))
                        {
                                CloseJPEG2000();
                                return NULL;
                        }

                        int aJ2kVer = (*fJ2K_getVersion)();
                        if (aJ2kVer < 0x120000)
                        {
                                CloseJPEG2000();
                                return NULL;
                        }

                        (*fJ2K_Unlock)(gJ2KCodecKey.c_str());
                }

                J2K_Callbacks aCallbacks;
                aCallbacks.read = Pak_read;
                aCallbacks.seek = Pak_seek;
                aCallbacks.close = Pak_close;

                //theFileName.c_str()
                void* aJ2KImage = (*fJ2K_OpenCustom)(aFP, &aCallbacks);
                if (aJ2KImage == NULL)
                {
                        int anErrNum = (*fJ2K_getLastError)();
                        std::string anErrorMessage = (*fJ2K_getErrorStr)(anErrNum);
                        return NULL;
                }

                int aWidth, aHeight, aComponents;
                if ((*fJ2K_GetInfo)(aJ2KImage, &aWidth, &aHeight, &aComponents) != J2KERR_SUCCESS)
                {
                        (*fJ2K_Close)(aJ2KImage);
                        return NULL;
                }

                (*fJ2K_GetResolutionDimensions)(aJ2KImage, 0, &aWidth, &aHeight);
               
                unsigned long* aBuffer = new unsigned long[aWidth*aHeight];
                if (aBuffer == NULL)
                {
                        (*fJ2K_Close)(aJ2KImage);
                        return NULL;
                }

                char anOptsBuffer[32];
                strcpy(anOptsBuffer, "bpp=4,rl=0");

                int aSize = aWidth*aHeight*4;
                int aPitch = aWidth*4;
                if ((*fJ2K_Decode)(aJ2KImage, (unsigned char**)&aBuffer, &aSize, anOptsBuffer, &aPitch) != J2KERR_SUCCESS)
                {
                        (*fJ2K_Close)(aJ2KImage);
                        delete[] aBuffer;
                        return NULL;
                }
                (*fJ2K_Close)(aJ2KImage);

                ImageLib::Image* anImage = new ImageLib::Image;
                anImage->mBits = aBuffer;
                anImage->mWidth = aWidth;
                anImage->mHeight = aHeight;
                if (gIgnoreJPEG2000Alpha)
                {
                        DWORD *aPtr = anImage->mBits;
                        DWORD *anEnd = aPtr+anImage->mWidth*anImage->mHeight;
                        for (; aPtr!=anEnd; ++aPtr)
                                *aPtr |= 0xFF000000;
                }

                p_fclose(aFP);

                return anImage;
        }
        return NULL;
}

#endif


int ImageLib::gAlphaComposeColor = 0xFFFFFF;
bool ImageLib::gAutoLoadAlpha = true;
bool ImageLib::gIgnoreJPEG2000Alpha = true;

Image* ImageLib::GetImage(const std::string& theFilename, bool lookForAlphaImage)
{
        if (!gAutoLoadAlpha)
                lookForAlphaImage = false;

        int aLastDotPos = theFilename.rfind('.');
        int aLastSlashPos = max((int)theFilename.rfind('\\'), (int)theFilename.rfind('/'));

        std::string anExt;
        std::string aFilename;

        if (aLastDotPos > aLastSlashPos)
        {
                anExt = theFilename.substr(aLastDotPos, theFilename.length() - aLastDotPos);
                aFilename = theFilename.substr(0, aLastDotPos);
        }
        else
                aFilename = theFilename;

        Image* anImage = NULL;

        if ((anImage == NULL) && ((stricmp(anExt.c_str(), ".tga") == 0) || (anExt.length() == 0)))
                 anImage = GetTGAImage(aFilename + ".tga");

        if ((anImage == NULL) && ((stricmp(anExt.c_str(), ".jpg") == 0) || (anExt.length() == 0)))
                 anImage = GetJPEGImage(aFilename + ".jpg");

        if ((anImage == NULL) && ((stricmp(anExt.c_str(), ".png") == 0) || (anExt.length() == 0)))
                 anImage = GetPNGImage(aFilename + ".png");

        if ((anImage == NULL) && ((stricmp(anExt.c_str(), ".gif") == 0) || (anExt.length() == 0)))
                 anImage = GetGIFImage(aFilename + ".gif");

        if (anImage == NULL && (stricmp(anExt.c_str(), ".j2k") == 0 || anExt.length() == 0))
                anImage = GetJPEG2000Image(aFilename + ".j2k");
        if (anImage == NULL && (stricmp(anExt.c_str(), ".jp2") == 0 || anExt.length() == 0))
                anImage = GetJPEG2000Image(aFilename + ".jp2");


        // Check for alpha images
        Image* anAlphaImage = NULL;
        if(lookForAlphaImage)
        {
                // Check _ImageName
                anAlphaImage = GetImage(theFilename.substr(0, aLastSlashPos+1) + "_" +
                        theFilename.substr(aLastSlashPos+1, theFilename.length() - aLastSlashPos - 1), false);

                // Check ImageName_
                if(anAlphaImage==NULL)
                        anAlphaImage = GetImage(theFilename + "_", false);
        }



        // Compose alpha channel with image
        if (anAlphaImage != NULL)
        {
                if (anImage != NULL)
                {
                        if ((anImage->mWidth == anAlphaImage->mWidth) &&
                                (anImage->mHeight == anAlphaImage->mHeight))
                        {
                                unsigned long* aBits1 = anImage->mBits;
                                unsigned long* aBits2 = anAlphaImage->mBits;
                                int aSize = anImage->mWidth*anImage->mHeight;

                                for (int i = 0; i < aSize; i++)
                                {
                                        *aBits1 = (*aBits1 & 0x00FFFFFF) | ((*aBits2 & 0xFF) << 24);
                                        ++aBits1;
                                        ++aBits2;
                                }
                        }

                        delete anAlphaImage;
                }
                else if (gAlphaComposeColor==0xFFFFFF)
                {
                        anImage = anAlphaImage;

                        unsigned long* aBits1 = anImage->mBits;

                        int aSize = anImage->mWidth*anImage->mHeight;
                        for (int i = 0; i < aSize; i++)
                        {
                                *aBits1 = (0x00FFFFFF) | ((*aBits1 & 0xFF) << 24);
                                ++aBits1;
                        }
                }
                else
                {
                        const int aColor = gAlphaComposeColor;
                        anImage = anAlphaImage;

                        unsigned long* aBits1 = anImage->mBits;

                        int aSize = anImage->mWidth*anImage->mHeight;
                        for (int i = 0; i < aSize; i++)
                        {
                                *aBits1 = aColor | ((*aBits1 & 0xFF) << 24);
                                ++aBits1;
                        }
                }
        }

        return anImage;
}