200int QGIFFormat::decode(QImage *image,
const uchar *buffer,
int length,
201 int *nextFrameDelay,
int *loopCount)
209 stack =
new short[(1 << max_lzw_bits) * 4];
210 table[0] = &stack[(1 << max_lzw_bits) * 2];
211 table[1] = &stack[(1 << max_lzw_bits) * 3];
215 qsizetype bpl = image->bytesPerLine();
216 unsigned char *bits = image->bits();
218#define LM(l, m) (((m)<<8
)|l)
220 const int initial = length;
221 while (!digress && length) {
223 unsigned char ch=*buffer++;
229 gif89=(hold[3]!=
'8' || hold[4]!=
'7');
230 state=LogicalScreenDescriptor;
234 case LogicalScreenDescriptor:
238 swidth=
LM(hold[0], hold[1]);
239 sheight=
LM(hold[2], hold[3]);
240 gcmap=!!(hold[4]&0x80);
243 gncols=2<<(hold[4]&0x7);
244 bgcol=(gcmap) ? hold[5] : -1;
252 state=GlobalColorMap;
253 globalcmap =
new QRgb[gncols+1];
260 case GlobalColorMap:
case LocalColorMap:
263 QRgb rgb = qRgb(hold[0], hold[1], hold[2]);
264 if (state == LocalColorMap) {
266 localcmap[ccount] = rgb;
268 globalcmap[ccount] = rgb;
270 if (++ccount >= ncols) {
271 if (state == LocalColorMap)
272 state=TableImageLZWSize;
283 state=ImageDescriptor;
286 state=ExtensionLabel;
298 case ImageDescriptor:
301 int newleft=
LM(hold[1], hold[2]);
302 int newtop=
LM(hold[3], hold[4]);
303 int newwidth=
LM(hold[5], hold[6]);
304 int newheight=
LM(hold[7], hold[8]);
308 if (swidth/10 > qMax(newwidth,16384))
310 if (sheight/10 > qMax(newheight,16384))
314 swidth = newleft + newwidth;
316 sheight = newtop + newheight;
318 QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32;
319 if (image->isNull()) {
320 if (!withinSizeLimit(swidth, sheight)) {
324 if (!QImageIOHandler::allocateImage(QSize(swidth, sheight), format, image)) {
328 bpl = image->bytesPerLine();
329 bits = image->bits();
331 memset(bits, 0, image->sizeInBytes());
336 if (image->isNull()) {
341 disposePrevious(image);
349 right=qMax(0, qMin(left+width, swidth)-1);
350 bottom=qMax(0, qMin(top+height, sheight)-1);
351 lcmap=!!(hold[9]&0x80);
352 interlace=!!(hold[9]&0x40);
354 lncols=lcmap ? (2<<(hold[9]&0x7)) : 0;
358 localcmap =
new QRgb[lncols+1];
366 if (left || top || width<swidth || height<sheight) {
368 if (trans_index >= 0) {
369 fillRect(image, 0, 0, swidth, sheight, color(trans_index));
371 }
else if (bgcol>=0) {
372 fillRect(image, 0, 0, swidth, sheight, color(bgcol));
378 if (disposal == RestoreImage) {
379 int l = qMin(swidth-1,left);
380 int r = qMin(swidth-1,right);
381 int t = qMin(sheight-1,top);
382 int b = qMin(sheight-1,bottom);
386 if (backingstore.width() < w
387 || backingstore.height() < h) {
389 if (!withinSizeLimit(w, h)) {
394 QSize bsSize(qMax(backingstore.width(), w), qMax(backingstore.height(), h));
395 if (!QImageIOHandler::allocateImage(bsSize, QImage::Format_RGB32,
400 memset(backingstore.bits(), 0, backingstore.sizeInBytes());
402 const qsizetype dest_bpl = backingstore.bytesPerLine();
403 unsigned char *dest_data = backingstore.bits();
404 for (
int ln=0; ln<h; ln++) {
406 FAST_SCAN_LINE(bits, bpl, t+ln) + l*
sizeof(QRgb), w*
sizeof(QRgb));
415 state=TableImageLZWSize;
422 firstcode = oldcode = 0;
424 out_of_bounds = left>=swidth || y>=sheight;
427 case TableImageLZWSize: {
429 if (lzwsize > max_lzw_bits) {
433 clear_code=1<<lzwsize;
434 end_code=clear_code+1;
435 max_code_size=2*clear_code;
436 max_code=clear_code+2;
438 for (i=0; i<clear_code; i++) {
442 state=ImageDataBlockSize;
446 }
case ImageDataBlockSize:
449 state=ImageDataBlock;
458 if (bitcount != -32768) {
459 if (bitcount < 0 || bitcount > 31) {
463 accum |= (ch << bitcount);
466 while (bitcount>=code_size && state==ImageDataBlock) {
467 int code=accum&((1<<code_size)-1);
471 if (code==clear_code) {
474 max_code_size=2*clear_code;
475 max_code=clear_code+2;
478 }
else if (code==end_code) {
483 firstcode=oldcode=code;
484 if (!out_of_bounds && image->height() > y && ((frame == 0) || (firstcode != trans_index)))
487 if (x>=swidth) out_of_bounds =
true;
491 out_of_bounds = left>=swidth || y>=sheight;
496 if (code>=max_code) {
500 while (code>=clear_code+2) {
501 if (code >= max_code) {
505 *sp++=table[1][code];
506 if (code==table[0][code]) {
510 if (sp-stack>=(1<<(max_lzw_bits))*2) {
521 *sp++=firstcode=table[1][code];
523 if (code<(1<<max_lzw_bits)) {
524 table[0][code]=oldcode;
525 table[1][code]=firstcode;
527 if ((max_code>=max_code_size)
528 && (max_code_size<(1<<max_lzw_bits)))
535 const int h = image->height();
536 QRgb *line =
nullptr;
537 if (!out_of_bounds && h > y)
540 const uchar index = *(--sp);
541 if (!out_of_bounds && h > y && ((frame == 0) || (index != trans_index))) {
542 line[x] = color(index);
545 if (x>=swidth) out_of_bounds =
true;
548 out_of_bounds = left>=swidth || y>=sheight;
550 if (!out_of_bounds && h > y)
557 partialNewFrame =
true;
558 if (count==expectcount) {
560 state=ImageDataBlockSize;
566 state=GraphicControlExtension;
569 state=ApplicationExtension;
573 state=CommentExtension;
583 case ApplicationExtension:
584 if (count<11) hold[count]=ch;
586 if (count==hold[0]+1) {
587 if (qstrncmp((
char*)(hold+1),
"NETSCAPE", 8)==0) {
589 state=NetscapeExtensionBlockSize;
596 case NetscapeExtensionBlockSize:
599 if (expectcount) state=NetscapeExtensionBlock;
600 else state=Introducer;
602 case NetscapeExtensionBlock:
603 if (count<3) hold[count]=ch;
605 if (count==expectcount) {
606 *loopCount = hold[1]+hold[2]*256;
610 case GraphicControlExtension:
611 if (count<5) hold[count]=ch;
613 if (count==hold[0]+1) {
614 disposePrevious(image);
615 uint dBits = (hold[1] >> 2) & 0x7;
616 disposal = (dBits <= RestoreImage) ? Disposal(dBits) : NoDisposal;
618 int delay=count>3 ?
LM(hold[2], hold[3]) : 1;
621 *nextFrameDelay = (delay < 2 ? 10 : delay) * 10;
623 bool havetrans=hold[1]&0x1;
624 trans_index = havetrans ? hold[4] : -1;
633 if (expectcount) state=SkipBlock;
634 else state=Introducer;
638 if (count==expectcount) state=SkipBlockSize;
643
644
645
651 return initial-length;
658void QGIFFormat::scan(QIODevice *device, QList<QSize> *imageSizes,
int *loopCount)
663 qint64 oldPos = device->pos();
664 if (device->isSequential() || !device->seek(0))
668 int localColorCount = 0;
669 int globalColorCount = 0;
670 int colorReadCount = 0;
671 bool localColormap =
false;
672 bool globalColormap =
false;
679 State state = Header;
681 const int readBufferSize = 40960;
682 QByteArray readBuffer(device->read(readBufferSize));
684 if (readBuffer.isEmpty()) {
685 device->seek(oldPos);
694 while (!readBuffer.isEmpty()) {
695 int length = readBuffer.size();
696 const uchar *buffer = (
const uchar *) readBuffer.constData();
697 while (!done && length) {
699 uchar ch = *buffer++;
704 state = LogicalScreenDescriptor;
708 case LogicalScreenDescriptor:
711 imageWidth =
LM(hold[0], hold[1]);
712 imageHeight =
LM(hold[2], hold[3]);
713 globalColormap = !!(hold[4] & 0x80);
714 globalColorCount = 2 << (hold[4] & 0x7);
716 colorCount = globalColorCount;
717 if (globalColormap) {
718 int colorTableSize = 3 * globalColorCount;
719 if (length >= colorTableSize) {
721 length -= colorTableSize;
722 buffer += colorTableSize;
726 state = GlobalColorMap;
737 if (++colorReadCount >= colorCount) {
738 if (state == LocalColorMap)
739 state = TableImageLZWSize;
750 state = ImageDescriptor;
753 state = ExtensionLabel;
763 case ImageDescriptor:
766 int newLeft =
LM(hold[1], hold[2]);
767 int newTop =
LM(hold[3], hold[4]);
768 int newWidth =
LM(hold[5], hold[6]);
769 int newHeight =
LM(hold[7], hold[8]);
771 if (imageWidth/10 > qMax(newWidth,200))
773 if (imageHeight/10 > qMax(newHeight,200))
777 imageWidth = newLeft + newWidth;
778 if (imageHeight <= 0)
779 imageHeight = newTop + newHeight;
781 *imageSizes << QSize(imageWidth, imageHeight);
783 localColormap = !!(hold[9] & 0x80);
784 localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
786 colorCount = localColorCount;
788 colorCount = globalColorCount;
792 int colorTableSize = 3 * localColorCount;
793 if (length >= colorTableSize) {
795 length -= colorTableSize;
796 buffer += colorTableSize;
797 state = TableImageLZWSize;
800 state = LocalColorMap;
803 state = TableImageLZWSize;
807 case TableImageLZWSize:
808 if (ch > max_lzw_bits)
811 state = ImageDataBlockSize;
814 case ImageDataBlockSize:
817 if (length >= blockSize) {
823 state = ImageDataBlock;
831 if (count == blockSize) {
833 state = ImageDataBlockSize;
839 state = GraphicControlExtension;
842 state = ApplicationExtension;
845 state = SkipBlockSize;
849 case ApplicationExtension:
853 if (count == hold[0] + 1) {
854 if (qstrncmp((
char*)(hold+1),
"NETSCAPE", 8) == 0)
855 state=NetscapeExtensionBlockSize;
861 case GraphicControlExtension:
865 if (count == hold[0] + 1) {
867 state = SkipBlockSize;
870 case NetscapeExtensionBlockSize:
874 state = NetscapeExtensionBlock;
878 case NetscapeExtensionBlock:
882 if (count == blockSize) {
883 *loopCount =
LM(hold[1], hold[2]);
884 state = SkipBlockSize;
891 if (length >= blockSize) {
904 if (count == blockSize)
905 state = SkipBlockSize;
911 device->seek(oldPos);
915 readBuffer = device->read(readBufferSize);
917 device->seek(oldPos);