Problem displaying transparent animated gifs

I’m trying to create a slideshow with transparent animated gifs.

To do this, I created a gif class that loads a sprite sheet and then alternates between each section of the sprite sheet to simulate a gif with transparency (since .pngs have no problem with transparency in OF).

If I create an instance and build the project, it works fine and you can see what appears to be an animated gif with transparency… But when I try to create more than one instance, it becomes unpredictable… sometimes loading one image and occasionally another image.

I’m guessing that I screwed something up with either the pointers I’m using or the variable scope of the instances… Just beginning to learn C++ and OF. :slight_smile:

I’ll paste my code below for posterity, but I’m guessing that some may find it easier to check out the code on GitHub, so here’s a link, just in case:

animatedGif.h

//  animatedGif.h
//  slideshowDancing

#ifndef __slideshowDancing__animatedGif__
#define __slideshowDancing__animatedGif__

#include "ofMain.h"


class AnimatedGif {
    
public: // place public functions or variables declarations here
    
    // methods, equivalent to specific functions of your class objects
    void update();  // update method, used to refresh your objects properties
    void draw();    // draw method, this where you'll do the object's drawing
    
    
    // from animated gif
    ofImage myImage;
    
    int xPositionOfSprite;
    
    int i;
    float x, y;
    int incrementAmount = 600;
    int numberOfFrames = 6;
    
    
    void setValueX(int _x);
    
    
    
    AnimatedGif(string _imagePath, float _x, float _y); // constructor - used to initialize an object, if no properties are passed
    //               the program sets them to the default value
    

    
private: // place private functions or variables declarations here
};


#endif /* defined(__slideshowDancing__animatedGif__) */

animatedGif.cpp:

//  animatedGif.cpp
//  slideshowDancing

#include "animatedGif.h"

AnimatedGif::AnimatedGif(string _imagePath, float _x, float _y)
{
    string imagePath = _imagePath;
    float x = _x;
    float y = _y;

    myImage.loadImage(imagePath);
    
}

void AnimatedGif::update() {
    i++;
    
    if (i % 20 == 0) {
        if (i > 120) {
            i = 0;
        }
        
        xPositionOfSprite += incrementAmount;
        
        if (xPositionOfSprite >= incrementAmount * numberOfFrames) {
            xPositionOfSprite = 0;
        }
        
    }
}

void AnimatedGif::draw() {
    myImage.drawSubsection(x, y, 600, 600, xPositionOfSprite, 0);  // draw first frame
}

ofApp.h

#pragma once

#include "ofMain.h"
#include "animatedGif.h"

class ofApp : public ofBaseApp{
public:
    void setup();
    void update();
    void draw();
    
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y);
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
    
    void drawAllGifs();
    void updateAllGifs();
    
    int numOfImages = 2;
    
private:
    AnimatedGif *gif[2];
};

ofApp.cpp

#include "ofApp.h"
#include "animatedGif.h"

//--------------------------------------------------------------
void ofApp::setup(){
    gif[0] = new AnimatedGif("images/png-sprite-sheet.png", 0, 0);
    gif[1] = new AnimatedGif("images/png-sprite-sheet-copy.png", 200, 600);
}

//--------------------------------------------------------------
void ofApp::update(){
    updateAllGifs();
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0, 0, 0);
//    ofSetColor(255, 255, 255);
    
    drawAllGifs();
}

//--------------------------------------------------------------
void ofApp::drawAllGifs() {
    // run draw function on each gif instance
    for (int i = 0; i < numOfImages; i++){
        gif[i]->draw();
    }
}

//--------------------------------------------------------------
void ofApp::updateAllGifs() {
    // run draw function on each gif instance
    for (int i = 0; i < numOfImages; i++){
        gif[i]->update();
    }
}
AnimatedGif::AnimatedGif(string _imagePath, float _x, float _y)
{
    string imagePath = _imagePath;
    float x = _x;
    float y = _y;

    myImage.loadImage(imagePath);
    
}

When you set

    float x = _x;
    float y = _y;

in the constructor you never actually set the member variables (just a local version of x/y) … so then when you draw your subsection in the draw() method, they may sometimes show up in the right place, but sometimes they may not because they have not been correctly initialized.

1 Like

The solution just looks something like:

AnimatedGif::AnimatedGif(string _imagePath, float _x, float _y)
{
    x = _x;
    y = _y;
    myImage.loadImage(_imagePath);
}
1 Like

Ah, I see!!.. Still getting the hang of this…

So by declaring the type inside the constructor, I was initializing a new variable, instead of just setting the variable that was initialized in my header file?

This definitely fixed my problem. Thanks!

Yes, you were creating a new local variable (even though it had the same name as your class variable from your header file)! If you want to learn more about how it all works, look around for information on variable “scope”. Good luck!

1 Like