//////////////////////////////////////////////////////////
// bmpio.cpp
//////////////////////////////////////////////////////////

#include <fstream.h>

#include "bmpio.h"
#include "rasterop.h"


static unsigned char bmpHeader[62] =
{        'B',  'M', 0x6E, 0x1B, 0x0F, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00,

        0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0xE4, 0x0C,

        0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00
};

int bmp_save( char *filename, BMPINFO *pbmpinfo )
{
        int starty = 0;
        int endy = pbmpinfo->height - 1;
        int bpl = (pbmpinfo->width + 7) / 8;

        if( pbmpinfo->cropy )
        {
                unsigned char *p = pbmpinfo->bits;
                int i = 0;
                while( !*p && starty <= endy )
                {
                        i++;
                        if( i >= bpl )
                        {
                                starty++;
                                i = 0;
                        }
                        p++;
                }

                p = pbmpinfo->bits + bpl * pbmpinfo->height;
                i = bpl;
                while( !*--p && starty <= endy )
                {
                        if( --i <= 0 )
                        {
                                endy--;
                                i = bpl;
                        }
                }

        }

        ofstream ofBmp;
        ofBmp.open( filename, ios::out | ios::binary );

        if( starty <= endy )
        {
                unsigned long w = pbmpinfo->width;
                unsigned long h = endy - starty + 1;

                if( pbmpinfo->scalex > 1 || pbmpinfo->scaley > 1 )
                {
                        if( starty + h < pbmpinfo->height && h % pbmpinfo->scaley )
                            h ++;

                        bit_res( pbmpinfo->bits + bpl * starty, w, h,
                                 (w + pbmpinfo->scalex - 1) / pbmpinfo->scalex,
                                 (h + pbmpinfo->scaley - 1) / pbmpinfo->scaley );
                        w = (w + pbmpinfo->scalex - 1) / pbmpinfo->scalex;
                        h = (h + pbmpinfo->scaley - 1) / pbmpinfo->scaley;
                }
                ofBmp.write( bmpHeader, 18 );
                ofBmp.put( char( w      & 0x000000FF) );
                ofBmp.put( char((w>> 8) & 0x000000FF) );
                ofBmp.put( char((w>>16) & 0x000000FF) );
                ofBmp.put( char((w>>24) & 0x000000FF) );

                ofBmp.put( char( h      & 0x000000FF) );
                ofBmp.put( char((h>> 8) & 0x000000FF) );
                ofBmp.put( char((h>>16) & 0x000000FF) );
                ofBmp.put( char((h>>24) & 0x000000FF) );
                ofBmp.write( bmpHeader + 26, sizeof(bmpHeader) - 26 );

                bit_neg( pbmpinfo->bits + bpl * starty, bpl * h );

                unsigned char *p = pbmpinfo->bits + bpl * (starty + h);
                int bpl2 = (w + 7) / 8;

                for( unsigned y = 0; y < h; y++ )
                {
                        p -= bpl;
                        ofBmp.write( p, bpl2 );
                        switch( bpl2 % 4 )
                        {
                                case 1:
                                        ofBmp.put( '\0' );
                                        // fallthru
                                case 2:
                                        ofBmp.put( '\0' );
                                        // fallthru
                                case 3:
                                        ofBmp.put( '\0' );
                                        // fallthru
                        }
                }
        }
        ofBmp.close();

        return 0;
}