src/plugins/imageformats/gif/qgifhandler.cpp
branchRCL_3
changeset 4 3b1da2848fc7
parent 3 41300fa6a67c
child 8 3f74d0d4af4c
equal deleted inserted replaced
3:41300fa6a67c 4:3b1da2848fc7
     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,
   133     bool needfirst;
   137     bool needfirst;
   134     int x, y;
   138     int x, y;
   135     int frame;
   139     int frame;
   136     bool out_of_bounds;
   140     bool out_of_bounds;
   137     bool digress;
   141     bool digress;
   138     void nextY(QImage *image);
   142     void nextY(unsigned char *bits, int bpl);
   139     void disposePrevious(QImage *image);
   143     void disposePrevious(QImage *image);
   140 };
   144 };
   141 
   145 
   142 /*!
   146 /*!
   143     Constructs a QGIFFormat.
   147     Constructs a QGIFFormat.
   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;
   527                             x++;
   539                             x++;
   528                             if (x>=swidth) out_of_bounds = true;
   540                             if (x>=swidth) out_of_bounds = true;
   529                             if (x>=left+width) {
   541                             if (x>=left+width) {
   530                                 x=left;
   542                                 x=left;
   531                                 out_of_bounds = left>=swidth || y>=sheight;
   543                                 out_of_bounds = left>=swidth || y>=sheight;
   532                                 nextY(image);
   544                                 nextY(bits, bpl);
   533                                 if (!out_of_bounds && h > y)
   545                                 if (!out_of_bounds && h > y)
   534                                     line = (QRgb*)image->scanLine(y);
   546                                     line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
   535                             }
   547                             }
   536                         }
   548                         }
   537                     }
   549                     }
   538                 }
   550                 }
   539             }
   551             }
   642                 *(line+col+i) = color;
   654                 *(line+col+i) = color;
   643         }
   655         }
   644     }
   656     }
   645 }
   657 }
   646 
   658 
   647 void QGIFFormat::nextY(QImage *image)
   659 void QGIFFormat::nextY(unsigned char *bits, int bpl)
   648 {
   660 {
   649     int my;
   661     int my;
   650     switch (interlace) {
   662     switch (interlace) {
   651     case 0: // Non-interlaced
   663     case 0: // Non-interlaced
   652         // if (!out_of_bounds) {
   664         // if (!out_of_bounds) {
   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);