/***************************************************************************
 *   Copyright (C) 2005 by Nick Bargnesi                                   *
 *   nbargnesi@gmail.com                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <qimage.h>
#include <qtextstream.h>
#include <qregexp.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qdatetime.h>

#include <iostream>

struct QRGBImage {
     QString string;
     int width;
     int height;
     bool alpha;
     QString name;
};

class ImageConverter {
    public:
        ImageConverter(const char *);
        ~ImageConverter();

        void convert( const char *, bool);
        void writeIndex();
    private:
        QFile *file;
        QPtrList<QRGBImage> *index;
        QTextStream stream;
};

int main(int argv, char *argc[]) {
	bool b = false;
    if ( argv < 3 || argv > 4 ) {
        std::cout << "Usage: png2qrgb [-i] <image.png> <header_file>" << std::endl;
        return EXIT_FAILURE;
    }

    for (int i = 0; i < argv; i++) {
		if (argc[i] == "-i" || argc[i] == "--generate-index") {
			qDebug("I will only generate index values.");
			b = true;
		} else {
			qDebug(argc[i]);
		}
	}

    ImageConverter imageConverter(argc[2]);
    imageConverter.convert(argc[1], b);
    //imageConverter.writeIndex();

    return EXIT_SUCCESS;
}

 ImageConverter::ImageConverter(const char *headerFile) {
    QDateTime date( QDateTime::currentDateTime() );
    QString datestring( date.toString() );

    file = new QFile( headerFile );
    file->open( IO_WriteOnly | IO_Truncate );

    stream.setDevice( file );
    index = new QPtrList<QRGBImage>;
    index->setAutoDelete( true );
}

ImageConverter::~ImageConverter() {
    file->close();
    delete file;
    delete index;
}

void ImageConverter::convert(const char *name, bool indexOnly) {
    QFileInfo   fileinfo( name );
    QString     basename( fileinfo.baseName() );
    QString     codename( basename );
    QImage      image( name );

	if (image == NULL) {
		qDebug("No such image " + name);
		exit 1;
	}

    codename = codename.replace( QRegExp("[^a-zA-Z0-9]"), "_" );

	if (!indexOnly) {
	    stream << "\tstatic const QRgb " << codename << "_data[] = {" << endl << "\t\t";
	    stream.setf( QTextStream::hex | QTextStream::right );
	    stream.fill( '0' );
	}

    int pixels = image.width() * image.height();
    Q_UINT32 *data = reinterpret_cast<Q_UINT32*>( image.bits() );
    bool hasAlpha = false;

    for ( int i = 0, j = 0; i < pixels; i++ ) {

        if ( qAlpha( *data ) && qAlpha( *data ) != 0xff ) {
             hasAlpha = true;
        }

		if (!indexOnly) {
	        stream << "0x" << qSetW(8) << *(data++);
		}
			
        if ( i != pixels-1 ) {
			if (!indexOnly) {
            	stream << ',';
			}
			
            if ( j++ > 4 ) {
                j = 0;
				if (!indexOnly) {
	                stream << endl << "\t\t";
				}
            } else {
				if (!indexOnly) {
	                stream << ' ';
				}
            }
        }
    }

	if (!indexOnly) {
		stream.reset();
		stream << endl << "\t}; // " << codename << "_data" << endl << endl;
	}

	if (indexOnly) {
		uint i = 0;
 		for (QRGBImage *image = index->first(); image; image = index->next()) {
			stream << "\t\t{ \"" << image->string << "\", "
            		<< image->width << ", " << image->height <<
					", " << (image->alpha ? "true" : "false")
					<< ", " << image->name << "_data }";
			if (i++ < index->count() - 1)
				stream << ',';
				stream << endl;
     	}
	}
	
    QRGBImage *imginfo = new QRGBImage;
    imginfo->width = image.width();
    imginfo->height = image.height();
    imginfo->alpha = hasAlpha;
    imginfo->name = codename;
    imginfo->string = basename;
    index->append( imginfo ); 
}

void ImageConverter::writeIndex() {
	 /*
     stream << "\tstruct QRGBImage {\n";
     stream << "\t\tconst char *name;\n";
     stream << "\t\tint width;\n";
     stream << "\t\tint height;\n";
     stream << "\t\tbool alpha;\n";
     stream << "\t\tconst QRgb *data;\n";
     stream << "\t};\n\n";
 
     uint i = 0;
     stream << "\tstatic const QRGBImage image_db[] = {\n";
     for ( QRGBImage *image = index->first(); image; image = index->next() )
     {
         stream << "\t\t{ \"" << image->string << "\", "
             << image->width << ", " << image->height <<
             ", " << (image->alpha ? "true" : "false")
             << ", " << image->name << "_data }";
         if ( i++ < index->count() - 1 )
             stream << ',';
         stream << endl;
     }
     stream << "\t};\n\n";
 
     uint prime = 0;
     
     for ( i = 0; i < 50; i++ )
         if ( (prime = primes[i]) >= index->count() )
             break;
     
     stream << "\tclass ImageDb {\n";
     stream << "\tprivate:\n";
     stream << "\t\tstatic ImageDb *m_inst;\n";
     stream << "\t\tQDict<QImage> *db;\n\n";
     stream << "\t\tImageDb() {\n";
     stream << "\t\t\tdb = new QDict<QImage>( " << prime << " );\n";
     stream << "\t\t\tdb->setAutoDelete( true );\n\n";
     stream << "\t\t\tfor ( int i = 0; i < " << index->count() << "; i++ ) {\n";
     stream << "\t\t\t\tQImage *img = new QImage( (uchar*)image_db[i].data,\n";
     stream << "\t\t\t\t\t\timage_db[i].width, image_db[i].height,\n";
     stream << "\t\t\t\t\t\t32, NULL, 0, QImage::LittleEndian );\n\n";
     stream << "\t\t\t\tif ( image_db[i].alpha )\n";
     stream << "\t\t\t\t\timg->setAlphaBuffer( true );\n\n";
     stream << "\t\t\t\tdb->insert( image_db[i].name, img );\n";
     stream << "\t\t\t}\n";
     stream << "\t\t}\n\n";
     stream << "\t\t~ImageDb() {\n";
     stream << "\t\t\tdelete db;\n";
     stream << "\t\t}\n\n";
     stream << "\tpublic:\n";
     stream << "\t\tstatic ImageDb* instance() {\n";  
     stream << "\t\t\tif ( ! m_inst ) m_inst = new ImageDb;\n";
     stream << "\t\t\treturn m_inst;\n";
     stream << "\t\t}\n\n";
     stream << "\t\tstatic void release() {\n";
     stream << "\t\t\tif ( m_inst ) delete m_inst;\n";
     stream << "\t\t\tm_inst = NULL;\n";
     stream << "\t\t}\n\n";
     stream << "\t\tQImage *image( const QString &name ) const {\n";
     stream << "\t\t\treturn db->find( name );\n";
     stream << "\t\t}\n\n";
     stream << "\t}; // class ImageDb\n\n";
     stream << "\tImageDb *ImageDb::m_inst = NULL;\n\n";
     */
}

// vim:ts=4:sw=4
