PDA

View Full Version : QImage getting black areas for GIF frames



elephant
5th December 2013, 20:42
I'm using a simple QImage program to look at frames from GIF animations. Occasionally the output image is corrupted, with black areas appearing over it. I have tried doing a simple export of the frames to files, in JPG, PNG, and GIF format and the results are the same. I've also verified the black areas are not transparency (although I've no idea how to set this in Qt if that were the case).

This is the relevant code:



QImage* image = new QImage();
QImageReader* reader = new QImageReader(gif);
reader->read(image);

for(int index=0;index<=reader->imageCount();index++)
{
reader->jumpToNextImage();
reader->read(image);
QString frameName = dir + '/' + QString("out%1.jpg").arg(index,5,10,QChar('0'));
image->save(frameName,"JPEG",100);
}


So I'm wondering if this is a known issue or if anyone else has encountered this? Or perhaps there are some changes required for certain colourspaces or something else I am not considering.

ChrisW67
5th December 2013, 22:14
If memory serves GIF animations can be a base image followed by a series of difference images. Are you perhaps seeing only the differences from the preceding frame? Can you post a link to an example image that does this?

elephant
6th December 2013, 00:11
Yes, that is correct. The frames can call a disposal method and if the underlying frames are transparent (or of different dimensions) then you would see the spaces in the raw frame. Imagemagick uses a "coalesce" option to collapse each frame into what the viewer would see. I do not know if QImage has an option to change its behaviour, but it does this by default (which is what I want).

I also looked at the frames as dumped out by Imagemagick (without coalesce) and these frames did not have transparency. Actually almost all animated gifs use this trick, and 95% of them work with the QImage libary (many times faster than Imagemagick too!)

ChrisW67
6th December 2013, 03:40
Your code reads an image imageCount() + 2 times. I expect the last two images are the problem children.


QImage* image = new QImage();
QImageReader* reader = new QImageReader(gif);
reader->read(image);

for(int index=0;index<=reader->imageCount();index++)
{
reader->jumpToNextImage();
reader->read(image);
QString frameName = dir + '/' + QString("out%1.jpg").arg(index,5,10,QChar('0'));
image->save(frameName,"JPEG",100);
}

Line 3: reads first image in file (discarded)
Line 5: Loop of imageCount() + 1 iterations
Line 7: index == 0, jump to second image in file. index == 1, jump to third image...
Line 8: returns false (ignored) on last two loops

Try this on your problem image


const QString gif("test.gif");
QImage image;
QImageReader reader(gif);
qDebug() << "Count =" << reader.imageCount();
for (int index = 0; index < reader.imageCount(); ++index) {
if (reader.read(&image))
image.save(QString("output%1.png").arg(index, 3, 10, QLatin1Char('0')));
}

elephant
7th December 2013, 00:29
No I think that error was just introduced in the code to extract the images to a file for tests.

However, I did look more closely and the problem is the disposal method "Previous".

For examples see this page: http://www.imagemagick.org/Usage/anim_basics/#previous

Using your code with the example gif with disposal method "None" (http://www.imagemagick.org/Usage/anim_basics/canvas_none.gif), frame #3 includes frame 2,1 and 0 all on top of one another. This is correct.

Using the gif with disposal method "Previous" (http://www.imagemagick.org/Usage/anim_basics/canvas_prev.gif) frame #3 includes frame 2 and 1, but does NOT include frame 0. This is not correct.

I guess as a side question, does anyone know if there are options for how qt handles the disposal method?