int main( int argc, char **argv ) { if ( argc < 2 ) { qWarning( "Usage:\n\t%s [--images] files", argv[0] ); return 1; } QFile output; bool images = FALSE; output.open( IO_WriteOnly, stdout ); QTextStream out( &output ); EmbedImageList list_image; QList<Embed> list; list.setAutoDelete( TRUE ); list_image.setAutoDelete( TRUE ); // Embed data for all input files out << "/* Generated by qembed */\n"; srand( time(0) ); long l = rand(); out << "#ifndef _" << l << endl; out << "#define _" << l << endl; for ( int i=1; i<argc; i++ ) { QString arg = argv[i]; if ( arg == "--images" ) { if ( !images ) { out << "#include <qimage.h>\n"; out << "#include <stdlib.h>\n"; images = TRUE; } } else { QFile f( argv[i] ); if ( !f.open(IO_ReadOnly) ) { qWarning( "Cannot open file %s, ignoring it", argv[i] ); continue; } QByteArray a( f.size() ); if ( f.readBlock(a.data(), f.size()) != (int)f.size() ) { qWarning( "Cannot read file %s, ignoring it", argv[i] ); f.close(); continue; } if ( images ) { QImage img; if ( !img.loadFromData(a) ) { qWarning( "Cannot read image from file %s, ignoring it", argv[i] ); f.close(); 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(argv[i]); 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 = argv[i]; e->cname = convertFileNameToCIdentifier( argv[i] ); 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"; } f.close(); } } // Generate summery 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" "inline 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 ( 0==strcmp(embed_vec[i].name, name) ) {\n" " ba = new QByteArray;\n" " ba->setRawData( (char*)embed_vec[i].data,\n" " embed_vec[i].size );\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"; list_image.sort(); 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 << "};\n"; out << "\n" "static int cmpEmbedImage(const void *a, const void *b)\n" "{\n" " const EmbedImage* ea = (const EmbedImage*)a;\n" " const EmbedImage* eb = (const EmbedImage*)b;\n" " return strcmp(ea->name,eb->name);\n" "}\n" "inline const QImage& qembed_findImage(const char* name)\n" "{\n" " EmbedImage key; key.name = name;\n" " EmbedImage* r = (EmbedImage*)bsearch( &key, embed_image_vec,\n" " sizeof(embed_image_vec)/sizeof(EmbedImage), sizeof(EmbedImage), cmpEmbedImage );\n" " QImage* img;\n" " if ( r ) {\n" " img = new QImage((uchar*)r->data,\n" " r->width,\n" " r->height,\n" " r->depth,\n" " (QRgb*)r->colorTable,\n" " r->numColors,\n" " QImage::BigEndian\n" " );\n" " if ( r->alpha )\n" " img->setAlphaBuffer(TRUE);\n" " } else {\n" " static QImage dummy;\n" " img = &dummy;\n" " }\n" " return *img;\n" "}\n\n"; } out << "#endif" << endl; return 0; }
void ImgCache::insertImage(int page, const QImage &img) { mtx.lock(); if (autoAdjust && (img.numBytes() + maxItemSizeSoFar > cache.maxCost())) { cache.setMaxCost(img.numBytes() + maxItemSizeSoFar); if (img.numBytes() > maxItemSizeSoFar) maxItemSizeSoFar = img.numBytes(); } cache.insert(page, new QImage(img), img.numBytes()); mtx.unlock(); }
PixelBuffer& PixelBuffer::operator=(const QImage& image) { QImage swapped = image.rgbSwapped(); QSize swappedSize = swapped.size(); int w = swappedSize.width(); int h = swappedSize.height(); int numPixels = w * h; int numBytes = w * h * 4; if (swappedSize != m_sizeInPixels) { deleteBuffer(); m_sizeInPixels = QSize(w, h); m_buffer = new uchar[numBytes]; } // Copy the memory over. // We'll add defensive code in case rgbSwapped has a different size const uchar* from = swapped.constBits(); int numFromBytes = swapped.numBytes(); int numToCopy = std::min(numFromBytes, numBytes); memcpy(m_buffer, from, numToCopy); if (numToCopy < numBytes) { memset(m_buffer + numToCopy, 0x00, numBytes - numToCopy); } return *this; }
uint MltPreview::imageVariance(QImage image) { if (image.isNull()) return 0; uint delta = 0; uint avg = 0; uint bytes = image.numBytes(); uint STEPS = bytes / 2; QVarLengthArray<uchar> pivot(STEPS); kDebug(DBG_AREA) << "Using " << STEPS << " steps\n"; const uchar *bits=image.bits(); // First pass: get pivots and taking average for( uint i=0; i<STEPS ; i++ ){ pivot[i] = bits[2 * i]; #if QT_VERSION >= 0x040700 avg+=pivot.at(i); #else avg+=pivot[i]; #endif } avg=avg/STEPS; // Second Step: calculate delta (average?) for (uint i=0; i<STEPS; i++) { #if QT_VERSION >= 0x040700 int curdelta=abs(int(avg - pivot.at(i))); #else int curdelta=abs(int(avg - pivot[i])); #endif delta+=curdelta; } return delta / STEPS; }
bool VideoThumbnailer::isFrameInteresting(const QImage &frame) { float variance = 0; //taken from mplayerthumbs uint delta=0; uint avg=0; uint bytes=frame.numBytes(); uint STEPS=bytes/2; QVarLengthArray<uchar> pivot(STEPS); const uchar *bits=frame.bits(); // First pass: get pivots and taking average for( uint i=0; i<STEPS ; i++ ){ pivot[i]=bits[i*(bytes/STEPS)]; avg+=pivot[i]; } avg=avg/STEPS; // Second Step: calculate delta (average?) for (uint i=0; i<STEPS; i++) { int curdelta=abs(int(avg-pivot[i])); delta+=curdelta; } variance= delta/STEPS; return variance > THRESHOLD_FRAME_VARIANCE; }
void syImgReaderCodec::LoadCurrentFrame(syBitmap* dest) { if(!dest) { return; } sySafeMutexLocker lock(m_Mutex); if(lock.IsLocked()) { // 1. Check if m_Image is null. If not, abort (can't create the image, we could be in a worker thread) if(!m_Image) { return; } // 2. Read the image into m_Image. if(!m_ImageLoaded && m_Reader->read(m_Image)) { m_ImageLoaded = true; } // 3. Copy the image to dest. if(m_ImageLoaded) { const unsigned char* bits = m_Image->bits(); dest->CopyFrom(bits,GetWidth(),GetHeight(),vcfRGB32,m_Image->numBytes()); } else { dest->Clear(); } } }
//static uint KThumb::imageVariance(QImage image ) { uint delta = 0; uint avg = 0; uint bytes = image.numBytes(); uint STEPS = bytes/2; QVarLengthArray<uchar> pivot(STEPS); const uchar *bits=image.bits(); // First pass: get pivots and taking average for( uint i=0; i<STEPS ; i++ ){ pivot[i] = bits[2 * i]; #if QT_VERSION >= 0x040700 avg+=pivot.at(i); #else avg+=pivot[i]; #endif } avg=avg/STEPS; // Second Step: calculate delta (average?) for (uint i=0; i<STEPS; i++) { #if QT_VERSION >= 0x040700 int curdelta=abs(int(avg - pivot.at(i))); #else int curdelta=abs(int(avg - pivot[i])); #endif delta+=curdelta; } return delta/STEPS; }
void pwan::imageviewer_backend_qt::do_work() { while(!abort) { while(!fileName.empty()) { QImage image; boost::shared_ptr<imagebuffer> buffer(new imagebuffer); image = QImage(0,0,QImage::Format_Invalid); QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings (codec); m_mutex.lock(); image.load(QString().fromStdString(fileName.at(0))); m_mutex.unlock(); if(!image.isNull()) { buffer->filename = fileName.at(0); buffer->width = image.width(); buffer->height = image.height(); buffer->depth = image.depth(); buffer->data.reset(new uchar[image.numBytes()]); buffer->noOfBytes = image.numBytes(); m_mutex.lock(); memcpy(buffer->data.get(), image.bits(), image.numBytes()); image2 = image1; image1 = buffer; m_mutex.unlock(); } m_mutex.lock(); fileName.erase(fileName.begin()); m_mutex.unlock(); } m_mutex.lock(); if (abort) break; m_mutex.unlock(); boost::asio::io_service io; boost::asio::deadline_timer t(io, boost::posix_time::millisec(20)); t.wait(); } }
void BitmapFactoryInst::convert(const QImage& p, SoSFImage& img) const { SbVec2s size; size[0] = p.width(); size[1] = p.height(); int buffersize = p.numBytes(); int numcomponents = buffersize / ( size[0] * size[1] ); // allocate image data img.setValue(size, numcomponents, NULL); unsigned char * bytes = img.startEditing(size, numcomponents); int width = (int)size[0]; int height = (int)size[1]; for (int y = 0; y < height; y++) { unsigned char * line = &bytes[width*numcomponents*(height-(y+1))]; for (int x = 0; x < width; x++) { QRgb rgb = p.pixel(x,y); switch (numcomponents) { default: break; case 1: line[0] = qGray( rgb ); break; case 2: line[0] = qGray( rgb ); line[1] = qAlpha( rgb ); break; case 3: line[0] = qRed( rgb ); line[1] = qGreen( rgb ); line[2] = qBlue( rgb ); break; case 4: line[0] = qRed( rgb ); line[1] = qGreen( rgb ); line[2] = qBlue( rgb ); line[3] = qAlpha( rgb ); break; } line += numcomponents; } } img.finishEditing(); }
void QFontEngineQPF::loadGlyph(glyph_t glyph) { quint32 glyphPos = ~0; if (!renderingFontEngine) return; QImage img = renderingFontEngine->alphaMapForGlyph(glyph).convertToFormat(QImage::Format_Indexed8); glyph_metrics_t metrics = renderingFontEngine->boundingBox(glyph); renderingFontEngine->removeGlyphFromCache(glyph); off_t oldSize = ::lseek(fd, 0, SEEK_END); if (oldSize == (off_t)-1) return; Glyph g; g.width = img.width(); g.height = img.height(); g.bytesPerLine = img.bytesPerLine(); g.x = qRound(metrics.x); g.y = qRound(metrics.y); g.advance = qRound(metrics.xoff); ::write(fd, &g, sizeof(g)); ::write(fd, img.bits(), img.numBytes()); glyphPos = oldSize - glyphDataOffset; #if 0 && defined(DEBUG_FONTENGINE) qDebug() << "glyphPos for new glyph" << glyph << "is" << glyphPos << "oldSize" << oldSize << "glyphDataOffset" << glyphDataOffset; #endif quint32 *gmap = (quint32 *)(fontData + glyphMapOffset); gmap[glyph] = qToBigEndian(glyphPos); glyphDataSize = glyphPos + sizeof(g) + img.numBytes(); quint32 *blockSizePtr = (quint32 *)(fontData + glyphDataOffset - 4); *blockSizePtr = qToBigEndian(glyphDataSize); }
/** * Automatic marshaling of a QImage for org.freedesktop.Notifications.Notify * * This function is from the Clementine project (see * http://www.clementine-player.org) and licensed under the GNU General Public * License, version 3 or later. * * Copyright 2010, David Sansome <*****@*****.**> */ QDBusArgument &operator<<( QDBusArgument &arg, const QImage &image ) { if ( image.isNull() ) { arg.beginStructure(); arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray(); arg.endStructure(); return arg; } QImage scaled = image.scaledToHeight( 100, Qt::SmoothTransformation ); scaled = scaled.convertToFormat( QImage::Format_ARGB32 ); #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN // ABGR -> ARGB QImage i = scaled.rgbSwapped(); #else // ABGR -> GBAR QImage i( scaled.size(), scaled.format() ); for ( int y = 0; y < i.height(); ++y ) { QRgb *p = ( QRgb * ) scaled.scanLine( y ); QRgb *q = ( QRgb * ) i.scanLine( y ); QRgb *end = p + scaled.width(); while ( p < end ) { *q = qRgba( qGreen( *p ), qBlue( *p ), qAlpha( *p ), qRed( *p ) ); p++; q++; } } #endif arg.beginStructure(); arg << i.width(); arg << i.height(); arg << i.bytesPerLine(); arg << i.hasAlphaChannel(); int channels = i.isGrayscale() ? 1 : ( i.hasAlphaChannel() ? 4 : 3 ); arg << i.depth() / channels; arg << channels; arg << QByteArray( reinterpret_cast<const char *>( i.bits() ), i.numBytes() ); arg.endStructure(); return arg; }
void LH_LgLcdThread::setQVGA( QImage img ) { if( img.isNull() ) { qvga_bm.hdr.Format = 0; return; } Q_ASSERT( img.numBytes() == sizeof( qvga_bm.bmp_qvga32.pixels ) ); qvga_bm.bmp_qvga32.hdr.Format = LGLCD_BMP_FORMAT_QVGAx32; memcpy( qvga_bm.bmp_qvga32.pixels, #ifdef Q_WS_MAC img.rgbSwapped().bits(), #else img.bits(), #endif sizeof( qvga_bm.bmp_qvga32.pixels ) ); sem_.release(); }
QDBusArgument& operator<< (QDBusArgument& arg, const DBusNotifyImageData &data) { if (data.image.isNull()) { // Sometimes this gets called with a null QImage for no obvious reason. // - There is one reason: Qt calls this method at first time to research it's structure arg.beginStructure(); arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray(); arg.endStructure(); return arg; } QImage scaled = data.image.scaledToHeight(qMin(100, qMin(data.image.height(), data.image.width())), Qt::SmoothTransformation).toImage(); QImage i = scaled.convertToFormat(QImage::Format_ARGB32).rgbSwapped(); arg.beginStructure(); arg << i.width(); arg << i.height(); arg << i.bytesPerLine(); arg << i.hasAlphaChannel(); int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3); arg << i.depth() / channels; arg << channels; arg << QByteArray(reinterpret_cast<const char*>(i.bits()), i.numBytes()); arg.endStructure(); return arg; }
bool ImageResize::imageResize(const EmailSettingsContainer& settings, const KUrl& orgUrl, const QString& destName, QString& err) { EmailSettingsContainer emailSettings = settings; QFileInfo fi(orgUrl.path()); if (!fi.exists() || !fi.isReadable()) { err = i18n("Error opening input file"); return false; } QFileInfo tmp(destName); QFileInfo tmpDir(tmp.dir().absolutePath()); kDebug() << "tmpDir: " << tmp.dir().absolutePath(); if (!tmpDir.exists() || !tmpDir.isWritable()) { err = i18n("Error opening temporary folder"); return false; } QImage img; // Check if RAW file. QString rawFilesExt(KDcrawIface::KDcraw::rawFiles()); if (rawFilesExt.toUpper().contains( fi.suffix().toUpper() )) KDcrawIface::KDcraw::loadDcrawPreview(img, orgUrl.path()); else img.load(orgUrl.path()); int sizeFactor = emailSettings.size(); if ( !img.isNull() ) { int w = img.width(); int h = img.height(); if( w > sizeFactor || h > sizeFactor ) { if( w > h ) { h = (int)( (double)( h * sizeFactor ) / w ); if ( h == 0 ) h = 1; w = sizeFactor; Q_ASSERT( h <= sizeFactor ); } else { w = (int)( (double)( w * sizeFactor ) / h ); if ( w == 0 ) w = 1; h = sizeFactor; Q_ASSERT( w <= sizeFactor ); } const QImage scaledImg(img.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); if ( scaledImg.width() != w || scaledImg.height() != h ) { err = i18n("Cannot resize image. Aborting."); return false; } img = scaledImg; } QString destPath = destName; KExiv2Iface::KExiv2 meta; meta.load(orgUrl.path()); meta.setImageProgramId(QString("Kipi-plugins"), QString(kipiplugins_version)); meta.setImageDimensions(img.size()); if (emailSettings.format() == QString("JPEG")) { if ( !img.save(destPath, emailSettings.format().toLatin1(), emailSettings.imageCompression) ) { err = i18n("Cannot save resized image (JPEG). Aborting."); return false; } else { meta.save(destPath); } } else if (emailSettings.format() == QString("PNG")) { QByteArray data((const char*)img.bits(), img.numBytes()); KIPIPlugins::KPWriteImage wImageIface; wImageIface.setImageData(data, img.width(), img.height(), false, true, QByteArray(), meta); if ( !wImageIface.write2PNG(destPath) ) { err = i18n("Cannot save resized image (PNG). Aborting."); return false; } } return true; } return false; }
// static QPixmap QPixmap::fromPmHBITMAP(HBITMAP hbm, HBITMAP hbmMask) { QPixmap res; if (hbm == NULLHANDLE) return res; // bitmap header + 2 palette entries (for the monochrome bitmap) char bmi[sizeof(BITMAPINFOHEADER2) + 4 * 2]; memset(bmi, 0, sizeof(bmi)); PBITMAPINFOHEADER2 bmh = (PBITMAPINFOHEADER2)bmi; bmh->cbFix = sizeof(BITMAPINFOHEADER2); PULONG pal = (PULONG)(bmi + sizeof(BITMAPINFOHEADER2)); if (!GpiQueryBitmapInfoHeader(hbm, bmh)) return res; HPS hps = qt_alloc_mem_ps(bmh->cx, bmh->cy * 2); if (hps == NULLHANDLE) return res; GpiSetBitmap(hps, hbm); QImage img; bool succeeded = false; if (bmh->cPlanes == 1 && bmh->cBitCount == 1) { // monochrome bitmap img = QImage(bmh->cx, bmh->cy, QImage::Format_Mono); if (GpiQueryBitmapBits(hps, 0, img.height(), (PBYTE)img.bits(), (PBITMAPINFO2)&bmi) != GPI_ALTERROR) { succeeded = true; // take the palette QVector<QRgb> colors(2); colors[0] = QRgb(pal[0]); colors[1] = QRgb(pal[1]); img.setColorTable(colors); } } else { // always convert to 32-bit otherwise img = QImage(bmh->cx, bmh->cy, QImage::Format_RGB32); bmh->cPlanes = 1; bmh->cBitCount = 32; if (GpiQueryBitmapBits(hps, 0, img.height(), (PBYTE)img.bits(), (PBITMAPINFO2)&bmi) != GPI_ALTERROR) { succeeded = true; // try to auto-detect if there is a real alpha channel bool allZero = true; for (int i = 0; i < img.numBytes(); ++i) { if (img.bits()[i] & 0xFF000000) { allZero = false; break; } } if (!allZero) { // assume we've got the alpha channel QImage alphaImg = QImage(bmh->cx, bmh->cy, QImage::Format_ARGB32); memcpy(alphaImg.bits(), img.bits(), img.numBytes()); img = alphaImg; } // flip the bitmap top to bottom to cancel PM inversion img = img.mirrored(); } } QImage mask; if (hbmMask != NULLHANDLE && GpiQueryBitmapInfoHeader(hbmMask, bmh)) { // get the AND+XOR mask if ((int)bmh->cx == img.width() && (int)bmh->cy == img.height() * 2 && bmh->cPlanes == 1 && bmh->cBitCount == 1) { GpiSetBitmap(hps, hbmMask); mask = QImage(bmh->cx, bmh->cy, QImage::Format_Mono); if (GpiQueryBitmapBits(hps, 0, mask.height(), (PBYTE)mask.bits(), (PBITMAPINFO2)&bmi) != GPI_ALTERROR) { // take the palette QVector<QRgb> colors(2); colors[0] = QRgb(pal[0]); colors[1] = QRgb(pal[1]); mask.setColorTable(colors); // flip the bitmap top to bottom to cancel PM inversion mask = mask.mirrored(false, true); // drop the XOR mask mask = mask.copy(0, 0, mask.width(), mask.height() / 2); // create a normal mask from the AND mask mask.invertPixels(); } else { mask = QImage(); } GpiSetBitmap(hps, NULLHANDLE); } else { Q_ASSERT(false); } } qt_free_mem_ps(hps); if (succeeded) { res = QPixmap::fromImage(img); if (!mask.isNull()) res.setMask(QBitmap::fromImage(mask)); } return res; }
void Uic::embed( QTextStream& out, const char* project, const QStringList& images ) { QString cProject = convertToCIdentifier( project ); QStringList::ConstIterator it; out << "/****************************************************************************\n"; out << "** Image collection for project '" << project << "'.\n"; out << "**\n"; out << "** Generated from reading image files: \n"; for ( it = images.begin(); it != images.end(); ++it ) out << "** " << *it << "\n"; out << "**\n"; out << "** Created: " << QDateTime::currentDateTime().toString() << "\n"; out << "** by: The User Interface Compiler ($Id: embed.cpp 2 2005-11-16 15:49:26Z dmik $)\n"; out << "**\n"; out << "** WARNING! All changes made in this file will be lost!\n"; out << "****************************************************************************/\n"; out << "\n"; out << "#include <qimage.h>\n"; out << "#include <qdict.h>\n"; out << "#include <qmime.h>\n"; out << "#include <qdragobject.h>\n"; out << "\n"; QPtrList<EmbedImage> list_image; list_image.setAutoDelete( TRUE ); int image_count = 0; for ( it = images.begin(); it != images.end(); ++it ) { QImage img; if ( !img.load( *it ) ) { fprintf( stderr, "uic: cannot load image file %s\n", (*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.fileName(); e->cname = QString("image_%1").arg( image_count++); list_image.append( e ); out << "// " << *it << "\n"; QString s; if ( e->depth == 1 ) img = img.convertBitOrder(QImage::BigEndian); out << s.sprintf( "static const unsigned char %s_data[] = {", (const char *)e->cname ); #ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION e->compressed = #endif embedData( out, img.bits(), img.numBytes() ); out << "\n};\n\n"; if ( e->numColors ) { out << s.sprintf( "static const QRgb %s_ctable[] = {", (const char *)e->cname ); embedData( out, e->colorTable, e->numColors ); out << "\n};\n\n"; } } if ( !list_image.isEmpty() ) { out << "static struct EmbedImage {\n" " int width, height, depth;\n" " const unsigned char *data;\n" #ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION " ulong compressed;\n" #endif " 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, " #ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION << e->compressed << ", " #endif << 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(); } #ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION out << " { 0, 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n"; #else out << " { 0, 0, 0, 0, 0, 0, 0, 0 }\n};\n"; #endif out << "\n" "static QImage uic_findImage( const QString& name )\n" "{\n" " for ( int i=0; embed_image_vec[i].data; i++ ) {\n" " if ( QString::fromUtf8(embed_image_vec[i].name) == name ) {\n" #ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION " QByteArray baunzip;\n" " baunzip = qUncompress( embed_image_vec[i].data, \n" " embed_image_vec[i].compressed );\n" " QImage img((uchar*)baunzip.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" " );\n" " img = img.copy();\n" #else " QImage img((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" " );\n" #endif " if ( embed_image_vec[i].alpha )\n" " img.setAlphaBuffer(TRUE);\n" " return img;\n" " }\n" " }\n" " return QImage();\n" "}\n\n"; out << "class MimeSourceFactory_" << cProject << " : public QMimeSourceFactory\n"; out << "{\n"; out << "public:\n"; out << " MimeSourceFactory_" << cProject << "() {}\n"; out << " ~MimeSourceFactory_" << cProject << "() {}\n"; out << " const QMimeSource* data( const QString& abs_name ) const {\n"; out << "\tconst QMimeSource* d = QMimeSourceFactory::data( abs_name );\n"; out << "\tif ( d || abs_name.isNull() ) return d;\n"; out << "\tQImage img = uic_findImage( abs_name );\n"; out << "\tif ( !img.isNull() )\n"; out << "\t ((QMimeSourceFactory*)this)->setImage( abs_name, img );\n"; out << "\treturn QMimeSourceFactory::data( abs_name );\n"; out << " };\n"; out << "};\n\n"; out << "static QMimeSourceFactory* factory = 0;\n"; out << "\n"; out << "void qInitImages_" << cProject << "()\n"; out << "{\n"; out << " if ( !factory ) {\n"; out << "\tfactory = new MimeSourceFactory_" << cProject << ";\n"; out << "\tQMimeSourceFactory::defaultFactory()->addFactory( factory );\n"; out << " }\n"; out << "}\n\n"; out << "void qCleanupImages_" << cProject << "()\n"; out << "{\n"; out << " if ( factory ) {\n"; out << "\tQMimeSourceFactory::defaultFactory()->removeFactory( factory );\n"; out << "\tdelete factory;\n"; out << "\tfactory = 0;\n"; out << " }\n"; out << "}\n\n"; out << "class StaticInitImages_" << cProject << "\n"; out << "{\n"; out << "public:\n"; out << " StaticInitImages_" << cProject << "() { qInitImages_" << cProject << "(); }\n"; out << "#if defined(Q_OS_SCO) || defined(Q_OS_UNIXWARE)\n"; out << " ~StaticInitImages_" << cProject << "() { }\n"; out << "#else\n"; out << " ~StaticInitImages_" << cProject << "() { qCleanupImages_" << cProject << "(); }\n"; out << "#endif\n"; out << "};\n\n"; out << "static StaticInitImages_" << cProject << " staticImages;\n"; } }
extern "C" void gxpport_decodeimmutable_to_platformbuffer (unsigned char* srcBuffer, long length, unsigned char** ret_dataBuffer, long* ret_length, gxutl_native_image_error_codes* creationErrorPtr) { gxutl_image_format format; MIDP_ERROR err; unsigned int w, h; err = gxutl_image_get_info(srcBuffer, (unsigned int)length, &format, &w, &h); switch (err) { case MIDP_ERROR_NONE: break; /* continue */ case MIDP_ERROR_IMAGE_CORRUPTED: *creationErrorPtr = GXUTL_NATIVE_IMAGE_DECODING_ERROR; return; default: *creationErrorPtr = GXUTL_NATIVE_IMAGE_UNSUPPORTED_FORMAT_ERROR; return; } switch (format) { case GXUTL_IMAGE_FORMAT_RAW: /* already in RAW format. make a copy */ { unsigned char* dataBuffer = (unsigned char*) midpMalloc(length); if (NULL == dataBuffer) { *creationErrorPtr = GXUTL_NATIVE_IMAGE_OUT_OF_MEMORY_ERROR; } else { memcpy(dataBuffer, srcBuffer, length); *ret_dataBuffer = dataBuffer; *ret_length = length; *creationErrorPtr = GXUTL_NATIVE_IMAGE_NO_ERROR; } } break; case GXUTL_IMAGE_FORMAT_JPEG: case GXUTL_IMAGE_FORMAT_PNG: { QImage qimage; if (qimage.loadFromData((uchar*)srcBuffer, (unsigned int)length)) { int imgWidth = qimage.width(); int imgHeight = qimage.height(); if ((0 == imgWidth) || (0 == imgHeight)) { *creationErrorPtr = GXUTL_NATIVE_IMAGE_DECODING_ERROR; } else { QImage image; if (IMAGE_DEPTH != qimage.depth()) { image = qimage.convertDepth(IMAGE_DEPTH); } else { image = qimage; } *ret_length = offsetof(gxutl_image_buffer_raw, data) + image.numBytes(); gxutl_image_buffer_raw *dataBuffer = (gxutl_image_buffer_raw *) midpMalloc(*ret_length); if (NULL == dataBuffer) { *creationErrorPtr = GXUTL_NATIVE_IMAGE_OUT_OF_MEMORY_ERROR; } else { dataBuffer->width = (unsigned int)imgWidth; dataBuffer->height = (unsigned int)imgHeight; dataBuffer->hasAlpha = (unsigned int)image.hasAlphaBuffer(); memcpy(dataBuffer->header, gxutl_raw_header, 4); memcpy(dataBuffer->data, image.bits(), image.numBytes()); *ret_dataBuffer = (unsigned char *)dataBuffer; *creationErrorPtr = GXUTL_NATIVE_IMAGE_NO_ERROR; } } } else { *creationErrorPtr = GXUTL_NATIVE_IMAGE_DECODING_ERROR; } } break; default: *creationErrorPtr = GXUTL_NATIVE_IMAGE_UNSUPPORTED_FORMAT_ERROR; break; } /* switch (format) */ }
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; }
void QPF::addGlyphs(QFontEngine *fe, const QList<CharacterRange> &ranges) { const quint16 glyphCount = fe->glyphCount(); QByteArray gmap; gmap.resize(glyphCount * sizeof(quint32)); gmap.fill(char(0xff)); //qDebug() << "glyphCount" << glyphCount; QByteArray glyphs; if (options & RenderGlyphs) { // this is only a rough estimation glyphs.reserve(glyphCount * (sizeof(QFontEngineQPF::Glyph) + qRound(fe->maxCharWidth() * (fe->ascent() + fe->descent()).toReal()))); QGlyphLayout layout[10]; foreach (CharacterRange range, ranges) { if (debugVerbosity > 2) qDebug() << "rendering range from" << range.start << "to" << range.end; for (uint uc = range.start; uc < range.end; ++uc) { QChar ch(uc); int nglyphs = 10; if (!fe->stringToCMap(&ch, 1, &layout[0], &nglyphs, /*flags*/ 0)) continue; if (nglyphs != 1) continue; const quint32 glyphIndex = layout[0].glyph; if (!glyphIndex) continue; Q_ASSERT(glyphIndex < glyphCount); QImage img = fe->alphaMapForGlyph(glyphIndex).convertToFormat(QImage::Format_Indexed8); glyph_metrics_t metrics = fe->boundingBox(glyphIndex); const quint32 oldSize = glyphs.size(); glyphs.resize(glyphs.size() + sizeof(QFontEngineQPF::Glyph) + img.numBytes()); uchar *data = reinterpret_cast<uchar *>(glyphs.data() + oldSize); uchar *gmapPtr = reinterpret_cast<uchar *>(gmap.data() + glyphIndex * sizeof(quint32)); qToBigEndian(oldSize, gmapPtr); QFontEngineQPF::Glyph *glyph = reinterpret_cast<QFontEngineQPF::Glyph *>(data); glyph->width = img.width(); glyph->height = img.height(); glyph->bytesPerLine = img.bytesPerLine(); glyph->x = qRound(metrics.x); glyph->y = qRound(metrics.y); glyph->advance = qRound(metrics.xoff); data += sizeof(QFontEngineQPF::Glyph); if (debugVerbosity && uc >= 'A' && uc <= 'z' || debugVerbosity > 1) { qDebug() << "adding glyph with index" << glyphIndex << " uc =" << char(uc) << ":\n" << " glyph->x =" << glyph->x << "rounded from" << metrics.x << "\n" << " glyph->y =" << glyph->y << "rounded from" << metrics.y << "\n" << " width =" << glyph->width << "height =" << glyph->height << " advance =" << glyph->advance << "rounded from" << metrics.xoff ; } qMemCopy(data, img.bits(), img.numBytes()); } } }
/*! This function decodes some data into image changes. Returns the number of bytes consumed. */ int QGIFFormat::decode(QImage& img, QImageConsumer* consumer, const uchar* buffer, int length) { // We are required to state that // "The Graphics Interchange Format(c) is the Copyright property of // CompuServe Incorporated. GIF(sm) is a Service Mark property of // CompuServe Incorporated." #define LM(l, m) (((m)<<8)|l) digress = FALSE; int initial = length; QRgb** line = (QRgb **)img.jumpTable(); while (!digress && length) { length--; unsigned char ch=*buffer++; switch (state) { case Header: hold[count++]=ch; if (count==6) { // Header gif89=(hold[3]!='8' || hold[4]!='7'); state=LogicalScreenDescriptor; count=0; } break; case LogicalScreenDescriptor: hold[count++]=ch; if (count==7) { // Logical Screen Descriptor swidth=LM(hold[0], hold[1]); sheight=LM(hold[2], hold[3]); gcmap=!!(hold[4]&0x80); //UNUSED: bpchan=(((hold[4]&0x70)>>3)+1); //UNUSED: gcmsortflag=!!(hold[4]&0x08); gncols=2<<(hold[4]&0x7); bgcol=(gcmap) ? hold[5] : -1; //aspect=hold[6] ? double(hold[6]+15)/64.0 : 1.0; trans_index = -1; count=0; ncols=gncols; if (gcmap) { ccount=0; state=GlobalColorMap; globalcmap = new QRgb[gncols+1]; // +1 for trans_index globalcmap[gncols] = Q_TRANSPARENT; } else { state=Introducer; } } break; case GlobalColorMap: case LocalColorMap: hold[count++]=ch; if (count==3) { QRgb rgb = qRgb(hold[0], hold[1], hold[2]); if ( state == LocalColorMap ) { if ( ccount < lncols ) localcmap[ccount] = rgb; } else { globalcmap[ccount] = rgb; } if (++ccount >= ncols) { if ( state == LocalColorMap ) state=TableImageLZWSize; else state=Introducer; } count=0; } break; case Introducer: hold[count++]=ch; switch (ch) { case ',': state=ImageDescriptor; break; case '!': state=ExtensionLabel; break; case ';': if (consumer) { if ( out_of_bounds ) // flush anything that survived consumer->changed(QRect(0,0,swidth,sheight)); consumer->end(); } state=Done; break; default: digress=TRUE; // Unexpected Introducer - ignore block state=Error; } break; case ImageDescriptor: hold[count++]=ch; if (count==10) { int newleft=LM(hold[1], hold[2]); int newtop=LM(hold[3], hold[4]); int width=LM(hold[5], hold[6]); int height=LM(hold[7], hold[8]); // disbelieve ridiculous logical screen sizes, // unless the image frames are also large. if ( swidth/10 > QMAX(width,200) ) swidth = -1; if ( sheight/10 > QMAX(height,200) ) sheight = -1; if ( swidth <= 0 ) swidth = newleft + width; if ( sheight <= 0 ) sheight = newtop + height; if (img.isNull()) { img.create(swidth, sheight, 32); memset( img.bits(), 0, img.numBytes() ); if (consumer) consumer->setSize(swidth, sheight); } img.setAlphaBuffer(trans_index >= 0); line = (QRgb **)img.jumpTable(); disposePrevious( img, consumer ); disposed = FALSE; left = newleft; top = newtop; // Sanity check frame size - must fit on "screen". if (left >= swidth) left=QMAX(0, swidth-1); if (top >= sheight) top=QMAX(0, sheight-1); if (left+width >= swidth) { if ( width <= swidth ) left=swidth-width; else width=swidth-left; } if (top+height >= sheight) { if ( height <= sheight ) top=sheight-height; else height=sheight-top; } right=QMAX( 0, left+width-1); bottom=QMAX(0, top+height-1); lcmap=!!(hold[9]&0x80); interlace=!!(hold[9]&0x40); //bool lcmsortflag=!!(hold[9]&0x20); lncols=lcmap ? (2<<(hold[9]&0x7)) : 0; if (lncols) { if ( localcmap ) delete [] localcmap; localcmap = new QRgb[lncols+1]; localcmap[lncols] = Q_TRANSPARENT; ncols = lncols; } else { ncols = gncols; } frame++; if ( frame == 0 ) { if ( left || top || width!=swidth || height!=sheight ) { // Not full-size image - erase with bg or transparent if ( trans_index >= 0 ) { fillRect(img, 0, 0, swidth, sheight, color(trans_index)); if (consumer) consumer->changed(QRect(0,0,swidth,sheight)); } else if ( bgcol>=0 ) { fillRect(img, 0, 0, swidth, sheight, color(bgcol)); if (consumer) consumer->changed(QRect(0,0,swidth,sheight)); } } } if ( disposal == RestoreImage ) { int l = QMIN(swidth-1,left); int r = QMIN(swidth-1,right); int t = QMIN(sheight-1,top); int b = QMIN(sheight-1,bottom); int w = r-l+1; int h = b-t+1; if (backingstore.width() < w || backingstore.height() < h) { // We just use the backing store as a byte array backingstore.create( QMAX(backingstore.width(), w), QMAX(backingstore.height(), h), 32); memset( img.bits(), 0, img.numBytes() ); } for (int ln=0; ln<h; ln++) { memcpy(backingstore.scanLine(ln), line[t+ln]+l, w*sizeof(QRgb)); } } count=0; if (lcmap) { ccount=0; state=LocalColorMap; } else { state=TableImageLZWSize; } x = left; y = top; accum = 0; bitcount = 0; sp = stack; needfirst = FALSE; out_of_bounds = FALSE; } break; case TableImageLZWSize: { lzwsize=ch; if ( lzwsize > max_lzw_bits ) { state=Error; } else { code_size=lzwsize+1; clear_code=1<<lzwsize; end_code=clear_code+1; max_code_size=2*clear_code; max_code=clear_code+2; int i; for (i=0; i<clear_code && i<(1<<max_lzw_bits); i++) { table[0][i]=0; table[1][i]=i; } for (i=clear_code; i<(1<<max_lzw_bits); i++) { table[0][i]=table[1][i]=0; } state=ImageDataBlockSize; } count=0; break; } case ImageDataBlockSize: expectcount=ch; if (expectcount) { state=ImageDataBlock; } else { if (consumer) { consumer->frameDone(); digress = TRUE; } state=Introducer; } break; case ImageDataBlock: count++; accum|=(ch<<bitcount); bitcount+=8; while (bitcount>=code_size && state==ImageDataBlock) { int code=accum&((1<<code_size)-1); bitcount-=code_size; accum>>=code_size; if (code==clear_code) { if (!needfirst) { int i; code_size=lzwsize+1; max_code_size=2*clear_code; max_code=clear_code+2; for (i=0; i<clear_code; i++) { table[0][i]=0; table[1][i]=i; } for (i=clear_code; i<(1<<max_lzw_bits); i++) { table[0][i]=table[1][i]=0; } } needfirst=TRUE; } else if (code==end_code) { bitcount = -32768; // Left the block end arrive } else { if (needfirst) { firstcode=oldcode=code; if (!out_of_bounds && line && firstcode!=trans_index) line[y][x] = color(firstcode); x++; if (x>=swidth) out_of_bounds = TRUE; needfirst=FALSE; if (x>right) { x=left; if (out_of_bounds) out_of_bounds = left>=swidth || y>=sheight; nextY(img,consumer); } } else { incode=code; if (code>=max_code) { *sp++=firstcode; code=oldcode; } while (code>=clear_code) { *sp++=table[1][code]; if (code==table[0][code]) { state=Error; break; } if (sp-stack>=(1<<(max_lzw_bits))*2) { state=Error; break; } code=table[0][code]; } *sp++=firstcode=table[1][code]; code=max_code; if (code<(1<<max_lzw_bits)) { table[0][code]=oldcode; table[1][code]=firstcode; max_code++; if ((max_code>=max_code_size) && (max_code_size<(1<<max_lzw_bits))) { max_code_size*=2; code_size++; } } oldcode=incode; while (sp>stack) { --sp; if (!out_of_bounds && *sp!=trans_index) line[y][x] = color(*sp); x++; if (x>=swidth) out_of_bounds = TRUE; if (x>right) { x=left; if (out_of_bounds) out_of_bounds = left>=swidth || y>=sheight; nextY(img,consumer); } } } } } if (count==expectcount) { count=0; state=ImageDataBlockSize; } break; case ExtensionLabel: switch (ch) { case 0xf9: state=GraphicControlExtension; break; case 0xff: state=ApplicationExtension; break; #if 0 case 0xfe: state=CommentExtension; break; case 0x01: break; #endif default: state=SkipBlockSize; } count=0; break; case ApplicationExtension: if (count<11) hold[count]=ch; count++; if (count==hold[0]+1) { if (qstrncmp((char*)(hold+1), "NETSCAPE", 8)==0) { // Looping extension state=NetscapeExtensionBlockSize; } else { state=SkipBlockSize; } count=0; } break; case NetscapeExtensionBlockSize: expectcount=ch; count=0; if (expectcount) state=NetscapeExtensionBlock; else state=Introducer; break; case NetscapeExtensionBlock: if (count<3) hold[count]=ch; count++; if (count==expectcount) { int loop = hold[0]+hold[1]*256; if (consumer) consumer->setLooping(loop); state=SkipBlockSize; // Ignore further blocks } break; case GraphicControlExtension: if (count<5) hold[count]=ch; count++; if (count==hold[0]+1) { disposePrevious( img, consumer ); disposal=Disposal((hold[1]>>2)&0x7); //UNUSED: waitforuser=!!((hold[1]>>1)&0x1); int delay=count>3 ? LM(hold[2], hold[3]) : 1; // IE and mozilla use a minimum delay of 10. With the minumum delay of 10 // we are compatible to them and avoid huge loads on the app and xserver. if ( delay < 10 ) delay = 10; bool havetrans=hold[1]&0x1; trans_index = havetrans ? hold[4] : -1; if (consumer) consumer->setFramePeriod(delay*10); count=0; state=SkipBlockSize; } break; case SkipBlockSize: expectcount=ch; count=0; if (expectcount) state=SkipBlock; else state=Introducer; break; case SkipBlock: count++; if (count==expectcount) state=SkipBlockSize; break; case Done: digress=TRUE; /* Netscape ignores the junk, so we do too. length++; // Unget state=Error; // More calls to this is an error */ break; case Error: return -1; // Called again after done. } }