PageRenderTime 26ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/qt-everywhere-opensource-src-4.8.2/src/gui/image/qgifhandler.cpp

#
C++ | 1214 lines | 989 code | 85 blank | 140 comment | 232 complexity | 268ef29109996305069e75afced24c62 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-4.0, LGPL-3.0, GPL-2.0, LGPL-2.0, LGPL-2.1, GPL-3.0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the plugins of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** GNU Lesser General Public License Usage
  11. ** This file may be used under the terms of the GNU Lesser General Public
  12. ** License version 2.1 as published by the Free Software Foundation and
  13. ** appearing in the file LICENSE.LGPL included in the packaging of this
  14. ** file. Please review the following information to ensure the GNU Lesser
  15. ** General Public License version 2.1 requirements will be met:
  16. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  17. **
  18. ** In addition, as a special exception, Nokia gives you certain additional
  19. ** rights. These rights are described in the Nokia Qt LGPL Exception
  20. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  21. **
  22. ** GNU General Public License Usage
  23. ** Alternatively, this file may be used under the terms of the GNU General
  24. ** Public License version 3.0 as published by the Free Software Foundation
  25. ** and appearing in the file LICENSE.GPL included in the packaging of this
  26. ** file. Please review the following information to ensure the GNU General
  27. ** Public License version 3.0 requirements will be met:
  28. ** http://www.gnu.org/copyleft/gpl.html.
  29. **
  30. ** Other Usage
  31. ** Alternatively, this file may be used in accordance with the terms and
  32. ** conditions contained in a signed written agreement between you and Nokia.
  33. **
  34. **
  35. **
  36. **
  37. **
  38. ** $QT_END_LICENSE$
  39. **
  40. ** WARNING:
  41. ** A separate license from Unisys may be required to use the gif
  42. ** reader. See http://www.unisys.com/about__unisys/lzw/
  43. ** for information from Unisys
  44. **
  45. ****************************************************************************/
  46. #include "qgifhandler_p.h"
  47. #include <qimage.h>
  48. #include <qiodevice.h>
  49. #include <qvariant.h>
  50. QT_BEGIN_NAMESPACE
  51. #define Q_TRANSPARENT 0x00ffffff
  52. // avoid going through QImage::scanLine() which calls detach
  53. #define FAST_SCAN_LINE(bits, bpl, y) (bits + (y) * bpl)
  54. /*
  55. Incremental image decoder for GIF image format.
  56. This subclass of QImageFormat decodes GIF format images,
  57. including animated GIFs. Internally in
  58. */
  59. class QGIFFormat {
  60. public:
  61. QGIFFormat();
  62. ~QGIFFormat();
  63. int decode(QImage *image, const uchar* buffer, int length,
  64. int *nextFrameDelay, int *loopCount);
  65. static void scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount);
  66. bool newFrame;
  67. bool partialNewFrame;
  68. private:
  69. void fillRect(QImage *image, int x, int y, int w, int h, QRgb col);
  70. inline QRgb color(uchar index) const;
  71. // GIF specific stuff
  72. QRgb* globalcmap;
  73. QRgb* localcmap;
  74. QImage backingstore;
  75. unsigned char hold[16];
  76. bool gif89;
  77. int count;
  78. int ccount;
  79. int expectcount;
  80. enum State {
  81. Header,
  82. LogicalScreenDescriptor,
  83. GlobalColorMap,
  84. LocalColorMap,
  85. Introducer,
  86. ImageDescriptor,
  87. TableImageLZWSize,
  88. ImageDataBlockSize,
  89. ImageDataBlock,
  90. ExtensionLabel,
  91. GraphicControlExtension,
  92. ApplicationExtension,
  93. NetscapeExtensionBlockSize,
  94. NetscapeExtensionBlock,
  95. SkipBlockSize,
  96. SkipBlock,
  97. Done,
  98. Error
  99. } state;
  100. int gncols;
  101. int lncols;
  102. int ncols;
  103. int lzwsize;
  104. bool lcmap;
  105. int swidth, sheight;
  106. int width, height;
  107. int left, top, right, bottom;
  108. enum Disposal { NoDisposal, DoNotChange, RestoreBackground, RestoreImage };
  109. Disposal disposal;
  110. bool disposed;
  111. int trans_index;
  112. bool gcmap;
  113. int bgcol;
  114. int interlace;
  115. int accum;
  116. int bitcount;
  117. enum { max_lzw_bits=12 }; // (poor-compiler's static const int)
  118. int code_size, clear_code, end_code, max_code_size, max_code;
  119. int firstcode, oldcode, incode;
  120. short* table[2];
  121. short* stack;
  122. short *sp;
  123. bool needfirst;
  124. int x, y;
  125. int frame;
  126. bool out_of_bounds;
  127. bool digress;
  128. void nextY(unsigned char *bits, int bpl);
  129. void disposePrevious(QImage *image);
  130. };
  131. /*!
  132. Constructs a QGIFFormat.
  133. */
  134. QGIFFormat::QGIFFormat()
  135. {
  136. globalcmap = 0;
  137. localcmap = 0;
  138. lncols = 0;
  139. gncols = 0;
  140. disposal = NoDisposal;
  141. out_of_bounds = false;
  142. disposed = true;
  143. frame = -1;
  144. state = Header;
  145. count = 0;
  146. lcmap = false;
  147. newFrame = false;
  148. partialNewFrame = false;
  149. table[0] = 0;
  150. table[1] = 0;
  151. stack = 0;
  152. }
  153. /*!
  154. Destroys a QGIFFormat.
  155. */
  156. QGIFFormat::~QGIFFormat()
  157. {
  158. if (globalcmap) delete[] globalcmap;
  159. if (localcmap) delete[] localcmap;
  160. delete [] stack;
  161. }
  162. void QGIFFormat::disposePrevious(QImage *image)
  163. {
  164. if (out_of_bounds) {
  165. // flush anything that survived
  166. // ### Changed: QRect(0, 0, swidth, sheight)
  167. }
  168. // Handle disposal of previous image before processing next one
  169. if (disposed) return;
  170. int l = qMin(swidth-1,left);
  171. int r = qMin(swidth-1,right);
  172. int t = qMin(sheight-1,top);
  173. int b = qMin(sheight-1,bottom);
  174. switch (disposal) {
  175. case NoDisposal:
  176. break;
  177. case DoNotChange:
  178. break;
  179. case RestoreBackground:
  180. if (trans_index>=0) {
  181. // Easy: we use the transparent color
  182. fillRect(image, l, t, r-l+1, b-t+1, Q_TRANSPARENT);
  183. } else if (bgcol>=0) {
  184. // Easy: we use the bgcol given
  185. fillRect(image, l, t, r-l+1, b-t+1, color(bgcol));
  186. } else {
  187. // Impossible: We don't know of a bgcol - use pixel 0
  188. QRgb *bits = (QRgb*)image->bits();
  189. fillRect(image, l, t, r-l+1, b-t+1, bits[0]);
  190. }
  191. // ### Changed: QRect(l, t, r-l+1, b-t+1)
  192. break;
  193. case RestoreImage: {
  194. if (frame >= 0) {
  195. for (int ln=t; ln<=b; ln++) {
  196. memcpy(image->scanLine(ln)+l,
  197. backingstore.scanLine(ln-t),
  198. (r-l+1)*sizeof(QRgb));
  199. }
  200. // ### Changed: QRect(l, t, r-l+1, b-t+1)
  201. }
  202. }
  203. }
  204. disposal = NoDisposal; // Until an extension says otherwise.
  205. disposed = true;
  206. }
  207. /*!
  208. This function decodes some data into image changes.
  209. Returns the number of bytes consumed.
  210. */
  211. int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
  212. int *nextFrameDelay, int *loopCount)
  213. {
  214. // We are required to state that
  215. // "The Graphics Interchange Format(c) is the Copyright property of
  216. // CompuServe Incorporated. GIF(sm) is a Service Mark property of
  217. // CompuServe Incorporated."
  218. if (!stack) {
  219. stack = new short[(1 << max_lzw_bits) * 4];
  220. table[0] = &stack[(1 << max_lzw_bits) * 2];
  221. table[1] = &stack[(1 << max_lzw_bits) * 3];
  222. }
  223. image->detach();
  224. int bpl = image->bytesPerLine();
  225. unsigned char *bits = image->bits();
  226. #define LM(l, m) (((m)<<8)|l)
  227. digress = false;
  228. const int initial = length;
  229. while (!digress && length) {
  230. length--;
  231. unsigned char ch=*buffer++;
  232. switch (state) {
  233. case Header:
  234. hold[count++]=ch;
  235. if (count==6) {
  236. // Header
  237. gif89=(hold[3]!='8' || hold[4]!='7');
  238. state=LogicalScreenDescriptor;
  239. count=0;
  240. }
  241. break;
  242. case LogicalScreenDescriptor:
  243. hold[count++]=ch;
  244. if (count==7) {
  245. // Logical Screen Descriptor
  246. swidth=LM(hold[0], hold[1]);
  247. sheight=LM(hold[2], hold[3]);
  248. gcmap=!!(hold[4]&0x80);
  249. //UNUSED: bpchan=(((hold[4]&0x70)>>3)+1);
  250. //UNUSED: gcmsortflag=!!(hold[4]&0x08);
  251. gncols=2<<(hold[4]&0x7);
  252. bgcol=(gcmap) ? hold[5] : -1;
  253. //aspect=hold[6] ? double(hold[6]+15)/64.0 : 1.0;
  254. trans_index = -1;
  255. count=0;
  256. ncols=gncols;
  257. if (gcmap) {
  258. ccount=0;
  259. state=GlobalColorMap;
  260. globalcmap = new QRgb[gncols+1]; // +1 for trans_index
  261. globalcmap[gncols] = Q_TRANSPARENT;
  262. } else {
  263. state=Introducer;
  264. }
  265. }
  266. break;
  267. case GlobalColorMap: case LocalColorMap:
  268. hold[count++]=ch;
  269. if (count==3) {
  270. QRgb rgb = qRgb(hold[0], hold[1], hold[2]);
  271. if (state == LocalColorMap) {
  272. if (ccount < lncols)
  273. localcmap[ccount] = rgb;
  274. } else {
  275. globalcmap[ccount] = rgb;
  276. }
  277. if (++ccount >= ncols) {
  278. if (state == LocalColorMap)
  279. state=TableImageLZWSize;
  280. else
  281. state=Introducer;
  282. }
  283. count=0;
  284. }
  285. break;
  286. case Introducer:
  287. hold[count++]=ch;
  288. switch (ch) {
  289. case ',':
  290. state=ImageDescriptor;
  291. break;
  292. case '!':
  293. state=ExtensionLabel;
  294. break;
  295. case ';':
  296. // ### Changed: QRect(0, 0, swidth, sheight)
  297. state=Done;
  298. break;
  299. default:
  300. digress=true;
  301. // Unexpected Introducer - ignore block
  302. state=Error;
  303. }
  304. break;
  305. case ImageDescriptor:
  306. hold[count++]=ch;
  307. if (count==10) {
  308. int newleft=LM(hold[1], hold[2]);
  309. int newtop=LM(hold[3], hold[4]);
  310. int newwidth=LM(hold[5], hold[6]);
  311. int newheight=LM(hold[7], hold[8]);
  312. // disbelieve ridiculous logical screen sizes,
  313. // unless the image frames are also large.
  314. if (swidth/10 > qMax(newwidth,200))
  315. swidth = -1;
  316. if (sheight/10 > qMax(newheight,200))
  317. sheight = -1;
  318. if (swidth <= 0)
  319. swidth = newleft + newwidth;
  320. if (sheight <= 0)
  321. sheight = newtop + newheight;
  322. QImage::Format format = trans_index >= 0 ? QImage::Format_ARGB32 : QImage::Format_RGB32;
  323. if (image->isNull()) {
  324. (*image) = QImage(swidth, sheight, format);
  325. bpl = image->bytesPerLine();
  326. bits = image->bits();
  327. memset(bits, 0, image->byteCount());
  328. }
  329. disposePrevious(image);
  330. disposed = false;
  331. left = newleft;
  332. top = newtop;
  333. width = newwidth;
  334. height = newheight;
  335. right=qMax(0, qMin(left+width, swidth)-1);
  336. bottom=qMax(0, qMin(top+height, sheight)-1);
  337. lcmap=!!(hold[9]&0x80);
  338. interlace=!!(hold[9]&0x40);
  339. //bool lcmsortflag=!!(hold[9]&0x20);
  340. lncols=lcmap ? (2<<(hold[9]&0x7)) : 0;
  341. if (lncols) {
  342. if (localcmap)
  343. delete [] localcmap;
  344. localcmap = new QRgb[lncols+1];
  345. localcmap[lncols] = Q_TRANSPARENT;
  346. ncols = lncols;
  347. } else {
  348. ncols = gncols;
  349. }
  350. frame++;
  351. if (frame == 0) {
  352. if (left || top || width<swidth || height<sheight) {
  353. // Not full-size image - erase with bg or transparent
  354. if (trans_index >= 0) {
  355. fillRect(image, 0, 0, swidth, sheight, color(trans_index));
  356. // ### Changed: QRect(0, 0, swidth, sheight)
  357. } else if (bgcol>=0) {
  358. fillRect(image, 0, 0, swidth, sheight, color(bgcol));
  359. // ### Changed: QRect(0, 0, swidth, sheight)
  360. }
  361. }
  362. }
  363. if (disposal == RestoreImage) {
  364. int l = qMin(swidth-1,left);
  365. int r = qMin(swidth-1,right);
  366. int t = qMin(sheight-1,top);
  367. int b = qMin(sheight-1,bottom);
  368. int w = r-l+1;
  369. int h = b-t+1;
  370. if (backingstore.width() < w
  371. || backingstore.height() < h) {
  372. // We just use the backing store as a byte array
  373. backingstore = QImage(qMax(backingstore.width(), w),
  374. qMax(backingstore.height(), h),
  375. QImage::Format_RGB32);
  376. memset(bits, 0, image->byteCount());
  377. }
  378. const int dest_bpl = backingstore.bytesPerLine();
  379. unsigned char *dest_data = backingstore.bits();
  380. for (int ln=0; ln<h; ln++) {
  381. memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln),
  382. FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb));
  383. }
  384. }
  385. count=0;
  386. if (lcmap) {
  387. ccount=0;
  388. state=LocalColorMap;
  389. } else {
  390. state=TableImageLZWSize;
  391. }
  392. x = left;
  393. y = top;
  394. accum = 0;
  395. bitcount = 0;
  396. sp = stack;
  397. firstcode = oldcode = 0;
  398. needfirst = true;
  399. out_of_bounds = left>=swidth || y>=sheight;
  400. }
  401. break;
  402. case TableImageLZWSize: {
  403. lzwsize=ch;
  404. if (lzwsize > max_lzw_bits) {
  405. state=Error;
  406. } else {
  407. code_size=lzwsize+1;
  408. clear_code=1<<lzwsize;
  409. end_code=clear_code+1;
  410. max_code_size=2*clear_code;
  411. max_code=clear_code+2;
  412. int i;
  413. for (i=0; i<clear_code; i++) {
  414. table[0][i]=0;
  415. table[1][i]=i;
  416. }
  417. state=ImageDataBlockSize;
  418. }
  419. count=0;
  420. break;
  421. } case ImageDataBlockSize:
  422. expectcount=ch;
  423. if (expectcount) {
  424. state=ImageDataBlock;
  425. } else {
  426. state=Introducer;
  427. digress = true;
  428. newFrame = true;
  429. }
  430. break;
  431. case ImageDataBlock:
  432. count++;
  433. accum|=(ch<<bitcount);
  434. bitcount+=8;
  435. while (bitcount>=code_size && state==ImageDataBlock) {
  436. int code=accum&((1<<code_size)-1);
  437. bitcount-=code_size;
  438. accum>>=code_size;
  439. if (code==clear_code) {
  440. if (!needfirst) {
  441. code_size=lzwsize+1;
  442. max_code_size=2*clear_code;
  443. max_code=clear_code+2;
  444. }
  445. needfirst=true;
  446. } else if (code==end_code) {
  447. bitcount = -32768;
  448. // Left the block end arrive
  449. } else {
  450. if (needfirst) {
  451. firstcode=oldcode=code;
  452. if (!out_of_bounds && image->height() > y && firstcode!=trans_index)
  453. ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode);
  454. x++;
  455. if (x>=swidth) out_of_bounds = true;
  456. needfirst=false;
  457. if (x>=left+width) {
  458. x=left;
  459. out_of_bounds = left>=swidth || y>=sheight;
  460. nextY(bits, bpl);
  461. }
  462. } else {
  463. incode=code;
  464. if (code>=max_code) {
  465. *sp++=firstcode;
  466. code=oldcode;
  467. }
  468. while (code>=clear_code+2) {
  469. if (code >= max_code) {
  470. state = Error;
  471. return -1;
  472. }
  473. *sp++=table[1][code];
  474. if (code==table[0][code]) {
  475. state=Error;
  476. return -1;
  477. }
  478. if (sp-stack>=(1<<(max_lzw_bits))*2) {
  479. state=Error;
  480. return -1;
  481. }
  482. code=table[0][code];
  483. }
  484. if (code < 0) {
  485. state = Error;
  486. return -1;
  487. }
  488. *sp++=firstcode=table[1][code];
  489. code=max_code;
  490. if (code<(1<<max_lzw_bits)) {
  491. table[0][code]=oldcode;
  492. table[1][code]=firstcode;
  493. max_code++;
  494. if ((max_code>=max_code_size)
  495. && (max_code_size<(1<<max_lzw_bits)))
  496. {
  497. max_code_size*=2;
  498. code_size++;
  499. }
  500. }
  501. oldcode=incode;
  502. const int h = image->height();
  503. const QRgb *map = lcmap ? localcmap : globalcmap;
  504. QRgb *line = 0;
  505. if (!out_of_bounds && h > y)
  506. line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
  507. while (sp>stack) {
  508. const uchar index = *(--sp);
  509. if (!out_of_bounds && h > y && index!=trans_index) {
  510. if (index > ncols)
  511. line[x] = Q_TRANSPARENT;
  512. else
  513. line[x] = map ? map[index] : 0;
  514. }
  515. x++;
  516. if (x>=swidth) out_of_bounds = true;
  517. if (x>=left+width) {
  518. x=left;
  519. out_of_bounds = left>=swidth || y>=sheight;
  520. nextY(bits, bpl);
  521. if (!out_of_bounds && h > y)
  522. line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
  523. }
  524. }
  525. }
  526. }
  527. }
  528. partialNewFrame = true;
  529. if (count==expectcount) {
  530. count=0;
  531. state=ImageDataBlockSize;
  532. }
  533. break;
  534. case ExtensionLabel:
  535. switch (ch) {
  536. case 0xf9:
  537. state=GraphicControlExtension;
  538. break;
  539. case 0xff:
  540. state=ApplicationExtension;
  541. break;
  542. #if 0
  543. case 0xfe:
  544. state=CommentExtension;
  545. break;
  546. case 0x01:
  547. break;
  548. #endif
  549. default:
  550. state=SkipBlockSize;
  551. }
  552. count=0;
  553. break;
  554. case ApplicationExtension:
  555. if (count<11) hold[count]=ch;
  556. count++;
  557. if (count==hold[0]+1) {
  558. if (qstrncmp((char*)(hold+1), "NETSCAPE", 8)==0) {
  559. // Looping extension
  560. state=NetscapeExtensionBlockSize;
  561. } else {
  562. state=SkipBlockSize;
  563. }
  564. count=0;
  565. }
  566. break;
  567. case NetscapeExtensionBlockSize:
  568. expectcount=ch;
  569. count=0;
  570. if (expectcount) state=NetscapeExtensionBlock;
  571. else state=Introducer;
  572. break;
  573. case NetscapeExtensionBlock:
  574. if (count<3) hold[count]=ch;
  575. count++;
  576. if (count==expectcount) {
  577. *loopCount = hold[1]+hold[2]*256;
  578. state=SkipBlockSize; // Ignore further blocks
  579. }
  580. break;
  581. case GraphicControlExtension:
  582. if (count<5) hold[count]=ch;
  583. count++;
  584. if (count==hold[0]+1) {
  585. disposePrevious(image);
  586. disposal=Disposal((hold[1]>>2)&0x7);
  587. //UNUSED: waitforuser=!!((hold[1]>>1)&0x1);
  588. int delay=count>3 ? LM(hold[2], hold[3]) : 1;
  589. // IE and mozilla use a minimum delay of 10. With the minimum delay of 10
  590. // we are compatible to them and avoid huge loads on the app and xserver.
  591. *nextFrameDelay = (delay < 2 ? 10 : delay) * 10;
  592. bool havetrans=hold[1]&0x1;
  593. trans_index = havetrans ? hold[4] : -1;
  594. count=0;
  595. state=SkipBlockSize;
  596. }
  597. break;
  598. case SkipBlockSize:
  599. expectcount=ch;
  600. count=0;
  601. if (expectcount) state=SkipBlock;
  602. else state=Introducer;
  603. break;
  604. case SkipBlock:
  605. count++;
  606. if (count==expectcount) state=SkipBlockSize;
  607. break;
  608. case Done:
  609. digress=true;
  610. /* Netscape ignores the junk, so we do too.
  611. length++; // Unget
  612. state=Error; // More calls to this is an error
  613. */
  614. break;
  615. case Error:
  616. return -1; // Called again after done.
  617. }
  618. }
  619. return initial-length;
  620. }
  621. /*!
  622. Scans through the data stream defined by \a device and returns the image
  623. sizes found in the stream in the \a imageSizes vector.
  624. */
  625. void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount)
  626. {
  627. if (!device)
  628. return;
  629. qint64 oldPos = device->pos();
  630. if (!device->seek(0))
  631. return;
  632. int colorCount = 0;
  633. int localColorCount = 0;
  634. int globalColorCount = 0;
  635. int colorReadCount = 0;
  636. bool localColormap = false;
  637. bool globalColormap = false;
  638. int count = 0;
  639. int blockSize = 0;
  640. int imageWidth = 0;
  641. int imageHeight = 0;
  642. bool done = false;
  643. uchar hold[16];
  644. State state = Header;
  645. const int readBufferSize = 40960; // 40k read buffer
  646. QByteArray readBuffer(device->read(readBufferSize));
  647. if (readBuffer.isEmpty()) {
  648. device->seek(oldPos);
  649. return;
  650. }
  651. // This is a specialized version of the state machine from decode(),
  652. // which doesn't do any image decoding or mallocing, and has an
  653. // optimized way of skipping SkipBlocks, ImageDataBlocks and
  654. // Global/LocalColorMaps.
  655. while (!readBuffer.isEmpty()) {
  656. int length = readBuffer.size();
  657. const uchar *buffer = (const uchar *) readBuffer.constData();
  658. while (!done && length) {
  659. length--;
  660. uchar ch = *buffer++;
  661. switch (state) {
  662. case Header:
  663. hold[count++] = ch;
  664. if (count == 6) {
  665. state = LogicalScreenDescriptor;
  666. count = 0;
  667. }
  668. break;
  669. case LogicalScreenDescriptor:
  670. hold[count++] = ch;
  671. if (count == 7) {
  672. imageWidth = LM(hold[0], hold[1]);
  673. imageHeight = LM(hold[2], hold[3]);
  674. globalColormap = !!(hold[4] & 0x80);
  675. globalColorCount = 2 << (hold[4] & 0x7);
  676. count = 0;
  677. colorCount = globalColorCount;
  678. if (globalColormap) {
  679. int colorTableSize = 3 * globalColorCount;
  680. if (length >= colorTableSize) {
  681. // skip the global color table in one go
  682. length -= colorTableSize;
  683. buffer += colorTableSize;
  684. state = Introducer;
  685. } else {
  686. colorReadCount = 0;
  687. state = GlobalColorMap;
  688. }
  689. } else {
  690. state=Introducer;
  691. }
  692. }
  693. break;
  694. case GlobalColorMap:
  695. case LocalColorMap:
  696. hold[count++] = ch;
  697. if (count == 3) {
  698. if (++colorReadCount >= colorCount) {
  699. if (state == LocalColorMap)
  700. state = TableImageLZWSize;
  701. else
  702. state = Introducer;
  703. }
  704. count = 0;
  705. }
  706. break;
  707. case Introducer:
  708. hold[count++] = ch;
  709. switch (ch) {
  710. case 0x2c:
  711. state = ImageDescriptor;
  712. break;
  713. case 0x21:
  714. state = ExtensionLabel;
  715. break;
  716. case 0x3b:
  717. state = Done;
  718. break;
  719. default:
  720. done = true;
  721. state = Error;
  722. }
  723. break;
  724. case ImageDescriptor:
  725. hold[count++] = ch;
  726. if (count == 10) {
  727. int newLeft = LM(hold[1], hold[2]);
  728. int newTop = LM(hold[3], hold[4]);
  729. int newWidth = LM(hold[5], hold[6]);
  730. int newHeight = LM(hold[7], hold[8]);
  731. if (imageWidth/10 > qMax(newWidth,200))
  732. imageWidth = -1;
  733. if (imageHeight/10 > qMax(newHeight,200))
  734. imageHeight = -1;
  735. if (imageWidth <= 0)
  736. imageWidth = newLeft + newWidth;
  737. if (imageHeight <= 0)
  738. imageHeight = newTop + newHeight;
  739. *imageSizes << QSize(imageWidth, imageHeight);
  740. localColormap = !!(hold[9] & 0x80);
  741. localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
  742. if (localColorCount)
  743. colorCount = localColorCount;
  744. else
  745. colorCount = globalColorCount;
  746. count = 0;
  747. if (localColormap) {
  748. int colorTableSize = 3 * localColorCount;
  749. if (length >= colorTableSize) {
  750. // skip the local color table in one go
  751. length -= colorTableSize;
  752. buffer += colorTableSize;
  753. state = TableImageLZWSize;
  754. } else {
  755. colorReadCount = 0;
  756. state = LocalColorMap;
  757. }
  758. } else {
  759. state = TableImageLZWSize;
  760. }
  761. }
  762. break;
  763. case TableImageLZWSize:
  764. if (ch > max_lzw_bits)
  765. state = Error;
  766. else
  767. state = ImageDataBlockSize;
  768. count = 0;
  769. break;
  770. case ImageDataBlockSize:
  771. blockSize = ch;
  772. if (blockSize) {
  773. if (length >= blockSize) {
  774. // we can skip the block in one go
  775. length -= blockSize;
  776. buffer += blockSize;
  777. count = 0;
  778. } else {
  779. state = ImageDataBlock;
  780. }
  781. } else {
  782. state = Introducer;
  783. }
  784. break;
  785. case ImageDataBlock:
  786. ++count;
  787. if (count == blockSize) {
  788. count = 0;
  789. state = ImageDataBlockSize;
  790. }
  791. break;
  792. case ExtensionLabel:
  793. switch (ch) {
  794. case 0xf9:
  795. state = GraphicControlExtension;
  796. break;
  797. case 0xff:
  798. state = ApplicationExtension;
  799. break;
  800. default:
  801. state = SkipBlockSize;
  802. }
  803. count = 0;
  804. break;
  805. case ApplicationExtension:
  806. if (count < 11)
  807. hold[count] = ch;
  808. ++count;
  809. if (count == hold[0] + 1) {
  810. if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0)
  811. state=NetscapeExtensionBlockSize;
  812. else
  813. state=SkipBlockSize;
  814. count = 0;
  815. }
  816. break;
  817. case GraphicControlExtension:
  818. if (count < 5)
  819. hold[count] = ch;
  820. ++count;
  821. if (count == hold[0] + 1) {
  822. count = 0;
  823. state = SkipBlockSize;
  824. }
  825. break;
  826. case NetscapeExtensionBlockSize:
  827. blockSize = ch;
  828. count = 0;
  829. if (blockSize)
  830. state = NetscapeExtensionBlock;
  831. else
  832. state = Introducer;
  833. break;
  834. case NetscapeExtensionBlock:
  835. if (count < 3)
  836. hold[count] = ch;
  837. count++;
  838. if (count == blockSize) {
  839. *loopCount = LM(hold[1], hold[2]);
  840. state = SkipBlockSize;
  841. }
  842. break;
  843. case SkipBlockSize:
  844. blockSize = ch;
  845. count = 0;
  846. if (blockSize) {
  847. if (length >= blockSize) {
  848. // we can skip the block in one go
  849. length -= blockSize;
  850. buffer += blockSize;
  851. } else {
  852. state = SkipBlock;
  853. }
  854. } else {
  855. state = Introducer;
  856. }
  857. break;
  858. case SkipBlock:
  859. ++count;
  860. if (count == blockSize)
  861. state = SkipBlockSize;
  862. break;
  863. case Done:
  864. done = true;
  865. break;
  866. case Error:
  867. device->seek(oldPos);
  868. return;
  869. }
  870. }
  871. readBuffer = device->read(readBufferSize);
  872. }
  873. device->seek(oldPos);
  874. return;
  875. }
  876. void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb color)
  877. {
  878. if (w>0) {
  879. for (int j=0; j<h; j++) {
  880. QRgb *line = (QRgb*)image->scanLine(j+row);
  881. for (int i=0; i<w; i++)
  882. *(line+col+i) = color;
  883. }
  884. }
  885. }
  886. void QGIFFormat::nextY(unsigned char *bits, int bpl)
  887. {
  888. int my;
  889. switch (interlace) {
  890. case 0: // Non-interlaced
  891. // if (!out_of_bounds) {
  892. // ### Changed: QRect(left, y, right - left + 1, 1);
  893. // }
  894. y++;
  895. break;
  896. case 1: {
  897. int i;
  898. my = qMin(7, bottom-y);
  899. // Don't dup with transparency
  900. if (trans_index < 0) {
  901. for (i=1; i<=my; i++) {
  902. memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
  903. (right-left+1)*sizeof(QRgb));
  904. }
  905. }
  906. // if (!out_of_bounds) {
  907. // ### Changed: QRect(left, y, right - left + 1, my + 1);
  908. // }
  909. // if (!out_of_bounds)
  910. // qDebug("consumer->changed(QRect(%d, %d, %d, %d))", left, y, right-left+1, my+1);
  911. y+=8;
  912. if (y>bottom) {
  913. interlace++; y=top+4;
  914. if (y > bottom) { // for really broken GIFs with bottom < 5
  915. interlace=2;
  916. y = top + 2;
  917. if (y > bottom) { // for really broken GIF with bottom < 3
  918. interlace = 0;
  919. y = top + 1;
  920. }
  921. }
  922. }
  923. } break;
  924. case 2: {
  925. int i;
  926. my = qMin(3, bottom-y);
  927. // Don't dup with transparency
  928. if (trans_index < 0) {
  929. for (i=1; i<=my; i++) {
  930. memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
  931. (right-left+1)*sizeof(QRgb));
  932. }
  933. }
  934. // if (!out_of_bounds) {
  935. // ### Changed: QRect(left, y, right - left + 1, my + 1);
  936. // }
  937. y+=8;
  938. if (y>bottom) {
  939. interlace++; y=top+2;
  940. // handle broken GIF with bottom < 3
  941. if (y > bottom) {
  942. interlace = 3;
  943. y = top + 1;
  944. }
  945. }
  946. } break;
  947. case 3: {
  948. int i;
  949. my = qMin(1, bottom-y);
  950. // Don't dup with transparency
  951. if (trans_index < 0) {
  952. for (i=1; i<=my; i++) {
  953. memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
  954. (right-left+1)*sizeof(QRgb));
  955. }
  956. }
  957. // if (!out_of_bounds) {
  958. // ### Changed: QRect(left, y, right - left + 1, my + 1);
  959. // }
  960. y+=4;
  961. if (y>bottom) { interlace++; y=top+1; }
  962. } break;
  963. case 4:
  964. // if (!out_of_bounds) {
  965. // ### Changed: QRect(left, y, right - left + 1, 1);
  966. // }
  967. y+=2;
  968. }
  969. // Consume bogus extra lines
  970. if (y >= sheight) out_of_bounds=true; //y=bottom;
  971. }
  972. inline QRgb QGIFFormat::color(uchar index) const
  973. {
  974. if (index == trans_index || index > ncols)
  975. return Q_TRANSPARENT;
  976. QRgb *map = lcmap ? localcmap : globalcmap;
  977. return map ? map[index] : 0;
  978. }
  979. //-------------------------------------------------------------------------
  980. //-------------------------------------------------------------------------
  981. //-------------------------------------------------------------------------
  982. QGifHandler::QGifHandler()
  983. {
  984. gifFormat = new QGIFFormat;
  985. nextDelay = 100;
  986. loopCnt = -1;
  987. frameNumber = -1;
  988. scanIsCached = false;
  989. }
  990. QGifHandler::~QGifHandler()
  991. {
  992. delete gifFormat;
  993. }
  994. // Does partial decode if necessary, just to see if an image is coming
  995. bool QGifHandler::imageIsComing() const
  996. {
  997. const int GifChunkSize = 4096;
  998. while (!gifFormat->partialNewFrame) {
  999. if (buffer.isEmpty()) {
  1000. buffer += device()->read(GifChunkSize);
  1001. if (buffer.isEmpty())
  1002. break;
  1003. }
  1004. int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
  1005. &nextDelay, &loopCnt);
  1006. if (decoded == -1)
  1007. break;
  1008. buffer.remove(0, decoded);
  1009. }
  1010. return gifFormat->partialNewFrame;
  1011. }
  1012. bool QGifHandler::canRead() const
  1013. {
  1014. if (canRead(device()) || imageIsComing()) {
  1015. setFormat("gif");
  1016. return true;
  1017. }
  1018. return false;
  1019. }
  1020. bool QGifHandler::canRead(QIODevice *device)
  1021. {
  1022. if (!device) {
  1023. qWarning("QGifHandler::canRead() called with no device");
  1024. return false;
  1025. }
  1026. char head[6];
  1027. if (device->peek(head, sizeof(head)) == sizeof(head))
  1028. return qstrncmp(head, "GIF87a", 6) == 0
  1029. || qstrncmp(head, "GIF89a", 6) == 0;
  1030. return false;
  1031. }
  1032. bool QGifHandler::read(QImage *image)
  1033. {
  1034. const int GifChunkSize = 4096;
  1035. while (!gifFormat->newFrame) {
  1036. if (buffer.isEmpty()) {
  1037. buffer += device()->read(GifChunkSize);
  1038. if (buffer.isEmpty())
  1039. break;
  1040. }
  1041. int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
  1042. &nextDelay, &loopCnt);
  1043. if (decoded == -1)
  1044. break;
  1045. buffer.remove(0, decoded);
  1046. }
  1047. if (gifFormat->newFrame || (gifFormat->partialNewFrame && device()->atEnd())) {
  1048. *image = lastImage;
  1049. ++frameNumber;
  1050. gifFormat->newFrame = false;
  1051. gifFormat->partialNewFrame = false;
  1052. return true;
  1053. }
  1054. return false;
  1055. }
  1056. bool QGifHandler::write(const QImage &image)
  1057. {
  1058. Q_UNUSED(image);
  1059. return false;
  1060. }
  1061. bool QGifHandler::supportsOption(ImageOption option) const
  1062. {
  1063. if (!device() || device()->isSequential())
  1064. return option == Animation;
  1065. else
  1066. return option == Size
  1067. || option == Animation;
  1068. }
  1069. QVariant QGifHandler::option(ImageOption option) const
  1070. {
  1071. if (option == Size) {
  1072. if (!scanIsCached) {
  1073. QGIFFormat::scan(device(), &imageSizes, &loopCnt);
  1074. scanIsCached = true;
  1075. }
  1076. // before the first frame is read, or we have an empty data stream
  1077. if (frameNumber == -1)
  1078. return (imageSizes.count() > 0) ? QVariant(imageSizes.at(0)) : QVariant();
  1079. // after the last frame has been read, the next size is undefined
  1080. if (frameNumber >= imageSizes.count() - 1)
  1081. return QVariant();
  1082. // and the last case: the size of the next frame
  1083. return imageSizes.at(frameNumber + 1);
  1084. } else if (option == Animation) {
  1085. return true;
  1086. }
  1087. return QVariant();
  1088. }
  1089. void QGifHandler::setOption(ImageOption option, const QVariant &value)
  1090. {
  1091. Q_UNUSED(option);
  1092. Q_UNUSED(value);
  1093. }
  1094. int QGifHandler::nextImageDelay() const
  1095. {
  1096. return nextDelay;
  1097. }
  1098. int QGifHandler::imageCount() const
  1099. {
  1100. if (!scanIsCached) {
  1101. QGIFFormat::scan(device(), &imageSizes, &loopCnt);
  1102. scanIsCached = true;
  1103. }
  1104. return imageSizes.count();
  1105. }
  1106. int QGifHandler::loopCount() const
  1107. {
  1108. if (!scanIsCached) {
  1109. QGIFFormat::scan(device(), &imageSizes, &loopCnt);
  1110. scanIsCached = true;
  1111. }
  1112. if (loopCnt == 0)
  1113. return -1;
  1114. else if (loopCnt == -1)
  1115. return 0;
  1116. else
  1117. return loopCnt;
  1118. }
  1119. int QGifHandler::currentImageNumber() const
  1120. {
  1121. return frameNumber;
  1122. }
  1123. QByteArray QGifHandler::name() const
  1124. {
  1125. return "gif";
  1126. }
  1127. QT_END_NAMESPACE