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
9.0 KiB
339 lines
9.0 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 <tqstring.h>
|
|
#include <tqfile.h>
|
|
#include <tqfileinfo.h>
|
|
#include <tqptrlist.h>
|
|
#include <tqtextstream.h>
|
|
#include <tqdatetime.h>
|
|
#include <tqimage.h>
|
|
#include <tqdict.h>
|
|
#include <tqdir.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
static void embedData( const TQByteArray &input, TQFile *output );
|
|
static void embedData( const uchar* input, int size, TQFile *output );
|
|
static void embedData( const TQRgb* input, int size, TQFile *output );
|
|
static TQString convertFileNameToCIdentifier( const char * );
|
|
|
|
static const char header[] = "/* Generated by qembed */\n";
|
|
|
|
struct Embed {
|
|
uint size;
|
|
TQString name;
|
|
TQString cname;
|
|
};
|
|
|
|
struct EmbedImage {
|
|
int width;
|
|
int height;
|
|
int depth;
|
|
int numColors;
|
|
TQRgb* colorTable;
|
|
TQString name;
|
|
TQString cname;
|
|
bool alpha;
|
|
};
|
|
|
|
int main( int argc, char **argv )
|
|
{
|
|
if ( argc < 2 ) {
|
|
tqWarning( "Usage:\n\t%s [--images] files", argv[0] );
|
|
return 1;
|
|
}
|
|
|
|
TQFile output;
|
|
bool output_hdr = FALSE;
|
|
bool images = FALSE;
|
|
output.open( IO_WriteOnly, stdout );
|
|
TQTextStream out( &output );
|
|
|
|
TQPtrList<EmbedImage> list_image;
|
|
TQPtrList<Embed> list;
|
|
list.setAutoDelete( TRUE );
|
|
list_image.setAutoDelete( TRUE );
|
|
|
|
long l = rand();
|
|
out << "#ifndef _QEMBED_" << l << endl;
|
|
out << "#define _QEMBED_" << l << endl;
|
|
|
|
TQStringList args;
|
|
for ( int i = 1; i < argc; ++i ) {
|
|
TQString file( argv[i] );
|
|
#ifdef TQ_WS_WIN
|
|
// Since wildcards are not expanded automatically for us on Windows, we need to do
|
|
// it ourselves
|
|
if ( file.contains( '*' ) || file.contains( '?' ) ) {
|
|
TQDir d;
|
|
const TQFileInfoList *fiList = d.entryInfoList( file, TQDir::Files );
|
|
TQFileInfoListIterator it(*fiList);
|
|
while ( it.current() ) {
|
|
args << (*it)->filePath();
|
|
++it;
|
|
}
|
|
} else
|
|
#endif
|
|
args << file;
|
|
}
|
|
for ( TQStringList::Iterator it = args.begin(); it != args.end(); ++it ) {
|
|
TQString arg = (*it);
|
|
if ( arg == "--images" ) {
|
|
if ( !images ) {
|
|
out << "#include <tqimage.h>\n";
|
|
out << "#include <tqdict.h>\n";
|
|
images = TRUE;
|
|
}
|
|
} else {
|
|
TQFile f( *it );
|
|
if ( !f.open(IO_ReadOnly) ) {
|
|
tqWarning( "Cannot open file %s, ignoring it", (*it).latin1() );
|
|
continue;
|
|
}
|
|
TQByteArray a( f.size() );
|
|
if ( f.size() == 0
|
|
|| f.readBlock(a.data(), f.size()) != (int)f.size() ) {
|
|
tqWarning( "Cannot read file %s, ignoring it", (*it).latin1() );
|
|
continue;
|
|
}
|
|
if ( images ) {
|
|
TQImage img;
|
|
if ( !img.loadFromData(a) ) {
|
|
tqWarning( "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 TQRgb[e->numColors];
|
|
e->alpha = img.hasAlphaBuffer();
|
|
memcpy(e->colorTable, img.colorTable(), e->numColors*sizeof(TQRgb));
|
|
TQFileInfo fi( (*it) );
|
|
e->name = fi.baseName();
|
|
e->cname = convertFileNameToCIdentifier( e->name.latin1() );
|
|
list_image.append( e );
|
|
TQString s;
|
|
if ( e->depth == 32 ) {
|
|
out << s.sprintf( "static const TQRgb %s_data[] = {",
|
|
(const char *)e->cname );
|
|
embedData( (TQRgb*)img.bits(), e->width*e->height, &output );
|
|
} else {
|
|
if ( e->depth == 1 )
|
|
img = img.convertBitOrder(TQImage::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 TQRgb %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 );
|
|
TQString 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 <tqcstring.h>\n";
|
|
if ( !images )
|
|
out << "#include <tqdict.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 TQByteArray& qembed_findData( const char* name )\n"
|
|
"{\n"
|
|
" static TQDict<TQByteArray> dict;\n"
|
|
" TQByteArray* 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 TQByteArray;\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 TQByteArray 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 TQRgb *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 TQImage& qembed_findImage( const TQString& name )\n"
|
|
"{\n"
|
|
" static TQDict<TQImage> dict;\n"
|
|
" TQImage* 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 TQImage((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"
|
|
" (TQRgb*)embed_image_vec[i].colorTable,\n"
|
|
" embed_image_vec[i].numColors,\n"
|
|
" TQImage::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 TQImage dummy;\n"
|
|
" return dummy;\n"
|
|
" }\n"
|
|
" }\n"
|
|
" return *img;\n"
|
|
"}\n\n";
|
|
}
|
|
|
|
out << "#endif" << endl;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
TQString convertFileNameToCIdentifier( const char *s )
|
|
{
|
|
TQString 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 TQByteArray &input, TQFile *output )
|
|
{
|
|
embedData((uchar*)input.data(), input.size(), output);
|
|
}
|
|
|
|
void embedData( const uchar* input, int nbytes, TQFile *output )
|
|
{
|
|
static const char hexdigits[] = "0123456789abcdef";
|
|
TQString 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 TQRgb* input, int n, TQFile *output )
|
|
{
|
|
TQString s;
|
|
for ( int i = 0; i < n; i++ ) {
|
|
if ( (i % 14) == 0 ) {
|
|
s += "\n ";
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
s.truncate( 0 );
|
|
}
|
|
TQRgb v = input[i];
|
|
s += "0x";
|
|
s += TQString::number( v, 16 );
|
|
if ( i < n-1 )
|
|
s += ',';
|
|
}
|
|
if ( s.length() )
|
|
output->writeBlock( (const char*)s, s.length() );
|
|
}
|