1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the plugins of the Qt Toolkit. |
7 ** This file is part of the plugins of the Qt Toolkit. |
8 ** |
8 ** |
51 #include <qvariant.h> |
51 #include <qvariant.h> |
52 |
52 |
53 QT_BEGIN_NAMESPACE |
53 QT_BEGIN_NAMESPACE |
54 |
54 |
55 #define Q_TRANSPARENT 0x00ffffff |
55 #define Q_TRANSPARENT 0x00ffffff |
|
56 |
|
57 // avoid going through QImage::scanLine() which calls detach |
|
58 #define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) |
|
59 |
56 |
60 |
57 /* |
61 /* |
58 Incremental image decoder for GIF image format. |
62 Incremental image decoder for GIF image format. |
59 |
63 |
60 This subclass of QImageFormat decodes GIF format images, |
64 This subclass of QImageFormat decodes GIF format images, |
229 { |
233 { |
230 // We are required to state that |
234 // We are required to state that |
231 // "The Graphics Interchange Format(c) is the Copyright property of |
235 // "The Graphics Interchange Format(c) is the Copyright property of |
232 // CompuServe Incorporated. GIF(sm) is a Service Mark property of |
236 // CompuServe Incorporated. GIF(sm) is a Service Mark property of |
233 // CompuServe Incorporated." |
237 // CompuServe Incorporated." |
|
238 |
|
239 image->detach(); |
|
240 int bpl = image->bytesPerLine(); |
|
241 unsigned char *bits = image->bits(); |
234 |
242 |
235 #define LM(l, m) (((m)<<8)|l) |
243 #define LM(l, m) (((m)<<8)|l) |
236 digress = false; |
244 digress = false; |
237 const int initial = length; |
245 const int initial = length; |
238 while (!digress && length) { |
246 while (!digress && length) { |
333 sheight = newtop + newheight; |
341 sheight = newtop + newheight; |
334 |
342 |
335 QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; |
343 QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; |
336 if (image->isNull()) { |
344 if (image->isNull()) { |
337 (*image) = QImage(swidth, sheight, format); |
345 (*image) = QImage(swidth, sheight, format); |
338 memset(image->bits(), 0, image->byteCount()); |
346 bpl = image->bytesPerLine(); |
|
347 bits = image->bits(); |
|
348 memset(bits, 0, image->byteCount()); |
339 |
349 |
340 // ### size of the upcoming frame, should rather |
350 // ### size of the upcoming frame, should rather |
341 // be known before decoding it. |
351 // be known before decoding it. |
342 *nextSize = QSize(swidth, sheight); |
352 *nextSize = QSize(swidth, sheight); |
343 } |
353 } |
391 || backingstore.height() < h) { |
401 || backingstore.height() < h) { |
392 // We just use the backing store as a byte array |
402 // We just use the backing store as a byte array |
393 backingstore = QImage(qMax(backingstore.width(), w), |
403 backingstore = QImage(qMax(backingstore.width(), w), |
394 qMax(backingstore.height(), h), |
404 qMax(backingstore.height(), h), |
395 QImage::Format_RGB32); |
405 QImage::Format_RGB32); |
396 memset(image->bits(), 0, image->byteCount()); |
406 memset(bits, 0, image->byteCount()); |
397 } |
407 } |
|
408 const int dest_bpl = backingstore.bytesPerLine(); |
|
409 unsigned char *dest_data = backingstore.bits(); |
398 for (int ln=0; ln<h; ln++) { |
410 for (int ln=0; ln<h; ln++) { |
399 memcpy(backingstore.scanLine(ln), |
411 memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln), |
400 image->scanLine(t+ln)+l, w*sizeof(QRgb)); |
412 FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb)); |
401 } |
413 } |
402 } |
414 } |
403 |
415 |
404 count=0; |
416 count=0; |
405 if (lcmap) { |
417 if (lcmap) { |
468 // Left the block end arrive |
480 // Left the block end arrive |
469 } else { |
481 } else { |
470 if (needfirst) { |
482 if (needfirst) { |
471 firstcode=oldcode=code; |
483 firstcode=oldcode=code; |
472 if (!out_of_bounds && image->height() > y && firstcode!=trans_index) |
484 if (!out_of_bounds && image->height() > y && firstcode!=trans_index) |
473 ((QRgb*)image->scanLine(y))[x] = color(firstcode); |
485 ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode); |
474 x++; |
486 x++; |
475 if (x>=swidth) out_of_bounds = true; |
487 if (x>=swidth) out_of_bounds = true; |
476 needfirst=false; |
488 needfirst=false; |
477 if (x>=left+width) { |
489 if (x>=left+width) { |
478 x=left; |
490 x=left; |
479 out_of_bounds = left>=swidth || y>=sheight; |
491 out_of_bounds = left>=swidth || y>=sheight; |
480 nextY(image); |
492 nextY(bits, bpl); |
481 } |
493 } |
482 } else { |
494 } else { |
483 incode=code; |
495 incode=code; |
484 if (code>=max_code) { |
496 if (code>=max_code) { |
485 *sp++=firstcode; |
497 *sp++=firstcode; |
513 oldcode=incode; |
525 oldcode=incode; |
514 const int h = image->height(); |
526 const int h = image->height(); |
515 const QRgb *map = lcmap ? localcmap : globalcmap; |
527 const QRgb *map = lcmap ? localcmap : globalcmap; |
516 QRgb *line = 0; |
528 QRgb *line = 0; |
517 if (!out_of_bounds && h > y) |
529 if (!out_of_bounds && h > y) |
518 line = (QRgb*)image->scanLine(y); |
530 line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y); |
519 while (sp>stack) { |
531 while (sp>stack) { |
520 const uchar index = *(--sp); |
532 const uchar index = *(--sp); |
521 if (!out_of_bounds && h > y && index!=trans_index) { |
533 if (!out_of_bounds && h > y && index!=trans_index) { |
522 if (index > ncols) |
534 if (index > ncols) |
523 line[x] = Q_TRANSPARENT; |
535 line[x] = Q_TRANSPARENT; |
658 int i; |
670 int i; |
659 my = qMin(7, bottom-y); |
671 my = qMin(7, bottom-y); |
660 // Don't dup with transparency |
672 // Don't dup with transparency |
661 if (trans_index < 0) { |
673 if (trans_index < 0) { |
662 for (i=1; i<=my; i++) { |
674 for (i=1; i<=my; i++) { |
663 memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), |
675 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), |
664 (right-left+1)*sizeof(QRgb)); |
676 (right-left+1)*sizeof(QRgb)); |
665 } |
677 } |
666 } |
678 } |
667 |
679 |
668 // if (!out_of_bounds) { |
680 // if (!out_of_bounds) { |
687 int i; |
699 int i; |
688 my = qMin(3, bottom-y); |
700 my = qMin(3, bottom-y); |
689 // Don't dup with transparency |
701 // Don't dup with transparency |
690 if (trans_index < 0) { |
702 if (trans_index < 0) { |
691 for (i=1; i<=my; i++) { |
703 for (i=1; i<=my; i++) { |
692 memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), |
704 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), |
693 (right-left+1)*sizeof(QRgb)); |
705 (right-left+1)*sizeof(QRgb)); |
694 } |
706 } |
695 } |
707 } |
696 |
708 |
697 // if (!out_of_bounds) { |
709 // if (!out_of_bounds) { |
711 int i; |
723 int i; |
712 my = qMin(1, bottom-y); |
724 my = qMin(1, bottom-y); |
713 // Don't dup with transparency |
725 // Don't dup with transparency |
714 if (trans_index < 0) { |
726 if (trans_index < 0) { |
715 for (i=1; i<=my; i++) { |
727 for (i=1; i<=my; i++) { |
716 memcpy(image->scanLine(y+i)+left*sizeof(QRgb), image->scanLine(y)+left*sizeof(QRgb), |
728 memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb), |
717 (right-left+1)*sizeof(QRgb)); |
729 (right-left+1)*sizeof(QRgb)); |
718 } |
730 } |
719 } |
731 } |
720 // if (!out_of_bounds) { |
732 // if (!out_of_bounds) { |
721 // ### Changed: QRect(left, y, right - left + 1, my + 1); |
733 // ### Changed: QRect(left, y, right - left + 1, my + 1); |