Qt 4.8
Public Functions | Static Public Functions | Public Variables | Private Types | Private Functions | Properties | List of all members
QGIFFormat Class Reference

Public Functions

int decode (QImage *image, const uchar *buffer, int length, int *nextFrameDelay, int *loopCount)
 This function decodes some data into image changes. More...
 
 QGIFFormat ()
 Constructs a QGIFFormat. More...
 
 ~QGIFFormat ()
 Destroys a QGIFFormat. More...
 

Static Public Functions

static void scan (QIODevice *device, QVector< QSize > *imageSizes, int *loopCount)
 Scans through the data stream defined by device and returns the image sizes found in the stream in the imageSizes vector. More...
 

Public Variables

bool newFrame
 
bool partialNewFrame
 

Private Types

enum  { max_lzw_bits =12 }
 
enum  Disposal { NoDisposal, DoNotChange, RestoreBackground, RestoreImage }
 
enum  State {
  Header, LogicalScreenDescriptor, GlobalColorMap, LocalColorMap,
  Introducer, ImageDescriptor, TableImageLZWSize, ImageDataBlockSize,
  ImageDataBlock, ExtensionLabel, GraphicControlExtension, ApplicationExtension,
  NetscapeExtensionBlockSize, NetscapeExtensionBlock, SkipBlockSize, SkipBlock,
  Done, Error
}
 

Private Functions

QRgb color (uchar index) const
 
void disposePrevious (QImage *image)
 
void fillRect (QImage *image, int x, int y, int w, int h, QRgb col)
 
void nextY (unsigned char *bits, int bpl)
 

Properties

int accum
 
QImage backingstore
 
int bgcol
 
int bitcount
 
int bottom
 
int ccount
 
int clear_code
 
int code_size
 
int count
 
bool digress
 
Disposal disposal
 
bool disposed
 
int end_code
 
int expectcount
 
int firstcode
 
int frame
 
bool gcmap
 
bool gif89
 
QRgbglobalcmap
 
int gncols
 
int height
 
unsigned char hold [16]
 
int incode
 
int interlace
 
bool lcmap
 
int left
 
int lncols
 
QRgblocalcmap
 
int lzwsize
 
int max_code
 
int max_code_size
 
int ncols
 
bool needfirst
 
int oldcode
 
bool out_of_bounds
 
int right
 
int sheight
 
short * sp
 
short * stack
 
enum QGIFFormat::State state
 
int swidth
 
short * table [2]
 
int top
 
int trans_index
 
int width
 
int x
 
int y
 

Detailed Description

Definition at line 68 of file qgifhandler.cpp.

Enumerations

◆ anonymous enum

anonymous enum
private
Enumerator
max_lzw_bits 

Definition at line 131 of file qgifhandler.cpp.

131 { max_lzw_bits=12 }; // (poor-compiler's static const int)

◆ Disposal

enum QGIFFormat::Disposal
private
Enumerator
NoDisposal 
DoNotChange 
RestoreBackground 
RestoreImage 

Definition at line 121 of file qgifhandler.cpp.

◆ State

enum QGIFFormat::State
private
Enumerator
Header 
LogicalScreenDescriptor 
GlobalColorMap 
LocalColorMap 
Introducer 
ImageDescriptor 
TableImageLZWSize 
ImageDataBlockSize 
ImageDataBlock 
ExtensionLabel 
GraphicControlExtension 
ApplicationExtension 
NetscapeExtensionBlockSize 
NetscapeExtensionBlock 
SkipBlockSize 
SkipBlock 
Done 
Error 

Definition at line 93 of file qgifhandler.cpp.

93  {
94  Header,
98  Introducer,
109  SkipBlock,
110  Done,
111  Error
112  } state;
enum QGIFFormat::State state

Constructors and Destructors

◆ QGIFFormat()

QGIFFormat::QGIFFormat ( )

Constructs a QGIFFormat.

Definition at line 150 of file qgifhandler.cpp.

Referenced by QGifHandler::QGifHandler().

151 {
152  globalcmap = 0;
153  localcmap = 0;
154  lncols = 0;
155  gncols = 0;
157  out_of_bounds = false;
158  disposed = true;
159  frame = -1;
160  state = Header;
161  count = 0;
162  lcmap = false;
163  newFrame = false;
164  partialNewFrame = false;
165  table[0] = 0;
166  table[1] = 0;
167  stack = 0;
168 }
QRgb * globalcmap
Definition: qgifhandler.cpp:85
Disposal disposal
QRgb * localcmap
Definition: qgifhandler.cpp:86
bool out_of_bounds
bool partialNewFrame
Definition: qgifhandler.cpp:78
short * table[2]
enum QGIFFormat::State state
short * stack

◆ ~QGIFFormat()

QGIFFormat::~QGIFFormat ( )

Destroys a QGIFFormat.

Definition at line 173 of file qgifhandler.cpp.

174 {
175  if (globalcmap) delete[] globalcmap;
176  if (localcmap) delete[] localcmap;
177  delete [] stack;
178 }
QRgb * globalcmap
Definition: qgifhandler.cpp:85
QRgb * localcmap
Definition: qgifhandler.cpp:86
short * stack

Functions

◆ color()

QRgb QGIFFormat::color ( uchar  index) const
inlineprivate

Definition at line 1028 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and fillRect().

1029 {
1030  if (index > ncols)
1031  return Q_TRANSPARENT;
1032 
1034  QRgb col = map ? map[index] : 0;
1035  return index == trans_index ? col & Q_TRANSPARENT : col;
1036 }
unsigned int QRgb
Definition: qrgb.h:53
QRgb * globalcmap
Definition: qgifhandler.cpp:85
#define Q_TRANSPARENT
Definition: qgifhandler.cpp:55
QRgb * localcmap
Definition: qgifhandler.cpp:86
quint16 index

◆ decode()

int QGIFFormat::decode ( QImage image,
const uchar buffer,
int  length,
int *  nextFrameDelay,
int *  loopCount 
)

This function decodes some data into image changes.

Returns the number of bytes consumed.

Definition at line 236 of file qgifhandler.cpp.

238 {
239  // We are required to state that
240  // "The Graphics Interchange Format(c) is the Copyright property of
241  // CompuServe Incorporated. GIF(sm) is a Service Mark property of
242  // CompuServe Incorporated."
243 
244  if (!stack) {
245  stack = new short[(1 << max_lzw_bits) * 4];
246  table[0] = &stack[(1 << max_lzw_bits) * 2];
247  table[1] = &stack[(1 << max_lzw_bits) * 3];
248  }
249 
250  image->detach();
251  int bpl = image->bytesPerLine();
252  unsigned char *bits = image->bits();
253 
254 #define LM(l, m) (((m)<<8)|l)
255  digress = false;
256  const int initial = length;
257  while (!digress && length) {
258  length--;
259  unsigned char ch=*buffer++;
260  switch (state) {
261  case Header:
262  hold[count++]=ch;
263  if (count==6) {
264  // Header
265  gif89=(hold[3]!='8' || hold[4]!='7');
267  count=0;
268  }
269  break;
271  hold[count++]=ch;
272  if (count==7) {
273  // Logical Screen Descriptor
274  swidth=LM(hold[0], hold[1]);
275  sheight=LM(hold[2], hold[3]);
276  gcmap=!!(hold[4]&0x80);
277  //UNUSED: bpchan=(((hold[4]&0x70)>>3)+1);
278  //UNUSED: gcmsortflag=!!(hold[4]&0x08);
279  gncols=2<<(hold[4]&0x7);
280  bgcol=(gcmap) ? hold[5] : -1;
281  //aspect=hold[6] ? double(hold[6]+15)/64.0 : 1.0;
282 
283  trans_index = -1;
284  count=0;
285  ncols=gncols;
286  if (gcmap) {
287  ccount=0;
289  globalcmap = new QRgb[gncols+1]; // +1 for trans_index
291  } else {
293  }
294  }
295  break;
296  case GlobalColorMap: case LocalColorMap:
297  hold[count++]=ch;
298  if (count==3) {
299  QRgb rgb = qRgb(hold[0], hold[1], hold[2]);
300  if (state == LocalColorMap) {
301  if (ccount < lncols)
302  localcmap[ccount] = rgb;
303  } else {
304  globalcmap[ccount] = rgb;
305  }
306  if (++ccount >= ncols) {
307  if (state == LocalColorMap)
309  else
311  }
312  count=0;
313  }
314  break;
315  case Introducer:
316  hold[count++]=ch;
317  switch (ch) {
318  case ',':
320  break;
321  case '!':
323  break;
324  case ';':
325  // ### Changed: QRect(0, 0, swidth, sheight)
326  state=Done;
327  break;
328  default:
329  digress=true;
330  // Unexpected Introducer - ignore block
331  state=Error;
332  }
333  break;
334  case ImageDescriptor:
335  hold[count++]=ch;
336  if (count==10) {
337  int newleft=LM(hold[1], hold[2]);
338  int newtop=LM(hold[3], hold[4]);
339  int newwidth=LM(hold[5], hold[6]);
340  int newheight=LM(hold[7], hold[8]);
341 
342  // disbelieve ridiculous logical screen sizes,
343  // unless the image frames are also large.
344  if (swidth/10 > qMax(newwidth,200))
345  swidth = -1;
346  if (sheight/10 > qMax(newheight,200))
347  sheight = -1;
348 
349  if (swidth <= 0)
350  swidth = newleft + newwidth;
351  if (sheight <= 0)
352  sheight = newtop + newheight;
353 
355  if (image->isNull()) {
356  (*image) = QImage(swidth, sheight, format);
357  bpl = image->bytesPerLine();
358  bits = image->bits();
359  memset(bits, 0, image->byteCount());
360  }
361 
362  disposePrevious(image);
363  disposed = false;
364 
365  left = newleft;
366  top = newtop;
367  width = newwidth;
368  height = newheight;
369 
370  right=qMax(0, qMin(left+width, swidth)-1);
371  bottom=qMax(0, qMin(top+height, sheight)-1);
372  lcmap=!!(hold[9]&0x80);
373  interlace=!!(hold[9]&0x40);
374  //bool lcmsortflag=!!(hold[9]&0x20);
375  lncols=lcmap ? (2<<(hold[9]&0x7)) : 0;
376  if (lncols) {
377  if (localcmap)
378  delete [] localcmap;
379  localcmap = new QRgb[lncols+1];
381  ncols = lncols;
382  } else {
383  ncols = gncols;
384  }
385  frame++;
386  if (frame == 0) {
387  if (left || top || width<swidth || height<sheight) {
388  // Not full-size image - erase with bg or transparent
389  if (trans_index >= 0) {
390  fillRect(image, 0, 0, swidth, sheight, color(trans_index));
391  // ### Changed: QRect(0, 0, swidth, sheight)
392  } else if (bgcol>=0) {
393  fillRect(image, 0, 0, swidth, sheight, color(bgcol));
394  // ### Changed: QRect(0, 0, swidth, sheight)
395  }
396  }
397  }
398 
399  if (disposal == RestoreImage) {
400  int l = qMin(swidth-1,left);
401  int r = qMin(swidth-1,right);
402  int t = qMin(sheight-1,top);
403  int b = qMin(sheight-1,bottom);
404  int w = r-l+1;
405  int h = b-t+1;
406 
407  if (backingstore.width() < w
408  || backingstore.height() < h) {
409  // We just use the backing store as a byte array
411  qMax(backingstore.height(), h),
413  memset(bits, 0, image->byteCount());
414  }
415  const int dest_bpl = backingstore.bytesPerLine();
416  unsigned char *dest_data = backingstore.bits();
417  for (int ln=0; ln<h; ln++) {
418  memcpy(FAST_SCAN_LINE(dest_data, dest_bpl, ln),
419  FAST_SCAN_LINE(bits, bpl, t+ln) + l, w*sizeof(QRgb));
420  }
421  }
422 
423  count=0;
424  if (lcmap) {
425  ccount=0;
427  } else {
429  }
430  x = left;
431  y = top;
432  accum = 0;
433  bitcount = 0;
434  sp = stack;
435  firstcode = oldcode = 0;
436  needfirst = true;
438  }
439  break;
440  case TableImageLZWSize: {
441  lzwsize=ch;
442  if (lzwsize > max_lzw_bits) {
443  state=Error;
444  } else {
445  code_size=lzwsize+1;
446  clear_code=1<<lzwsize;
450  int i;
451  for (i=0; i<clear_code; i++) {
452  table[0][i]=0;
453  table[1][i]=i;
454  }
456  }
457  count=0;
458  break;
459  } case ImageDataBlockSize:
460  expectcount=ch;
461  if (expectcount) {
463  } else {
465  digress = true;
466  newFrame = true;
467  }
468  break;
469  case ImageDataBlock:
470  count++;
471  accum|=(ch<<bitcount);
472  bitcount+=8;
473  while (bitcount>=code_size && state==ImageDataBlock) {
474  int code=accum&((1<<code_size)-1);
476  accum>>=code_size;
477 
478  if (code==clear_code) {
479  if (!needfirst) {
480  code_size=lzwsize+1;
483  }
484  needfirst=true;
485  } else if (code==end_code) {
486  bitcount = -32768;
487  // Left the block end arrive
488  } else {
489  if (needfirst) {
490  firstcode=oldcode=code;
491  if (!out_of_bounds && image->height() > y && ((frame == 0) || (firstcode != trans_index)))
492  ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode);
493  x++;
494  if (x>=swidth) out_of_bounds = true;
495  needfirst=false;
496  if (x>=left+width) {
497  x=left;
499  nextY(bits, bpl);
500  }
501  } else {
502  incode=code;
503  if (code>=max_code) {
504  *sp++=firstcode;
505  code=oldcode;
506  }
507  while (code>=clear_code+2) {
508  if (code >= max_code) {
509  state = Error;
510  return -1;
511  }
512  *sp++=table[1][code];
513  if (code==table[0][code]) {
514  state=Error;
515  return -1;
516  }
517  if (sp-stack>=(1<<(max_lzw_bits))*2) {
518  state=Error;
519  return -1;
520  }
521  code=table[0][code];
522  }
523  if (code < 0) {
524  state = Error;
525  return -1;
526  }
527 
528  *sp++=firstcode=table[1][code];
529  code=max_code;
530  if (code<(1<<max_lzw_bits)) {
531  table[0][code]=oldcode;
532  table[1][code]=firstcode;
533  max_code++;
534  if ((max_code>=max_code_size)
535  && (max_code_size<(1<<max_lzw_bits)))
536  {
537  max_code_size*=2;
538  code_size++;
539  }
540  }
541  oldcode=incode;
542  const int h = image->height();
543  QRgb *line = 0;
544  if (!out_of_bounds && h > y)
545  line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
546  while (sp>stack) {
547  const uchar index = *(--sp);
548  if (!out_of_bounds && h > y && ((frame == 0) || (index != trans_index))) {
549  line[x] = color(index);
550  }
551  x++;
552  if (x>=swidth) out_of_bounds = true;
553  if (x>=left+width) {
554  x=left;
556  nextY(bits, bpl);
557  if (!out_of_bounds && h > y)
558  line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
559  }
560  }
561  }
562  }
563  }
564  partialNewFrame = true;
565  if (count==expectcount) {
566  count=0;
568  }
569  break;
570  case ExtensionLabel:
571  switch (ch) {
572  case 0xf9:
574  break;
575  case 0xff:
577  break;
578 #if 0
579  case 0xfe:
580  state=CommentExtension;
581  break;
582  case 0x01:
583  break;
584 #endif
585  default:
587  }
588  count=0;
589  break;
591  if (count<11) hold[count]=ch;
592  count++;
593  if (count==hold[0]+1) {
594  if (qstrncmp((char*)(hold+1), "NETSCAPE", 8)==0) {
595  // Looping extension
597  } else {
599  }
600  count=0;
601  }
602  break;
604  expectcount=ch;
605  count=0;
607  else state=Introducer;
608  break;
610  if (count<3) hold[count]=ch;
611  count++;
612  if (count==expectcount) {
613  *loopCount = hold[1]+hold[2]*256;
614  state=SkipBlockSize; // Ignore further blocks
615  }
616  break;
618  if (count<5) hold[count]=ch;
619  count++;
620  if (count==hold[0]+1) {
621  disposePrevious(image);
622  disposal=Disposal((hold[1]>>2)&0x7);
623  //UNUSED: waitforuser=!!((hold[1]>>1)&0x1);
624  int delay=count>3 ? LM(hold[2], hold[3]) : 1;
625  // IE and mozilla use a minimum delay of 10. With the minimum delay of 10
626  // we are compatible to them and avoid huge loads on the app and xserver.
627  *nextFrameDelay = (delay < 2 ? 10 : delay) * 10;
628 
629  bool havetrans=hold[1]&0x1;
630  trans_index = havetrans ? hold[4] : -1;
631 
632  count=0;
634  }
635  break;
636  case SkipBlockSize:
637  expectcount=ch;
638  count=0;
640  else state=Introducer;
641  break;
642  case SkipBlock:
643  count++;
645  break;
646  case Done:
647  digress=true;
648  /* Netscape ignores the junk, so we do too.
649  length++; // Unget
650  state=Error; // More calls to this is an error
651  */
652  break;
653  case Error:
654  return -1; // Called again after done.
655  }
656  }
657  return initial-length;
658 }
Format
The following image formats are available in Qt.
Definition: qimage.h:91
short * sp
unsigned int QRgb
Definition: qrgb.h:53
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
QRgb * globalcmap
Definition: qgifhandler.cpp:85
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
#define Q_TRANSPARENT
Definition: qgifhandler.cpp:55
int byteCount() const
Returns the number of bytes occupied by the image data.
Definition: qimage.cpp:1800
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
void fillRect(QImage *image, int x, int y, int w, int h, QRgb col)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
Disposal disposal
unsigned char uchar
Definition: qglobal.h:994
QRgb color(uchar index) const
void detach()
If multiple images share common data, this image makes a copy of the data and detaches itself from th...
Definition: qimage.cpp:1359
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned char hold[16]
Definition: qgifhandler.cpp:88
QRgb * localcmap
Definition: qgifhandler.cpp:86
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
bool out_of_bounds
#define LM(l, m)
bool partialNewFrame
Definition: qgifhandler.cpp:78
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
Definition: qrgb.h:69
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
QFactoryLoader * l
short * table[2]
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
quint16 index
#define FAST_SCAN_LINE(bits, bpl, y)
Definition: qgifhandler.cpp:58
enum QGIFFormat::State state
void nextY(unsigned char *bits, int bpl)
short * stack
void disposePrevious(QImage *image)
QImage backingstore
Definition: qgifhandler.cpp:87

◆ disposePrevious()

void QGIFFormat::disposePrevious ( QImage image)
private

Definition at line 180 of file qgifhandler.cpp.

Referenced by decode().

181 {
182  if (out_of_bounds) {
183  // flush anything that survived
184  // ### Changed: QRect(0, 0, swidth, sheight)
185  }
186 
187  // Handle disposal of previous image before processing next one
188 
189  if (disposed) return;
190 
191  int l = qMin(swidth-1,left);
192  int r = qMin(swidth-1,right);
193  int t = qMin(sheight-1,top);
194  int b = qMin(sheight-1,bottom);
195 
196  switch (disposal) {
197  case NoDisposal:
198  break;
199  case DoNotChange:
200  break;
201  case RestoreBackground:
202  if (trans_index>=0) {
203  // Easy: we use the transparent color
204  fillRect(image, l, t, r-l+1, b-t+1, Q_TRANSPARENT);
205  } else if (bgcol>=0) {
206  // Easy: we use the bgcol given
207  fillRect(image, l, t, r-l+1, b-t+1, color(bgcol));
208  } else {
209  // Impossible: We don't know of a bgcol - use pixel 0
210  QRgb *bits = (QRgb*)image->bits();
211  fillRect(image, l, t, r-l+1, b-t+1, bits[0]);
212  }
213  // ### Changed: QRect(l, t, r-l+1, b-t+1)
214  break;
215  case RestoreImage: {
216  if (frame >= 0) {
217  for (int ln=t; ln<=b; ln++) {
218  memcpy(image->scanLine(ln)+l,
219  backingstore.scanLine(ln-t),
220  (r-l+1)*sizeof(QRgb));
221  }
222  // ### Changed: QRect(l, t, r-l+1, b-t+1)
223  }
224  }
225  }
226  disposal = NoDisposal; // Until an extension says otherwise.
227 
228  disposed = true;
229 }
unsigned int QRgb
Definition: qrgb.h:53
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define Q_TRANSPARENT
Definition: qgifhandler.cpp:55
void fillRect(QImage *image, int x, int y, int w, int h, QRgb col)
Disposal disposal
QRgb color(uchar index) const
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
bool out_of_bounds
QFactoryLoader * l
QImage backingstore
Definition: qgifhandler.cpp:87
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886

◆ fillRect()

void QGIFFormat::fillRect ( QImage image,
int  x,
int  y,
int  w,
int  h,
QRgb  col 
)
private

Definition at line 927 of file qgifhandler.cpp.

Referenced by decode(), and disposePrevious().

928 {
929  if (w>0) {
930  for (int j=0; j<h; j++) {
931  QRgb *line = (QRgb*)image->scanLine(j+row);
932  for (int i=0; i<w; i++)
933  *(line+col+i) = color;
934  }
935  }
936 }
unsigned int QRgb
Definition: qrgb.h:53
QRgb color(uchar index) const
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886

◆ nextY()

void QGIFFormat::nextY ( unsigned char *  bits,
int  bpl 
)
private

Definition at line 938 of file qgifhandler.cpp.

Referenced by decode().

939 {
940  int my;
941  switch (interlace) {
942  case 0: // Non-interlaced
943  // if (!out_of_bounds) {
944  // ### Changed: QRect(left, y, right - left + 1, 1);
945  // }
946  y++;
947  break;
948  case 1: {
949  int i;
950  my = qMin(7, bottom-y);
951  // Don't dup with transparency
952  if (trans_index < 0) {
953  for (i=1; i<=my; i++) {
954  memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
955  (right-left+1)*sizeof(QRgb));
956  }
957  }
958 
959  // if (!out_of_bounds) {
960  // ### Changed: QRect(left, y, right - left + 1, my + 1);
961  // }
962 // if (!out_of_bounds)
963 // qDebug("consumer->changed(QRect(%d, %d, %d, %d))", left, y, right-left+1, my+1);
964  y+=8;
965  if (y>bottom) {
966  interlace++; y=top+4;
967  if (y > bottom) { // for really broken GIFs with bottom < 5
968  interlace=2;
969  y = top + 2;
970  if (y > bottom) { // for really broken GIF with bottom < 3
971  interlace = 0;
972  y = top + 1;
973  }
974  }
975  }
976  } break;
977  case 2: {
978  int i;
979  my = qMin(3, bottom-y);
980  // Don't dup with transparency
981  if (trans_index < 0) {
982  for (i=1; i<=my; i++) {
983  memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
984  (right-left+1)*sizeof(QRgb));
985  }
986  }
987 
988  // if (!out_of_bounds) {
989  // ### Changed: QRect(left, y, right - left + 1, my + 1);
990  // }
991  y+=8;
992  if (y>bottom) {
993  interlace++; y=top+2;
994  // handle broken GIF with bottom < 3
995  if (y > bottom) {
996  interlace = 3;
997  y = top + 1;
998  }
999  }
1000  } break;
1001  case 3: {
1002  int i;
1003  my = qMin(1, bottom-y);
1004  // Don't dup with transparency
1005  if (trans_index < 0) {
1006  for (i=1; i<=my; i++) {
1007  memcpy(FAST_SCAN_LINE(bits, bpl, y+i)+left*sizeof(QRgb), FAST_SCAN_LINE(bits, bpl, y)+left*sizeof(QRgb),
1008  (right-left+1)*sizeof(QRgb));
1009  }
1010  }
1011  // if (!out_of_bounds) {
1012  // ### Changed: QRect(left, y, right - left + 1, my + 1);
1013  // }
1014  y+=4;
1015  if (y>bottom) { interlace++; y=top+1; }
1016  } break;
1017  case 4:
1018  // if (!out_of_bounds) {
1019  // ### Changed: QRect(left, y, right - left + 1, 1);
1020  // }
1021  y+=2;
1022  }
1023 
1024  // Consume bogus extra lines
1025  if (y >= sheight) out_of_bounds=true; //y=bottom;
1026 }
unsigned int QRgb
Definition: qrgb.h:53
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
bool out_of_bounds
#define FAST_SCAN_LINE(bits, bpl, y)
Definition: qgifhandler.cpp:58

◆ scan()

void QGIFFormat::scan ( QIODevice device,
QVector< QSize > *  imageSizes,
int *  loopCount 
)
static

Scans through the data stream defined by device and returns the image sizes found in the stream in the imageSizes vector.

Definition at line 664 of file qgifhandler.cpp.

Referenced by QGifHandler::imageCount(), QGifHandler::loopCount(), and QGifHandler::option().

665 {
666  if (!device)
667  return;
668 
669  qint64 oldPos = device->pos();
670  if (!device->seek(0))
671  return;
672 
673  int colorCount = 0;
674  int localColorCount = 0;
675  int globalColorCount = 0;
676  int colorReadCount = 0;
677  bool localColormap = false;
678  bool globalColormap = false;
679  int count = 0;
680  int blockSize = 0;
681  int imageWidth = 0;
682  int imageHeight = 0;
683  bool done = false;
684  uchar hold[16];
685  State state = Header;
686 
687  const int readBufferSize = 40960; // 40k read buffer
688  QByteArray readBuffer(device->read(readBufferSize));
689 
690  if (readBuffer.isEmpty()) {
691  device->seek(oldPos);
692  return;
693  }
694 
695  // This is a specialized version of the state machine from decode(),
696  // which doesn't do any image decoding or mallocing, and has an
697  // optimized way of skipping SkipBlocks, ImageDataBlocks and
698  // Global/LocalColorMaps.
699 
700  while (!readBuffer.isEmpty()) {
701  int length = readBuffer.size();
702  const uchar *buffer = (const uchar *) readBuffer.constData();
703  while (!done && length) {
704  length--;
705  uchar ch = *buffer++;
706  switch (state) {
707  case Header:
708  hold[count++] = ch;
709  if (count == 6) {
710  state = LogicalScreenDescriptor;
711  count = 0;
712  }
713  break;
715  hold[count++] = ch;
716  if (count == 7) {
717  imageWidth = LM(hold[0], hold[1]);
718  imageHeight = LM(hold[2], hold[3]);
719  globalColormap = !!(hold[4] & 0x80);
720  globalColorCount = 2 << (hold[4] & 0x7);
721  count = 0;
722  colorCount = globalColorCount;
723  if (globalColormap) {
724  int colorTableSize = 3 * globalColorCount;
725  if (length >= colorTableSize) {
726  // skip the global color table in one go
727  length -= colorTableSize;
728  buffer += colorTableSize;
729  state = Introducer;
730  } else {
731  colorReadCount = 0;
732  state = GlobalColorMap;
733  }
734  } else {
735  state=Introducer;
736  }
737  }
738  break;
739  case GlobalColorMap:
740  case LocalColorMap:
741  hold[count++] = ch;
742  if (count == 3) {
743  if (++colorReadCount >= colorCount) {
744  if (state == LocalColorMap)
745  state = TableImageLZWSize;
746  else
747  state = Introducer;
748  }
749  count = 0;
750  }
751  break;
752  case Introducer:
753  hold[count++] = ch;
754  switch (ch) {
755  case 0x2c:
756  state = ImageDescriptor;
757  break;
758  case 0x21:
759  state = ExtensionLabel;
760  break;
761  case 0x3b:
762  state = Done;
763  break;
764  default:
765  done = true;
766  state = Error;
767  }
768  break;
769  case ImageDescriptor:
770  hold[count++] = ch;
771  if (count == 10) {
772  int newLeft = LM(hold[1], hold[2]);
773  int newTop = LM(hold[3], hold[4]);
774  int newWidth = LM(hold[5], hold[6]);
775  int newHeight = LM(hold[7], hold[8]);
776 
777  if (imageWidth/10 > qMax(newWidth,200))
778  imageWidth = -1;
779  if (imageHeight/10 > qMax(newHeight,200))
780  imageHeight = -1;
781 
782  if (imageWidth <= 0)
783  imageWidth = newLeft + newWidth;
784  if (imageHeight <= 0)
785  imageHeight = newTop + newHeight;
786 
787  *imageSizes << QSize(imageWidth, imageHeight);
788 
789  localColormap = !!(hold[9] & 0x80);
790  localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
791  if (localColorCount)
792  colorCount = localColorCount;
793  else
794  colorCount = globalColorCount;
795 
796  count = 0;
797  if (localColormap) {
798  int colorTableSize = 3 * localColorCount;
799  if (length >= colorTableSize) {
800  // skip the local color table in one go
801  length -= colorTableSize;
802  buffer += colorTableSize;
803  state = TableImageLZWSize;
804  } else {
805  colorReadCount = 0;
806  state = LocalColorMap;
807  }
808  } else {
809  state = TableImageLZWSize;
810  }
811  }
812  break;
813  case TableImageLZWSize:
814  if (ch > max_lzw_bits)
815  state = Error;
816  else
817  state = ImageDataBlockSize;
818  count = 0;
819  break;
820  case ImageDataBlockSize:
821  blockSize = ch;
822  if (blockSize) {
823  if (length >= blockSize) {
824  // we can skip the block in one go
825  length -= blockSize;
826  buffer += blockSize;
827  count = 0;
828  } else {
829  state = ImageDataBlock;
830  }
831  } else {
832  state = Introducer;
833  }
834  break;
835  case ImageDataBlock:
836  ++count;
837  if (count == blockSize) {
838  count = 0;
839  state = ImageDataBlockSize;
840  }
841  break;
842  case ExtensionLabel:
843  switch (ch) {
844  case 0xf9:
845  state = GraphicControlExtension;
846  break;
847  case 0xff:
848  state = ApplicationExtension;
849  break;
850  default:
851  state = SkipBlockSize;
852  }
853  count = 0;
854  break;
856  if (count < 11)
857  hold[count] = ch;
858  ++count;
859  if (count == hold[0] + 1) {
860  if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0)
862  else
863  state=SkipBlockSize;
864  count = 0;
865  }
866  break;
868  if (count < 5)
869  hold[count] = ch;
870  ++count;
871  if (count == hold[0] + 1) {
872  count = 0;
873  state = SkipBlockSize;
874  }
875  break;
877  blockSize = ch;
878  count = 0;
879  if (blockSize)
880  state = NetscapeExtensionBlock;
881  else
882  state = Introducer;
883  break;
885  if (count < 3)
886  hold[count] = ch;
887  count++;
888  if (count == blockSize) {
889  *loopCount = LM(hold[1], hold[2]);
890  state = SkipBlockSize;
891  }
892  break;
893  case SkipBlockSize:
894  blockSize = ch;
895  count = 0;
896  if (blockSize) {
897  if (length >= blockSize) {
898  // we can skip the block in one go
899  length -= blockSize;
900  buffer += blockSize;
901  } else {
902  state = SkipBlock;
903  }
904  } else {
905  state = Introducer;
906  }
907  break;
908  case SkipBlock:
909  ++count;
910  if (count == blockSize)
911  state = SkipBlockSize;
912  break;
913  case Done:
914  done = true;
915  break;
916  case Error:
917  device->seek(oldPos);
918  return;
919  }
920  }
921  readBuffer = device->read(readBufferSize);
922  }
923  device->seek(oldPos);
924  return;
925 }
const int blockSize
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
unsigned char uchar
Definition: qglobal.h:994
__int64 qint64
Definition: qglobal.h:942
The State element defines configurations of objects and properties.
unsigned char hold[16]
Definition: qgifhandler.cpp:88
#define LM(l, m)
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
enum QGIFFormat::State state
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659

Properties

◆ accum

int QGIFFormat::accum
private

Definition at line 128 of file qgifhandler.cpp.

Referenced by decode().

◆ backingstore

QImage QGIFFormat::backingstore
private

Definition at line 87 of file qgifhandler.cpp.

Referenced by decode(), and disposePrevious().

◆ bgcol

int QGIFFormat::bgcol
private

Definition at line 126 of file qgifhandler.cpp.

Referenced by decode(), and disposePrevious().

◆ bitcount

int QGIFFormat::bitcount
private

Definition at line 129 of file qgifhandler.cpp.

Referenced by decode().

◆ bottom

int QGIFFormat::bottom
private

Definition at line 120 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and nextY().

◆ ccount

int QGIFFormat::ccount
private

Definition at line 91 of file qgifhandler.cpp.

Referenced by decode().

◆ clear_code

int QGIFFormat::clear_code
private

Definition at line 133 of file qgifhandler.cpp.

Referenced by decode().

◆ code_size

int QGIFFormat::code_size
private

Definition at line 133 of file qgifhandler.cpp.

Referenced by decode().

◆ count

int QGIFFormat::count
private

Definition at line 90 of file qgifhandler.cpp.

Referenced by decode(), QGIFFormat(), and scan().

◆ digress

bool QGIFFormat::digress
private

Definition at line 142 of file qgifhandler.cpp.

Referenced by decode().

◆ disposal

Disposal QGIFFormat::disposal
private

Definition at line 122 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and QGIFFormat().

◆ disposed

bool QGIFFormat::disposed
private

Definition at line 123 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and QGIFFormat().

◆ end_code

int QGIFFormat::end_code
private

Definition at line 133 of file qgifhandler.cpp.

Referenced by decode().

◆ expectcount

int QGIFFormat::expectcount
private

Definition at line 92 of file qgifhandler.cpp.

Referenced by decode().

◆ firstcode

int QGIFFormat::firstcode
private

Definition at line 134 of file qgifhandler.cpp.

Referenced by decode().

◆ frame

int QGIFFormat::frame
private

Definition at line 140 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and QGIFFormat().

◆ gcmap

bool QGIFFormat::gcmap
private

Definition at line 125 of file qgifhandler.cpp.

Referenced by decode().

◆ gif89

bool QGIFFormat::gif89
private

Definition at line 89 of file qgifhandler.cpp.

Referenced by decode().

◆ globalcmap

QRgb* QGIFFormat::globalcmap
private

Definition at line 85 of file qgifhandler.cpp.

Referenced by color(), decode(), QGIFFormat(), and ~QGIFFormat().

◆ gncols

int QGIFFormat::gncols
private

Definition at line 113 of file qgifhandler.cpp.

Referenced by decode(), and QGIFFormat().

◆ height

int QGIFFormat::height
private

Definition at line 119 of file qgifhandler.cpp.

Referenced by decode().

◆ hold

unsigned char QGIFFormat::hold[16]
private

Definition at line 88 of file qgifhandler.cpp.

Referenced by decode(), and scan().

◆ incode

int QGIFFormat::incode
private

Definition at line 134 of file qgifhandler.cpp.

Referenced by decode().

◆ interlace

int QGIFFormat::interlace
private

Definition at line 127 of file qgifhandler.cpp.

Referenced by decode(), and nextY().

◆ lcmap

bool QGIFFormat::lcmap
private

Definition at line 117 of file qgifhandler.cpp.

Referenced by color(), decode(), and QGIFFormat().

◆ left

int QGIFFormat::left
private

Definition at line 120 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and nextY().

◆ lncols

int QGIFFormat::lncols
private

Definition at line 114 of file qgifhandler.cpp.

Referenced by decode(), and QGIFFormat().

◆ localcmap

QRgb* QGIFFormat::localcmap
private

Definition at line 86 of file qgifhandler.cpp.

Referenced by color(), decode(), QGIFFormat(), and ~QGIFFormat().

◆ lzwsize

int QGIFFormat::lzwsize
private

Definition at line 116 of file qgifhandler.cpp.

Referenced by decode().

◆ max_code

int QGIFFormat::max_code
private

Definition at line 133 of file qgifhandler.cpp.

Referenced by decode().

◆ max_code_size

int QGIFFormat::max_code_size
private

Definition at line 133 of file qgifhandler.cpp.

Referenced by decode().

◆ ncols

int QGIFFormat::ncols
private

Definition at line 115 of file qgifhandler.cpp.

Referenced by color(), and decode().

◆ needfirst

bool QGIFFormat::needfirst
private

Definition at line 138 of file qgifhandler.cpp.

Referenced by decode().

◆ newFrame

bool QGIFFormat::newFrame

Definition at line 77 of file qgifhandler.cpp.

Referenced by decode(), and QGIFFormat().

◆ oldcode

int QGIFFormat::oldcode
private

Definition at line 134 of file qgifhandler.cpp.

Referenced by decode().

◆ out_of_bounds

bool QGIFFormat::out_of_bounds
private

Definition at line 141 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), nextY(), and QGIFFormat().

◆ partialNewFrame

bool QGIFFormat::partialNewFrame

Definition at line 78 of file qgifhandler.cpp.

Referenced by decode(), and QGIFFormat().

◆ right

int QGIFFormat::right
private

Definition at line 120 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and nextY().

◆ sheight

int QGIFFormat::sheight
private

Definition at line 118 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and nextY().

◆ sp

short* QGIFFormat::sp
private

Definition at line 137 of file qgifhandler.cpp.

Referenced by decode().

◆ stack

short* QGIFFormat::stack
private

Definition at line 136 of file qgifhandler.cpp.

Referenced by decode(), QGIFFormat(), and ~QGIFFormat().

◆ state

enum QGIFFormat::State QGIFFormat::state
private

Referenced by decode(), QGIFFormat(), and scan().

◆ swidth

int QGIFFormat::swidth
private

Definition at line 118 of file qgifhandler.cpp.

Referenced by decode(), and disposePrevious().

◆ table

short* QGIFFormat::table[2]
private

Definition at line 135 of file qgifhandler.cpp.

Referenced by decode(), and QGIFFormat().

◆ top

int QGIFFormat::top
private

Definition at line 120 of file qgifhandler.cpp.

Referenced by decode(), disposePrevious(), and nextY().

◆ trans_index

int QGIFFormat::trans_index
private

Definition at line 124 of file qgifhandler.cpp.

Referenced by color(), decode(), disposePrevious(), and nextY().

◆ width

int QGIFFormat::width
private

Definition at line 119 of file qgifhandler.cpp.

Referenced by decode().

◆ x

int QGIFFormat::x
private

Definition at line 139 of file qgifhandler.cpp.

Referenced by decode().

◆ y

int QGIFFormat::y
private

Definition at line 139 of file qgifhandler.cpp.

Referenced by decode(), and nextY().


The documentation for this class was generated from the following file: