Commit df845cfdc305eefe37f621d37ad894c13752ed47
- Diff rendering mode:
- inline
- side by side
src/plugins/imageformats/gif/qgifhandler.cpp
(51 / 34)
|   | |||
| 56 | 56 | ||
| 57 | 57 | // avoid going through QImage::scanLine() which calls detach | |
| 58 | 58 | #define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl) | |
| 59 | #define GIF_CHUNK_SIZE 4096 | ||
| 59 | 60 | ||
| 60 | |||
| 61 | 61 | /* | |
| 62 | 62 | Incremental image decoder for GIF image format. | |
| 63 | 63 | ||
| … | … | ||
| 67 | 67 | ||
| 68 | 68 | class QGIFFormat { | |
| 69 | 69 | public: | |
| 70 | enum QueryMode { | ||
| 71 | QuerySize, | ||
| 72 | QueryAll, | ||
| 73 | }; | ||
| 74 | |||
| 70 | 75 | QGIFFormat(); | |
| 71 | 76 | ~QGIFFormat(); | |
| 72 | 77 | ||
| 73 | 78 | int decode(QImage *image, const uchar* buffer, int length, | |
| 74 | int *nextFrameDelay, int *loopCount, QSize *nextSize); | ||
| 79 | int *nextFrameDelay, int *loopCount, QSize *nextSize, int mode = QueryAll); | ||
| 75 | 80 | ||
| 76 | 81 | bool newFrame; | |
| 77 | 82 | bool partialNewFrame; | |
| … | … | ||
| 234 | 234 | Returns the number of bytes consumed. | |
| 235 | 235 | */ | |
| 236 | 236 | int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, | |
| 237 | int *nextFrameDelay, int *loopCount, QSize *nextSize) | ||
| 237 | int *nextFrameDelay, int *loopCount, QSize *nextSize, int mode) | ||
| 238 | 238 | { | |
| 239 | 239 | // We are required to state that | |
| 240 | 240 | // "The Graphics Interchange Format(c) is the Copyright property of | |
| … | … | ||
| 346 | 346 | sheight = newtop + newheight; | |
| 347 | 347 | ||
| 348 | 348 | QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32; | |
| 349 | if (image->isNull()) { | ||
| 349 | if (image->isNull() || (mode == QuerySize && nextSize->isEmpty())) { | ||
| 350 | // ### size of the upcoming frame, should rather | ||
| 351 | // be known before decoding it. | ||
| 352 | *nextSize = QSize(swidth, sheight); | ||
| 353 | |||
| 354 | // Only the size of the image should be decoded. Make sure that on | ||
| 355 | // the next entry to the ::decode method we come here again. Do | ||
| 356 | // this by reducing the count and claiming that the ImageDescriptor | ||
| 357 | // has not been processed. | ||
| 358 | if (mode == QuerySize) { | ||
| 359 | --count; | ||
| 360 | return initial-length - 1; | ||
| 361 | } | ||
| 362 | |||
| 350 | 363 | (*image) = QImage(swidth, sheight, format); | |
| 351 | 364 | bpl = image->bytesPerLine(); | |
| 352 | 365 | bits = image->bits(); | |
| 353 | 366 | memset(bits, 0, image->byteCount()); | |
| 354 | |||
| 355 | // ### size of the upcoming frame, should rather | ||
| 356 | // be known before decoding it. | ||
| 357 | *nextSize = QSize(swidth, sheight); | ||
| 358 | 367 | } | |
| 359 | 368 | ||
| 360 | 369 | disposePrevious(image); | |
| … | … | ||
| 791 | 791 | ||
| 792 | 792 | bool QGifHandler::imageIsComing() const | |
| 793 | 793 | { | |
| 794 | const int GifChunkSize = 4096; | ||
| 795 | |||
| 796 | 794 | while (!gifFormat->partialNewFrame) { | |
| 797 | if (buffer.isEmpty()) { | ||
| 798 | buffer += device()->read(GifChunkSize); | ||
| 799 | if (buffer.isEmpty()) | ||
| 800 | break; | ||
| 801 | } | ||
| 802 | |||
| 803 | int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(), | ||
| 804 | &nextDelay, &loopCnt, &nextSize); | ||
| 805 | if (decoded == -1) | ||
| 795 | if (!decode(QGIFFormat::QueryAll)) | ||
| 806 | 796 | break; | |
| 807 | buffer.remove(0, decoded); | ||
| 808 | 797 | } | |
| 809 | 798 | return gifFormat->partialNewFrame; | |
| 810 | 799 | } | |
| … | … | ||
| 824 | 824 | ||
| 825 | 825 | bool QGifHandler::read(QImage *image) | |
| 826 | 826 | { | |
| 827 | const int GifChunkSize = 4096; | ||
| 828 | |||
| 829 | 827 | while (!gifFormat->newFrame) { | |
| 830 | if (buffer.isEmpty()) { | ||
| 831 | buffer += device()->read(GifChunkSize); | ||
| 832 | if (buffer.isEmpty()) | ||
| 833 | break; | ||
| 834 | } | ||
| 835 | |||
| 836 | int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(), | ||
| 837 | &nextDelay, &loopCnt, &nextSize); | ||
| 838 | if (decoded == -1) | ||
| 828 | if (!decode(QGIFFormat::QueryAll)) | ||
| 839 | 829 | break; | |
| 840 | buffer.remove(0, decoded); | ||
| 841 | 830 | } | |
| 842 | 831 | if (gifFormat->newFrame || (gifFormat->partialNewFrame && device()->atEnd())) { | |
| 843 | 832 | *image = lastImage; | |
| … | … | ||
| 854 | 854 | QVariant QGifHandler::option(ImageOption option) const | |
| 855 | 855 | { | |
| 856 | 856 | if (option == Size) { | |
| 857 | if (imageIsComing()) | ||
| 858 | return nextSize; | ||
| 857 | // Reset the size when we are not within a frame. | ||
| 858 | if (!gifFormat->partialNewFrame) | ||
| 859 | nextSize = QSize(); | ||
| 860 | while (nextSize.isEmpty()) { | ||
| 861 | if (!decode(QGIFFormat::QuerySize)) { | ||
| 862 | break; | ||
| 863 | } | ||
| 864 | } | ||
| 865 | |||
| 866 | return nextSize; | ||
| 859 | 867 | } else if (option == Animation) { | |
| 860 | 868 | return true; | |
| 861 | 869 | } | |
| … | … | ||
| 899 | 899 | QByteArray QGifHandler::name() const | |
| 900 | 900 | { | |
| 901 | 901 | return "gif"; | |
| 902 | } | ||
| 903 | |||
| 904 | bool QGifHandler::decode(int mode) const | ||
| 905 | { | ||
| 906 | if (buffer.isEmpty()) { | ||
| 907 | buffer += device()->read(GIF_CHUNK_SIZE); | ||
| 908 | if (buffer.isEmpty()) | ||
| 909 | return false; | ||
| 910 | } | ||
| 911 | |||
| 912 | int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(), | ||
| 913 | &nextDelay, &loopCnt, &nextSize, mode); | ||
| 914 | if (decoded == -1) | ||
| 915 | return false; | ||
| 916 | |||
| 917 | buffer.remove(0, decoded); | ||
| 918 | return true; | ||
| 902 | 919 | } | |
| 903 | 920 | ||
| 904 | 921 | QT_END_NAMESPACE |
src/plugins/imageformats/gif/qgifhandler.h
(1 / 0)
|   | |||
| 78 | 78 | int currentImageNumber() const; | |
| 79 | 79 | ||
| 80 | 80 | private: | |
| 81 | bool decode(int mode) const; | ||
| 81 | 82 | bool imageIsComing() const; | |
| 82 | 83 | QGIFFormat *gifFormat; | |
| 83 | 84 | QString fileName; |
Comments
Add a new comment:
Login or create an account to post a comment
Add your comment
Please log in to comment

