-
strange number problem
Hi I just started C and since I started with a scripting language, pointers are hard to grasp.
I'm hoping someone can help me with this baffling problem.
I wrote the code below hoping to make a image manipulating program. I create a white image and output it as ppm type 3 format but I get a strange result.
Code:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct pixel {
float r, g, b;
} pixel;
typedef struct image {
int width, height;
pixel *(data[]);
} image;
void createWhiteImage(image **img, int width, int height) {
int i;
pixel pixels[width*height];
for(i = 0; i < width*height; ++i)
{
pixels[i].r = 255;
pixels[i].g = 255;
pixels[i].b = 255;
}
*img = (image *)malloc(sizeof(image));
(**img).width = width;
(**img).height = height;
(*((**img).data)) = pixels;
}
void imageToP3(char *str, image *img) {
int i;
char tmp[70];
strcpy(str, "P3\n");
sprintf(tmp, "%d %d\n", img->width, img->height);
strcat(str, tmp);
strcat(str, "255\n");
for(i = 0; i < img->width*img->height; ++i)
{
sprintf(tmp, "% 3.0f % 3.0f % 3.0f ", (*(img->data))[i].r, (*(img->data))[i].g, (*(img->data))[i].b);
strcat(str, tmp);
if ( i%10 ==9 ) {
strcat(str, "\n");
}
}
}
pixel getPixel(image *img, int x, int y) {
return (*((*img).data))[img->width * y + x - 1];
}
int main (int argc, char const *argv[])
{
image *b;
char str[10000];
createWhiteImage(&b, 10, 10);
imageToP3(str, b);
printf("%s\n", str);
return 0;
}
Result:
Code:
P3
10 10
255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 -2 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -2 255 255 255 255 255 255 255 255 255
255 255 0 -2 0 0 -2 0 -0 -0 -2 0 -0 255 255 255 255 255 255 255 255 255 -2 255 255 255 255 255 255 0
0 0 0 0 -2 0 0 0 -2 -2 -0 0 0 0 0 -0 0 2422584382005669456248832 -0 255 255 -0 -0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 -2 0 -2 -2 0 -0 -2 0 -0 0 -2 -0 -0 -0 0 0 -0 0 0 0 -2 0
0 0 0 0 0 0 0 0 0 0 -2 -0 nan 0 -2 nan -0 0 0 0 0 -0 255 255 -2 255 0 -0 0 0
0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 0 0 -2
-2 0 -2 255 0 255 255 255 -2 0 4 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255
Why do I get these strange numbers? What am I doing wrong?
Environment: Mac OS X, PPC
-
> pixel pixels[width*height];
Since this array is local to function createWhiteImage, it ceases to exist once the function ends. And you're storing this address of this local array in img.
-
You might want to try using a library that allows you to display some proper visual output. SDL might be a good one to start with. Lodes computer graphics tutorials explains a lot of the stuff you might want to do as well.
For storing colours you would probably be better using an integer RGB value than 3 floats. It would save a lot of space.
-
Thanks swoopy! So my guess is that I could use malloc to allocate sizeof(pixel)*width*height bytes of memory, but then I would have to manually move the pointer sizeof(pixel) at a time. Is this ok or is there a better proper way?
Thanks mike_g! Right now I'm only writing this to learn more about C but SDL will be great to use in the future.
-
>So my guess is that I could use malloc to allocate sizeof(pixel)*width*height bytes of memory,
Correct. And ideally the memory should be freed at the end of main().
>but then I would have to manually move the pointer sizeof(pixel) at a time.
Actually since it's be declared of type pixel, you could use array index notation like you are doing now on your pixels array. Even if you decided to use a pointer versus a simple array index, the pointer would increment automatically by sizeof(pixel). But why not use array indexing?
By the way some of your notation can be simplified, for example:
Code:
(**img).width = width;
(**img).height = height;
This could be rewritten as:
Code:
(*img)->width = width;
(*img)->height = height;
-
Thanks for your advice swoopy! I've managed to write a working script that reads and writes p3 files. thanks alot!
-
Actually I have one more question...
I don't know how to free memory.
This is my code
Code:
typedef struct pixel {
int r, g, b;
} pixel;
typedef struct image {
int width, height;
pixel *data;
} image;
void createWhiteImage(image **img, int width, int height)
{
int i;
*img = (image *)malloc(sizeof(image));
(*img)->data = malloc(sizeof(pixel)*width*height);
for(i = 0; i < width*height; ++i)
{
((*img)->data)[i].r = 255;
((*img)->data)[i].g = 255;
((*img)->data)[i].b = 255;
}
(*img)->width = width;
(*img)->height = height;
}
and I wrote a function that will free the memory
Code:
void freeImage(image **img)
{
free((*img)->data);
free((*img));
}
Am I doing enough freeing? I always get confused about what to free.
-
Yes you do enough freeing
What you can add to your function - setting *img pointer to NULL to prevent using the freeed memory by mistake
-
See the FAQ on casting malloc in C programs (don't do it).
-
thanks vart and Salem. I've followed both advices and successfully implemented in my code. I was casting malloc without thinking so it was very interesting read.