You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
8.9 KiB
339 lines
8.9 KiB
/****************************************************************************
|
|
**
|
|
** Utility program for embedding binary data into a C/C++ source code.
|
|
** It reads a binary file and generates a C array with the binary data.
|
|
** The C code is written to standard output.
|
|
**
|
|
** Created : 951017
|
|
**
|
|
** Copyright (C) 1995-2008 Trolltech ASA. All rights reserved.
|
|
**
|
|
** Permission to use, copy, modify, and distribute this software and its
|
|
** documentation for any purpose and without fee is hereby granted, provided
|
|
** that this copyright notice appears in all copies.
|
|
** No representations are made about the suitability of this software for any
|
|
** purpose. It is provided "as is" without express or implied warranty.
|
|
**
|
|
*****************************************************************************/
|
|
|
|
#include <qstring.h>
|
|
#include <qfile.h>
|
|
#include <qfileinfo.h>
|
|
#include <qptrlist.h>
|
|
#include <qtextstream.h>
|
|
#include <qdatetime.h>
|
|
#include <qimage.h>
|
|
#include <qdict.h>
|
|
#include <qdir.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
static void embedData( const QByteArray &input, QFile *output );
|
|
static void embedData( const uchar* input, int size, QFile *output );
|
|
static void embedData( const QRgb* input, int size, QFile *output );
|
|
static QString convertFileNameToCIdentifier( const char * );
|
|
|
|
static const char header[] = "/* Generated by qembed */\n";
|
|
|
|
struct Embed {
|
|
uint size;
|
|
QString name;
|
|
QString cname;
|
|
};
|
|
|
|
struct EmbedImage {
|
|
int width;
|
|
int height;
|
|
int depth;
|
|
int numColors;
|
|
QRgb* colorTable;
|
|
QString name;
|
|
QString cname;
|
|
bool alpha;
|
|
};
|
|
|
|
int main( int argc, char **argv )
|
|
{
|
|
if ( argc < 2 ) {
|
|
qWarning( "Usage:\n\t%s [--images] files", argv[0] );
|
|
return 1;
|
|
}
|
|
|
|
QFile output;
|
|
bool output_hdr = FALSE;
|
|
bool images = FALSE;
|
|
output.open( IO_WriteOnly, stdout );
|
|
QTextStream out( &output );
|
|
|
|
QPtrList<EmbedImage> list_image;
|
|
QPtrList<Embed> list;
|
|
list.setAutoDelete( TRUE );
|
|
list_image.setAutoDelete( TRUE );
|
|
|
|
long l = rand();
|
|
out << "#ifndef _QEMBED_" << l << endl;
|
|
out << "#define _QEMBED_" << l << endl;
|
|
|
|
QStringList args;
|
|
for ( int i = 1; i < argc; ++i ) {
|
|
QString file( argv[i] );
|
|
#ifdef Q_WS_WIN
|
|
// Since wildcards are not expanded automatically for us on Windows, we need to do
|
|
// it ourselves
|
|
if ( file.contains( '*' ) || file.contains( '?' ) ) {
|
|
QDir d;
|
|
const QFileInfoList *fiList = d.entryInfoList( file, QDir::Files );
|
|
QFileInfoListIterator it(*fiList);
|
|
while ( it.current() ) {
|
|
args << (*it)->filePath();
|
|
++it;
|
|
}
|
|
} else
|
|
#endif
|
|
args << file;
|
|
}
|
|
for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it ) {
|
|
QString arg = (*it);
|
|
if ( arg == "--images" ) {
|
|
if ( !images ) {
|
|
out << "#include <qimage.h>\n";
|
|
out << "#include <qdict.h>\n";
|
|
images = TRUE;
|
|
}
|
|
} else {
|
|
QFile f( *it );
|
|
if ( !f.open(IO_ReadOnly) ) {
|
|
qWarning( "Cannot open file %s, ignoring it", (*it).latin1() );
|
|
continue;
|
|
}
|
|
QByteArray a( f.size() );
|
|
if ( f.size() == 0
|
|
|| f.readBlock(a.data(), f.size()) != (int)f.size() ) {
|
|
qWarning( "Cannot read file %s, ignoring it", (*it).latin1() );
|
|
continue;
|
|
}
|
|
if ( images ) {
|
|
QImage img;
|
|
if ( !img.loadFromData(a) ) {
|
|
qWarning( "Cannot read image from file %s, ignoring it", (*it).latin1() );
|
|
continue;
|
|
}
|
|
EmbedImage *e = new EmbedImage;
|
|
e->width = img.width();
|
|
e->height = img.height();
|
|
e->depth = img.depth();
|
|
e->numColors = img.numColors();
|
|
e->colorTable = new QRgb[e->numColors];
|
|
e->alpha = img.hasAlphaBuffer();
|
|
memcpy(e->colorTable, img.colorTable(), e->numColors*sizeof(QRgb));
|
|
QFileInfo fi( (*it) );
|
|
e->name = fi.baseName();
|
|
e->cname = convertFileNameToCIdentifier( e->name.latin1() );
|
|
list_image.append( e );
|
|
QString s;
|
|
if ( e->depth == 32 ) {
|
|
out << s.sprintf( "static const QRgb %s_data[] = {",
|
|
(const char *)e->cname );
|
|
embedData( (QRgb*)img.bits(), e->width*e->height, &output );
|
|
} else {
|
|
if ( e->depth == 1 )
|
|
img = img.convertBitOrder(QImage::BigEndian);
|
|
out << s.sprintf( "static const unsigned char %s_data[] = {",
|
|
(const char *)e->cname );
|
|
embedData( img.bits(), img.numBytes(), &output );
|
|
}
|
|
out << "\n};\n\n";
|
|
if ( e->numColors ) {
|
|
out << s.sprintf( "static const QRgb %s_ctable[] = {",
|
|
(const char *)e->cname );
|
|
embedData( e->colorTable, e->numColors, &output );
|
|
out << "\n};\n\n";
|
|
}
|
|
} else {
|
|
Embed *e = new Embed;
|
|
e->size = f.size();
|
|
e->name = (*it);
|
|
e->cname = convertFileNameToCIdentifier( (*it) );
|
|
list.append( e );
|
|
QString s;
|
|
out << s.sprintf( "static const unsigned int %s_len = %d;\n",
|
|
(const char *)e->cname, e->size );
|
|
out << s.sprintf( "static const unsigned char %s_data[] = {",
|
|
(const char *)e->cname );
|
|
embedData( a, &output );
|
|
out << "\n};\n\n";
|
|
}
|
|
if ( !output_hdr ) {
|
|
output_hdr = TRUE;
|
|
out << header;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( list.count() > 0 ) {
|
|
out << "#include <qcstring.h>\n";
|
|
if ( !images )
|
|
out << "#include <qdict.h>\n";
|
|
|
|
out << "static struct Embed {\n"
|
|
" unsigned int size;\n"
|
|
" const unsigned char *data;\n"
|
|
" const char *name;\n"
|
|
"} embed_vec[] = {\n";
|
|
Embed *e = list.first();
|
|
while ( e ) {
|
|
out << " { " << e->size << ", " << e->cname << "_data, "
|
|
<< "\"" << e->name << "\" },\n";
|
|
e = list.next();
|
|
}
|
|
out << " { 0, 0, 0 }\n};\n";
|
|
|
|
out << "\n"
|
|
"static const QByteArray& qembed_findData( const char* name )\n"
|
|
"{\n"
|
|
" static QDict<QByteArray> dict;\n"
|
|
" QByteArray* ba = dict.find( name );\n"
|
|
" if ( !ba ) {\n"
|
|
" for ( int i = 0; embed_vec[i].data; i++ ) {\n"
|
|
" if ( strcmp(embed_vec[i].name, name) == 0 ) {\n"
|
|
" ba = new QByteArray;\n"
|
|
" ba->setRawData( (char*)embed_vec[i].data,\n"
|
|
" embed_vec[i].size );\n"
|
|
" dict.insert( name, ba );\n"
|
|
" break;\n"
|
|
" }\n"
|
|
" }\n"
|
|
" if ( !ba ) {\n"
|
|
" static QByteArray dummy;\n"
|
|
" return dummy;\n"
|
|
" }\n"
|
|
" }\n"
|
|
" return *ba;\n"
|
|
"}\n\n";
|
|
}
|
|
|
|
if ( list_image.count() > 0 ) {
|
|
out << "static struct EmbedImage {\n"
|
|
" int width, height, depth;\n"
|
|
" const unsigned char *data;\n"
|
|
" int numColors;\n"
|
|
" const QRgb *colorTable;\n"
|
|
" bool alpha;\n"
|
|
" const char *name;\n"
|
|
"} embed_image_vec[] = {\n";
|
|
EmbedImage *e = list_image.first();
|
|
while ( e ) {
|
|
out << " { "
|
|
<< e->width << ", "
|
|
<< e->height << ", "
|
|
<< e->depth << ", "
|
|
<< "(const unsigned char*)" << e->cname << "_data, "
|
|
<< e->numColors << ", ";
|
|
if ( e->numColors )
|
|
out << e->cname << "_ctable, ";
|
|
else
|
|
out << "0, ";
|
|
if ( e->alpha )
|
|
out << "TRUE, ";
|
|
else
|
|
out << "FALSE, ";
|
|
out << "\"" << e->name << "\" },\n";
|
|
e = list_image.next();
|
|
}
|
|
out << " { 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n";
|
|
|
|
out << "\n"
|
|
"static const QImage& qembed_findImage( const QString& name )\n"
|
|
"{\n"
|
|
" static QDict<QImage> dict;\n"
|
|
" QImage* img = dict.find( name );\n"
|
|
" if ( !img ) {\n"
|
|
" for ( int i = 0; embed_image_vec[i].data; i++ ) {\n"
|
|
" if ( strcmp(embed_image_vec[i].name, name.latin1()) == 0 ) {\n"
|
|
" img = new QImage((uchar*)embed_image_vec[i].data,\n"
|
|
" embed_image_vec[i].width,\n"
|
|
" embed_image_vec[i].height,\n"
|
|
" embed_image_vec[i].depth,\n"
|
|
" (QRgb*)embed_image_vec[i].colorTable,\n"
|
|
" embed_image_vec[i].numColors,\n"
|
|
" QImage::BigEndian );\n"
|
|
" if ( embed_image_vec[i].alpha )\n"
|
|
" img->setAlphaBuffer( TRUE );\n"
|
|
" dict.insert( name, img );\n"
|
|
" break;\n"
|
|
" }\n"
|
|
" }\n"
|
|
" if ( !img ) {\n"
|
|
" static QImage dummy;\n"
|
|
" return dummy;\n"
|
|
" }\n"
|
|
" }\n"
|
|
" return *img;\n"
|
|
"}\n\n";
|
|
}
|
|
|
|
out << "#endif" << endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
QString convertFileNameToCIdentifier( const char *s )
|
|
{
|
|
QString r = s;
|
|
int len = r.length();
|
|
if ( len > 0 && !isalpha( (char)r[0].latin1() ) )
|
|
r[0] = '_';
|
|
for ( int i = 1; i < len; i++ ) {
|
|
if ( !isalnum( (char)r[i].latin1() ) )
|
|
r[i] = '_';
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
void embedData( const QByteArray &input, QFile *output )
|
|
{
|
|
embedData((uchar*)input.data(), input.size(), output);
|
|
}
|
|
|
|
void embedData( const uchar* input, int nbytes, QFile *output )
|
|
{
|
|
static const char hexdigits[] = "0123456789abcdef";
|
|
QString s;
|
|
for ( int i=0; i<nbytes; i++ ) {
|
|
if ( (i%14) == 0 ) {
|
|
s += "\n ";
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
s.truncate( 0 );
|
|
}
|
|
uint v = input[i];
|
|
s += "0x";
|
|
s += hexdigits[(v >> 4) & 15];
|
|
s += hexdigits[v & 15];
|
|
if ( i < nbytes-1 )
|
|
s += ',';
|
|
}
|
|
if ( s.length() )
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
}
|
|
|
|
void embedData( const QRgb* input, int n, QFile *output )
|
|
{
|
|
QString s;
|
|
for ( int i = 0; i < n; i++ ) {
|
|
if ( (i % 14) == 0 ) {
|
|
s += "\n ";
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
s.truncate( 0 );
|
|
}
|
|
QRgb v = input[i];
|
|
s += "0x";
|
|
s += QString::number( v, 16 );
|
|
if ( i < n-1 )
|
|
s += ',';
|
|
}
|
|
if ( s.length() )
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
}
|