gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Graphics > Problem using GD

#37760 - kajic - Tue Mar 15, 2005 11:41 pm

UPDATE2:
I updated the code so that output format and the frameskipping rate can be specified from the terminal. Also added a backup function so that one can easily backup the old animation file when generating another one.

UPDATE:
I just came to the bright idea of testing another program to open the gif generated by my program. Guess what? It worked perfectly! Ive been sitting for 6 hours trying to fix an error not there... one thing is for sure, I wont be using Kuickshow anymore.

Hi, first of all I hope I am placing the thread in the right forum. I was considering between the Coding, the C/C++, and this one and finally decided this was the one I should use.

I've made a little program that can generate a series of png images from an animation created by an algorithm. This part works perfectly using some GD functions. Then I decided I wanted a way to create an animated gif directly instead of merging the pngs into a gif using the ImageMagick convert program together with a shell script.
Well, sufficient to say I tried and even though I get a lot of data written to the output gif when I try to view it I only see a black image... no animation, no nothing. I am hoping I have done some easy to see mistake in my coding and that someone can point out why I am not getting the desired result.
Btw, the "tool" Im making will be used to make nice sprites for a gba game I am thinking to start on. You might say I could just as easy make the animations with photoshop but the thing is my skills in that area are equal to zero so I trust more in my ability to algorithmically create animations :)
Anyway, here is my code... I hope you will find it easy to read/understand!

Code:

#include<gd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define WIDTH 180
#define HEIGHT 120
#define GIF_NAME "animation.gif"


/* determine if a file exists */

int fileExists(char *filename) {
  /* declare file */
  FILE *file;
 
  /* try to open file */
  if ((file = fopen(filename, "r")) == NULL)
    return 0;

  /* as the file exists we must close it */
  fclose(file);
  return 1;
}


/* add the frame to the gif-animation specified by GIF_NAME. if no such
   animation exists one will be created and before we add the frame the
   header of the gif will be written to the created file */

void makeGif(gdImagePtr im) {
  /* declare output file */
  FILE *outFile;

  /* if there exists no animatione we will create one and write its header */
  if (!fileExists(GIF_NAME)) {
    /* open file */
    outFile = fopen(GIF_NAME, "wb");
       
    /* write the header */
    gdImageGifAnimBegin(im, outFile, 0, 0);

    /* close the file */
    fclose(outFile);
  }

  /* open file im append mode */
  outFile = fopen(GIF_NAME, "ab");

  /* add the frame */
  gdImageGifAnimAdd(im, outFile, 1, 0, 0, 1, gdDisposalNone, NULL);

  /* close the file */
  fclose(outFile);
}


/* terminate the gif-animation specified by GIF_NAME. this is done
   by adding a semicolon to the end of the file. */

void closeGif() {
  /* declare output file */
  FILE *outFile;

  /* open file in append mode */
  outFile = fopen(GIF_NAME, "ab"); 

  gdImageGifAnimEnd(outFile);
}


/* save the frame at im to a png-file */

void makePng(gdImagePtr im, int frame) {
  /* declare output file */
  FILE *outFile;

  char frameName[11];
  frameName[0] = '\0';
 
  /* convert frame int to string */
  sprintf(frameName, "%d", frame);

  /* append the extension */
  strcat(frameName, ".png\0");

  /* open output file */
  outFile = fopen(frameName, "wb");

  /* output the image */
  gdImagePng(im, outFile);

  /* close file */
  fclose(outFile);
}


/* if the current frame shouldnt be skipped we can either call
   upon makePng for it to create the frame OR makeGif so that
   the frame can be added to the gif-animation specified by
   GIF_NAME */

void makeFile(gdImagePtr im, char *type, int frame, int frameSkipping) {
  /* check if the frame we are at should be outputed */
  if (frame % (frameSkipping+1))
    return;

  /* check what type of image we want to output */
  if (!strcmp(type, "gif"))
    makeGif(im);
  else if (!strcmp(type, "png"))
    makePng(im, frame);
}


/* sets the given pixel in the frame im to the given color */

void putPixel(gdImagePtr im, int x_pos, int y_pos, int red, int green, int blue) {
  /* put the pixel to the image */
  gdImageSetPixel(im, x_pos, y_pos, gdImageColorResolve(im, red, green, blue));
}


/* draws a line from from_x, from_t to to_x, to_y */

void drawLine(gdImagePtr im, int from_x, int from_y, int to_x, int to_y, int red, int green, int blue) {
  /* draw the line */
  gdImageLine(im, from_x, from_y, to_x, to_y, gdImageColorResolve(im, red, green, blue));
}


/* create a frame with the given dimensions/background color
   note: the color of the background is also made transparent */

gdImagePtr createImage(gdImagePtr im, int width, int height, int red, int green, int blue) {
  /* allocate the image */
  im = gdImageCreate(width, height);

  /* allocate the background color, as it is the first color allocated in a new
     image it will be used as background */
  int bg;
  bg = gdImageColorAllocate(im, red, green, blue);
 
  return im;
}


/* create a backup of the animation specified by GIF_NAME */

void backupAnimation(void) {
  if (fileExists(GIF_NAME)) {
    char newName[200];
    newName[0] = '\0';
   
    int n;
    for (n=1; n>0; n++) {
      sprintf(newName, "old.%d." GIF_NAME, n);
      if (!fileExists(newName))
   n=-1;
    }

    rename(GIF_NAME, newName);
  }
}


int main(int argc, char *argv[]) {
  /* check if the correct number of arguments have been suplied */
  if (argc != 3) {
    /* print usage message */
    printf("Usage: %s [string png/gif] [int frameSkip where frameSkip>=0]\nExample: %s gif 9; would produce a gif animation where every tenth frame is used. \nExample: %s png 0; would produce one png image for each frame. \nNote: The first frame can't be skipped. \n", argv[0], argv[0], argv[0]);
    return 20;
  }
 
  /* set output type */
  char outType[3];
  strcpy(outType, argv[1]);

  /* set frameSkip value */
  int frameSkip;
  frameSkip = atoi(argv[2]); /* this will cause an floating point exception if argv[2] cant be converted to and int */

  /* backup the animation file if it already exists */
  if (!strcmp(outType, "gif"))
    backupAnimation();
 
  /* declare the image */
  gdImagePtr im;

  /* create the image */
  im = createImage(im, WIDTH, HEIGHT, 0, 0, 0);

  /* a simple algorithm indended for testing */
  int frame;
  int red=0;
  for (frame=0; frame<HEIGHT; frame++) {
    /* put pixels to image */
    int i;
    for (i=0; i<WIDTH; i++)
      putPixel(im, i, frame, red, 0, 0);

    /* output the image */
    makeFile(im, outType, frame, frameSkip);

    /* change the color of the next row */
    red++;
  }
  srand(time(NULL));
  int r;
  int x=WIDTH/2, y=HEIGHT/2;
  for (frame=0; frame<HEIGHT/2; frame++) {
    r = (rand() % (HEIGHT/2))-(HEIGHT/4);
    x+=r;
    r = (rand() % (HEIGHT/2))-(HEIGHT/4);
    y+=r;
    red = (rand() % WIDTH);
    drawLine(im, WIDTH/2, HEIGHT/2, x, y, red, 0, 0);
    makeFile(im, outType, frame, frameSkip);
   
    x=WIDTH/2;
    y=HEIGHT/2;
  }
  for (frame=0; frame<HEIGHT; frame++) {
    /* put pixels to image */
    int i;
    for (i=0; i<WIDTH; i++)
      putPixel(im, i, frame, 0, 0, 0);

    /* output the image */
    makeFile(im, outType, frame, frameSkip);

    /* change the color of the next row */
    red++;
  } /* end of the testing algorithm */

  /* close gif */
  if (!strcmp(outType, "gif"))
    closeGif();

  /* destroy image */
  gdImageDestroy(im);

  return 0;
}


Last edited by kajic on Thu Mar 17, 2005 1:07 am; edited 1 time in total

#37775 - FluBBa - Wed Mar 16, 2005 9:46 am

You do know this forum is for Gameboy Advance, right?
_________________
I probably suck, my not is a programmer.

#37784 - tepples - Wed Mar 16, 2005 2:26 pm

And for tools designed to convert images for use on a Game Boy Advance. Explanation using an example of a program that you maintain: Imagine a bmp/jpg/png to PocketNES splash screen converter.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.