📄 qgifimageformat.cpp
字号:
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 ( bgcol>=0 ) { fillRect(img, 0, 0, swidth, sheight, bgcol); if (consumer) consumer->changed(QRect(0,0,swidth,sheight)); } else if ( trans_index > 0 ) { fillRect(img, 0, 0, swidth, sheight, trans_index); 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), 8,1); } for (int ln=0; ln<h; ln++) { memcpy(backingstore.scanLine(ln), line[t+ln]+l, w); } } count=0; if (lcmap) { ccount=0; state=LocalColorMap; } else { if (gcmap) { int n=ncols; if (n<256) n++; // +1 for trans_index if ( !img.colorTable() || img.numColors() < n ) img.setNumColors( n ); memcpy(img.colorTable(), globalcmap, n * sizeof(QRgb)); } 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) { if (firstcode==trans) { if ( !preserve_trans && line ) line[y][x] = trans_index; } else if ( line ) { line[y][x] = 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) { if (*sp==trans) { if ( !preserve_trans ) line[y][x] = trans_index; } else { line[y][x] = *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;/////////////////////////////////////////// Ignored at this time //////// case 0xfe:// state=CommentExtension;// break;// case 0x01:// break;/////////////////////////////////////////////////////////////////////// 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; // Why if the extension here, if it is supposed to only // play through once? We assume that the creator meant // 0, which is infinite. if (loop == 1) loop = 0; 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; if ( delay < 1 ) delay = 1; bool havetrans=hold[1]&0x1; int newtrans=havetrans ? hold[4] : -1; if (newtrans > ncols) { // Ignore invalid transparency. newtrans=-1; } if (newtrans >= 0 && frame>=0) preserve_trans = TRUE; if (newtrans != trans) { if (trans >= 0 && trans < gncols) { if (globalcmap && trans_index >=0 && trans_index < gncols) globalcmap[trans_index]|=0xff000000; } trans = newtrans; if ( ncols < 256 ) trans_index = ncols; else trans_index = newtrans; if (trans >= 0 && trans < gncols) { if (globalcmap && trans_index >=0 && trans_index < gncols) globalcmap[trans_index]&=0x00ffffff; } } 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. } } return initial-length;}void QGIFFormat::fillRect(QImage& img, int col, int row, int w, int h, uchar color){ if (w>0) { uchar** line = img.jumpTable() + row; for (int j=0; j<h; j++) { memset(line[j]+col, color, w); } }}void QGIFFormat::nextY(QImage& img, QImageConsumer* consumer){ int my; switch (interlace) { case 0: // Non-interlaced if (consumer && !out_of_bounds) consumer->changed(QRect(left, y, right-left+1, 1)); y++; break; case 1: { int i; my = QMIN(7, bottom-y); if ( trans<0 ) // Don't dup with transparency for (i=1; i<=my; i++) memcpy(img.scanLine(y+i)+left, img.scanLine(y)+left, right-left+1); if (consumer && !out_of_bounds) consumer->changed(QRect(left, y, right-left+1, my+1)); y+=8; if (y>bottom) { interlace++; y=top+4; if (y > bottom) { // for really broken GIFs with bottom < 5 interlace=2; y = top + 2; if (y > bottom) { // for really broken GIF with bottom < 3 interlace = 0; y = top + 1; } } } } break; case 2: { int i; my = QMIN(3, bottom-y); if ( trans<0 ) // Don't dup with transparency for (i=1; i<=my; i++) memcpy(img.scanLine(y+i)+left, img.scanLine(y)+left, right-left+1); if (consumer && !out_of_bounds) consumer->changed(QRect(left, y, right-left+1, my+1)); y+=8; if (y>bottom) { interlace++; y=top+2; if (y > bottom) { // for really broken GIF with bottom < 3 interlace = 3; y = top + 1; } } } break; case 3: { int i; my = QMIN(1, bottom-y); if ( trans<0 ) // Don't dup with transparency for (i=1; i<=my; i++) memcpy(img.scanLine(y+i)+left, img.scanLine(y)+left, right-left+1); if (consumer && !out_of_bounds) consumer->changed(QRect(left, y, right-left+1, my+1)); y+=4; if (y>bottom) { interlace++; y=top+1; } } break; case 4: if (consumer && !out_of_bounds) consumer->changed(QRect(left, y, right-left+1, 1)); y+=2; } // Consume bogus extra lines if (y >= sheight) out_of_bounds=TRUE; //y=bottom;}#endif // QT_BUILTIN_GIF_READER#endif // QT_NO_ASYNC_IMAGE_IO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -