15#define Q_TRANSPARENT 0x00ffffff
18#define FAST_SCAN_LINE(bits, bpl, y) (bits + qptrdiff(y) * bpl)
33 int *nextFrameDelay,
int *loopCount);
51 unsigned char hold[16];
58 LogicalScreenDescriptor,
67 GraphicControlExtension,
69 NetscapeExtensionBlockSize,
70 NetscapeExtensionBlock,
84 enum Disposal { NoDisposal, DoNotChange, RestoreBackground, RestoreImage };
94 enum { max_lzw_bits=12 };
96 int code_size, clear_code, end_code, max_code_size, max_code;
97 int firstcode, oldcode, incode;
106 void nextY(
unsigned char *
bits,
int bpl);
115 globalcmap =
nullptr;
119 disposal = NoDisposal;
120 out_of_bounds =
false;
138 if (globalcmap)
delete[] globalcmap;
139 if (localcmap)
delete[] localcmap;
152 if (disposed)
return;
164 case RestoreBackground:
165 if (trans_index>=0) {
168 }
else if (bgcol>=0) {
180 for (
int ln=
t; ln<=
b; ln++) {
181 memcpy(
image->scanLine(ln)+l*
sizeof(
QRgb),
183 (
r-l+1)*
sizeof(
QRgb));
189 disposal = NoDisposal;
200 int *nextFrameDelay,
int *loopCount)
208 stack =
new short[(1 << max_lzw_bits) * 4];
209 table[0] = &stack[(1 << max_lzw_bits) * 2];
210 table[1] = &stack[(1 << max_lzw_bits) * 3];
217#define LM(l, m) (((m)<<8)|l)
219 const int initial =
length;
220 while (!digress &&
length) {
228 gif89=(hold[3]!=
'8' || hold[4]!=
'7');
229 state=LogicalScreenDescriptor;
233 case LogicalScreenDescriptor:
237 swidth=
LM(hold[0], hold[1]);
238 sheight=
LM(hold[2], hold[3]);
239 gcmap=!!(hold[4]&0x80);
242 gncols=2<<(hold[4]&0x7);
243 bgcol=(gcmap) ? hold[5] : -1;
251 state=GlobalColorMap;
252 globalcmap =
new QRgb[gncols+1];
259 case GlobalColorMap:
case LocalColorMap:
263 if (state == LocalColorMap) {
265 localcmap[ccount] =
rgb;
267 globalcmap[ccount] =
rgb;
269 if (++ccount >= ncols) {
270 if (state == LocalColorMap)
271 state=TableImageLZWSize;
282 state=ImageDescriptor;
285 state=ExtensionLabel;
297 case ImageDescriptor:
300 int newleft=
LM(hold[1], hold[2]);
301 int newtop=
LM(hold[3], hold[4]);
302 int newwidth=
LM(hold[5], hold[6]);
303 int newheight=
LM(hold[7], hold[8]);
307 if (swidth/10 >
qMax(newwidth,16384))
309 if (sheight/10 >
qMax(newheight,16384))
313 swidth = newleft + newwidth;
315 sheight = newtop + newheight;
318 if (
image->isNull()) {
319 if (!withinSizeLimit(swidth, sheight)) {
327 bpl =
image->bytesPerLine();
335 if (
image->isNull()) {
340 disposePrevious(
image);
350 lcmap=!!(hold[9]&0x80);
351 interlace=!!(hold[9]&0x40);
353 lncols=lcmap ? (2<<(hold[9]&0x7)) : 0;
357 localcmap =
new QRgb[lncols+1];
367 if (trans_index >= 0) {
368 fillRect(
image, 0, 0, swidth, sheight,
color(trans_index));
370 }
else if (bgcol>=0) {
371 fillRect(
image, 0, 0, swidth, sheight,
color(bgcol));
377 if (disposal == RestoreImage) {
385 if (backingstore.
width() <
w
386 || backingstore.
height() <
h) {
388 if (!withinSizeLimit(
w,
h)) {
402 unsigned char *dest_data = backingstore.
bits();
403 for (
int ln=0; ln<
h; ln++) {
414 state=TableImageLZWSize;
421 firstcode = oldcode = 0;
423 out_of_bounds =
left>=swidth ||
y>=sheight;
426 case TableImageLZWSize: {
428 if (lzwsize > max_lzw_bits) {
432 clear_code=1<<lzwsize;
433 end_code=clear_code+1;
434 max_code_size=2*clear_code;
435 max_code=clear_code+2;
437 for (
i=0;
i<clear_code;
i++) {
441 state=ImageDataBlockSize;
445 }
case ImageDataBlockSize:
448 state=ImageDataBlock;
457 if (bitcount != -32768) {
458 if (bitcount < 0 || bitcount > 31) {
462 accum |= (
ch << bitcount);
465 while (bitcount>=code_size && state==ImageDataBlock) {
466 int code=accum&((1<<code_size)-1);
470 if (code==clear_code) {
473 max_code_size=2*clear_code;
474 max_code=clear_code+2;
477 }
else if (code==end_code) {
482 firstcode=oldcode=code;
483 if (!out_of_bounds &&
image->height() >
y && ((frame == 0) || (firstcode != trans_index)))
486 if (
x>=swidth) out_of_bounds =
true;
490 out_of_bounds =
left>=swidth ||
y>=sheight;
495 if (code>=max_code) {
499 while (code>=clear_code+2) {
500 if (code >= max_code) {
504 *sp++=
table[1][code];
505 if (code==
table[0][code]) {
509 if (sp-stack>=(1<<(max_lzw_bits))*2) {
520 *sp++=firstcode=
table[1][code];
522 if (code<(1<<max_lzw_bits)) {
523 table[0][code]=oldcode;
524 table[1][code]=firstcode;
526 if ((max_code>=max_code_size)
527 && (max_code_size<(1<<max_lzw_bits)))
534 const int h =
image->height();
536 if (!out_of_bounds &&
h >
y)
540 if (!out_of_bounds &&
h >
y && ((frame == 0) || (
index != trans_index))) {
544 if (
x>=swidth) out_of_bounds =
true;
547 out_of_bounds =
left>=swidth ||
y>=sheight;
549 if (!out_of_bounds &&
h >
y)
557 if (
count==expectcount) {
559 state=ImageDataBlockSize;
565 state=GraphicControlExtension;
568 state=ApplicationExtension;
572 state=CommentExtension;
582 case ApplicationExtension:
585 if (
count==hold[0]+1) {
586 if (
qstrncmp((
char*)(hold+1),
"NETSCAPE", 8)==0) {
588 state=NetscapeExtensionBlockSize;
595 case NetscapeExtensionBlockSize:
598 if (expectcount) state=NetscapeExtensionBlock;
599 else state=Introducer;
601 case NetscapeExtensionBlock:
604 if (
count==expectcount) {
605 *loopCount = hold[1]+hold[2]*256;
609 case GraphicControlExtension:
612 if (
count==hold[0]+1) {
613 disposePrevious(
image);
614 uint dBits = (hold[1] >> 2) & 0x7;
615 disposal = (dBits <= RestoreImage) ? Disposal(dBits) : NoDisposal;
617 int delay=
count>3 ?
LM(hold[2], hold[3]) : 1;
620 *nextFrameDelay = (delay < 2 ? 10 : delay) * 10;
622 bool havetrans=hold[1]&0x1;
623 trans_index = havetrans ? hold[4] : -1;
632 if (expectcount) state=SkipBlock;
633 else state=Introducer;
637 if (
count==expectcount) state=SkipBlockSize;
667 int localColorCount = 0;
668 int globalColorCount = 0;
669 int colorReadCount = 0;
670 bool localColormap =
false;
671 bool globalColormap =
false;
678 State state = Header;
680 const int readBufferSize = 40960;
703 state = LogicalScreenDescriptor;
707 case LogicalScreenDescriptor:
710 imageWidth =
LM(hold[0], hold[1]);
711 imageHeight =
LM(hold[2], hold[3]);
712 globalColormap = !!(hold[4] & 0x80);
713 globalColorCount = 2 << (hold[4] & 0x7);
715 colorCount = globalColorCount;
716 if (globalColormap) {
717 int colorTableSize = 3 * globalColorCount;
718 if (
length >= colorTableSize) {
725 state = GlobalColorMap;
736 if (++colorReadCount >= colorCount) {
737 if (
state == LocalColorMap)
738 state = TableImageLZWSize;
749 state = ImageDescriptor;
752 state = ExtensionLabel;
762 case ImageDescriptor:
765 int newLeft =
LM(hold[1], hold[2]);
766 int newTop =
LM(hold[3], hold[4]);
767 int newWidth =
LM(hold[5], hold[6]);
768 int newHeight =
LM(hold[7], hold[8]);
770 if (imageWidth/10 >
qMax(newWidth,200))
772 if (imageHeight/10 >
qMax(newHeight,200))
776 imageWidth = newLeft + newWidth;
777 if (imageHeight <= 0)
778 imageHeight = newTop + newHeight;
780 *imageSizes <<
QSize(imageWidth, imageHeight);
782 localColormap = !!(hold[9] & 0x80);
783 localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
785 colorCount = localColorCount;
787 colorCount = globalColorCount;
791 int colorTableSize = 3 * localColorCount;
792 if (
length >= colorTableSize) {
796 state = TableImageLZWSize;
799 state = LocalColorMap;
802 state = TableImageLZWSize;
806 case TableImageLZWSize:
807 if (
ch > max_lzw_bits)
810 state = ImageDataBlockSize;
813 case ImageDataBlockSize:
822 state = ImageDataBlock;
832 state = ImageDataBlockSize;
838 state = GraphicControlExtension;
841 state = ApplicationExtension;
844 state = SkipBlockSize;
848 case ApplicationExtension:
852 if (
count == hold[0] + 1) {
853 if (
qstrncmp((
char*)(hold+1),
"NETSCAPE", 8) == 0)
854 state=NetscapeExtensionBlockSize;
860 case GraphicControlExtension:
864 if (
count == hold[0] + 1) {
866 state = SkipBlockSize;
869 case NetscapeExtensionBlockSize:
873 state = NetscapeExtensionBlock;
877 case NetscapeExtensionBlock:
882 *loopCount =
LM(hold[1], hold[2]);
883 state = SkipBlockSize;
904 state = SkipBlockSize;
923 for (
int j=0;
j<
h;
j++) {
925 for (
int i=0;
i<
w;
i++)
931void QGIFFormat::nextY(
unsigned char *
bits,
int bpl)
947 if (trans_index < 0) {
948 for (
i=1;
i<=my;
i++) {
961 interlace++;
y=
top+4;
976 if (trans_index < 0) {
977 for (
i=1;
i<=my;
i++) {
988 interlace++;
y=
top+2;
1000 if (trans_index < 0) {
1001 for (
i=1;
i<=my;
i++) {
1020 if (
y >= sheight) out_of_bounds=
true;
1028 QRgb *
map = lcmap ? localcmap : globalcmap;
1043 scanIsCached =
false;
1053bool QGifHandler::imageIsComing()
const
1055 const int GifChunkSize = 4096;
1065 &nextDelay, &loopCnt);
1068 buffer.remove(0, decoded);
1086 qCWarning(lcGif,
"QGifHandler::canRead() called with no device");
1091 if (
device->
peek(head,
sizeof(head)) ==
sizeof(head))
1092 return qstrncmp(head,
"GIF87a", 6) == 0
1093 ||
qstrncmp(head,
"GIF89a", 6) == 0;
1099 const int GifChunkSize = 4096;
1109 &nextDelay, &loopCnt);
1112 buffer.remove(0, decoded);
1143 if (!scanIsCached) {
1145 scanIsCached =
true;
1148 if (frameNumber == -1)
1151 if (frameNumber >= imageSizes.
size() - 1)
1154 return imageSizes.
at(frameNumber + 1);
1174 if (!scanIsCached) {
1176 scanIsCached =
true;
1178 return imageSizes.
size();
1183 if (!scanIsCached) {
1185 scanIsCached =
true;
1190 else if (loopCnt == -1)
IOBluetoothDevice * device
bool supportsOption(ImageOption option) const override
Returns true if the QImageIOHandler supports the option option; otherwise returns false.
int nextImageDelay() const override
For image formats that support animation, this function returns the number of milliseconds to wait un...
int currentImageNumber() const override
For image formats that support animation, this function returns the sequence number of the current im...
bool read(QImage *image) override
Read an image from the device, and stores it in image.
int loopCount() const override
For image formats that support animation, this function returns the number of times the animation sho...
bool canRead() const override
Returns true if an image can be read from the device (i.e., the image format is supported,...
int imageCount() const override
For image formats that support animation, this function returns the number of images in the animation...
QVariant option(ImageOption option) const override
Returns the value assigned to option as a QVariant.
bool write(const QImage &image) override
Writes the image image to the assigned device.
void setOption(ImageOption option, const QVariant &value) override
Sets the option option with the value value.
\inmodule QtCore \reentrant
qint64 peek(char *data, qint64 maxlen)
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
ImageOption
This enum describes the different options supported by QImageIOHandler.
static bool allocateImage(QSize size, QImage::Format format, QImage *image)
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
qsizetype bytesPerLine() const
Returns the number of bytes per image scanline.
qsizetype sizeInBytes() const
QSize size() const
Returns the size of the image, i.e.
int width() const
Returns the width of the image.
uchar * bits()
Returns a pointer to the first pixel data.
int height() const
Returns the height of the image.
Format
The following image formats are available in Qt.
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
qsizetype size() const noexcept
const_reference at(qsizetype i) const noexcept
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
int qstrncmp(const char *str1, const char *str2, size_t len)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define FAST_SCAN_LINE(bits, bpl, y)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLenum GLsizei length
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLenum GLenum GLsizei void * row
GLenum GLenum GLsizei void * table
GLbitfield GLuint readBuffer
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
constexpr QRgb qRgb(int r, int g, int b)
unsigned long long quint64