📄 qgifimageformat.cpp
字号:
/****************************************************************************** $Id: qt/src/3rdparty/kernel/qgifimageformat.cpp 2.3.8 edited 2004-08-05 $**** Implementation of gif image/movie loading classes**** Created : 970617**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the kernel module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qgifimageformat_p.h"#define Q_TRANSPARENT 0x00ffffff/*! Returns TRUE if Qt was compiled with built-in GIF reading support, otherwise FALSE.*/bool qt_builtin_gif_reader(){#if defined(QT_BUILTIN_GIF_READER) return QT_BUILTIN_GIF_READER == 1;#else return 0;#endif}#ifndef QT_NO_ASYNC_IMAGE_IO// See qgif.h for important information regarding this option#if defined(QT_BUILTIN_GIF_READER) && QT_BUILTIN_GIF_READER == 1class Q_EXPORT QGIFFormat : public QImageFormat {public: QGIFFormat(); virtual ~QGIFFormat(); int decode(QImage& img, QImageConsumer* consumer, const uchar* buffer, int length);private: void fillRect(QImage&, int x, int y, int w, int h, QRgb col); QRgb color( uchar index ) const; // GIF specific stuff QRgb* globalcmap; QRgb* localcmap; QImage backingstore; unsigned char hold[16]; bool gif89; int count; int ccount; int expectcount; enum State { Header, LogicalScreenDescriptor, GlobalColorMap, LocalColorMap, Introducer, ImageDescriptor, TableImageLZWSize, ImageDataBlockSize, ImageDataBlock, ExtensionLabel, GraphicControlExtension, ApplicationExtension, NetscapeExtensionBlockSize, NetscapeExtensionBlock, SkipBlockSize, SkipBlock, Done, Error } state; int gncols; int lncols; int ncols; int lzwsize; bool lcmap; int swidth, sheight; int left, top, right, bottom; enum Disposal { NoDisposal, DoNotChange, RestoreBackground, RestoreImage }; Disposal disposal; bool disposed; int trans_index; bool gcmap; int bgcol; int interlace; int accum; int bitcount; enum { max_lzw_bits=12 }; // (poor-compiler's static const int) int code_size, clear_code, end_code, max_code_size, max_code; int firstcode, oldcode, incode; short table[2][1<< max_lzw_bits]; short stack[(1<<(max_lzw_bits))*2]; short *sp; bool needfirst; int x, y; int frame; bool out_of_bounds; bool digress; void nextY(QImage& img, QImageConsumer* consumer); void disposePrevious( QImage& img, QImageConsumer* consumer );};/* -- NOTDOC \class QGIFFormat qasyncimageio.h \brief Incremental image decoder for GIF image format. \ingroup images This subclass of QImageFormat decodes GIF format images, including animated GIFs. Internally in*//*! Constructs a QGIFFormat.*/QGIFFormat::QGIFFormat(){ globalcmap = 0; localcmap = 0; lncols = 0; gncols = 0; disposal = NoDisposal; out_of_bounds = FALSE; disposed = TRUE; frame = -1; state = Header; count = 0; lcmap = FALSE;}/*! Destructs a QGIFFormat.*/QGIFFormat::~QGIFFormat(){ if (globalcmap) delete[] globalcmap; if ( localcmap ) delete[] localcmap;}/* -- NOTDOC \class QGIFFormatType qasyncimageio.h \brief Incremental image decoder for GIF image format. \ingroup images This subclass of QImageFormatType recognizes GIF format images, creating a QGIFFormat when required. An instance of this class is created automatically before any other factories, so you should have no need for such objects.*/QImageFormat* QGIFFormatType::decoderFor( const uchar* buffer, int length){ if (length < 6) return 0; if (buffer[0]=='G' && buffer[1]=='I' && buffer[2]=='F' && buffer[3]=='8' && (buffer[4]=='9' || buffer[4]=='7') && buffer[5]=='a') return new QGIFFormat; return 0;}const char* QGIFFormatType::formatName() const{ return "GIF";}void QGIFFormat::disposePrevious( QImage& img, QImageConsumer* consumer ){ if ( out_of_bounds ) // flush anything that survived consumer->changed(QRect(0,0,swidth,sheight)); // Handle disposal of previous image before processing next one if ( disposed ) return; int l = QMIN(swidth-1,left); int r = QMIN(swidth-1,right); int t = QMIN(sheight-1,top); int b = QMIN(sheight-1,bottom); switch (disposal) { case NoDisposal: break; case DoNotChange: break; case RestoreBackground: if (trans_index>=0) { // Easy: we use the transparent color fillRect(img, l, t, r-l+1, b-t+1, Q_TRANSPARENT); } else if (bgcol>=0) { // Easy: we use the bgcol given fillRect(img, l, t, r-l+1, b-t+1, color(bgcol)); } else { // Impossible: We don't know of a bgcol - use pixel 0 QRgb** line = (QRgb **)img.jumpTable(); fillRect(img, l, t, r-l+1, b-t+1, line[0][0]); } if (consumer) consumer->changed(QRect(l, t, r-l+1, b-t+1)); break; case RestoreImage: { if ( frame > 0 ) { QRgb** line = (QRgb **)img.jumpTable(); for (int ln=t; ln<=b; ln++) { memcpy(line[ln]+l, backingstore.scanLine(ln-t), (r-l+1)*sizeof(QRgb) ); } consumer->changed(QRect(l, t, r-l+1, b-t+1)); } } } disposal = NoDisposal; // Until an extension says otherwise. disposed = TRUE;}/*! 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -