Reputation: 47
For my Project I need to read an PPM(P3) image into memory. Because I want to rotate the input picture and therefore I would like to go through an x and y axis/array.
First I read the values of the image into an "unsigned char" since the color values used are only between 0 and 255 and to save memory I convert them into unsigned chars.
Every pixel in the PPM image has a red, green, blue values.
For this, I created this typedef struct
.
typedef struct{
unsigned char red;
unsigned char greed;
unsigned char blue;
} color;
I tried to make a simple 2-dimensional array like this:
color inputColor[pictureHeight][pictureWidth];
But this fails very fast when the pictures get bigger. I am trying to make it work, so I can allocate that 2d array with malloc. One attempt was:
color *inputColor[pictureHeight][pictureWidth];
//Allocating memory
for (int y = 0; y < pictureHeight; y++){
for (int x = 0; x < pictureWidth; x++){
inputColor[y][x] = malloc(sizeof(color));
}
}
// Here i am copying values from an inputStream to the structure
int pixel = 0;
for (int y = 0; y < pictureHeight; y++){
for (int x = 0; x < pictureWidth; x++){
inputColor[y][x]->red = inputMalloc[pixel];
pixel++;
inputColor[y][x]->green = inputMalloc[pixel];
pixel++;
inputColor[y][x]->blue = inputMalloc[pixel];
pixel++;
}
}
But it fails again in the first line...
How can a 2-dimensional struct array be allocated with malloc
, so the picture sizes don't matter that much any more?
Right now it fails around a picture size of 700x700 pixels.
Upvotes: 1
Views: 493
Reputation: 23792
The pointer to array approach posted by mch, I believe would be the best approach:
#include <stdlib.h>
color (*inputColor)[pictureWidth] = malloc(pictureHeight * sizeof *inputColor);
The access is the same as you are using, inputColor[y]
for line and inputColor[y][x]
for column, inputColor[y][x].red
to access struct member.
Since you stated you can't make it work, you can try using the pointer to pointer method, though slower, it may be easier to understand and apply:
color **inputColor;
inputColor = malloc(pictureHeight * sizeof *inputColor);
for (int y = 0; y < pictureHeight; y++)
{
inputColor[y] = malloc(pictureWidth * sizeof **inputColor);
}
The first malloc
allocates memory for pictureHeight
number of rows, the for
loop allocates memory for each row with the size of pictureWidth
.
The access is the same as the pointer to array method.
In these simplified pieces of code no error checks are performed, it's something you should do, namely checking malloc return values for errors.
Don't forget to free the memory when you're done with it:
For the first example:
free(inputColor);
For the second:
for (int y = 0; y < pictureHeight; y++)
{
free(inputColor[y]);
}
free(inputColor);
Upvotes: 1
Reputation: 67476
Double pointer solutions have a very weak point when considering images. They cannot be transferred directly to the screen memory or accessed fast way.
Much better is to use a pointer to array.
typedef struct{
unsigned char red;
unsigned char greed;
unsigned char blue;
} color;
int main(void)
{
size_t pictureHeight = 600, pictureWidth = 800;
color (*inputColor)[pictureHeight][pictureWidth];
inputColor = malloc(sizeof(*inputColor));
}
Upvotes: 3
Reputation: 36
Just allocate a double pointer and allocate memory to it:
color **inputColor;
inputcolor= malloc(sizeof(color*)*pictureHeight);
for (int y = 0; y < pictureHeight; y++){
inputColor[y] = malloc(sizeof(color)*pictureWidth);
}
Upvotes: 1