I've got this sample code below. I understand cells is being made in a 1 dimensional manner,
since the compiler stores 2d arrays in memory row-by-row in 1d. What I don't understand/can't visualize is how to access elements or change positions.
I know board->cells[i + (20 * (10 - 1))] = FLAG_WALL; is used to set flags for the bottom most row. From the format it looks to be using a formula but I am unsure of what it is. The formula also seems to change for the right and left edges.
(board->cells[i * 20 + 20 - 1] = FLAG_WALL;)
Looking at the line board->cells[20 * 2 + 2] = FLAG_SNAKE; it seems cell[42] is where the snake flag is spawned. What would the arithmetic look like to shift its position by 1 cell up, down, right, left? When imagining cell[42] as a part of a 1d array in memory I can't figure out the arithmetic nor the resulting cell number after a shift such as 'up'.
board_init_status_t initialize_default_board(board_t* board) {
board->width = 20;
board->height = 10;
board->cells = calloc(20 * 10, sizeof(int));
// Set edge cells!
// Top and bottom edges:
for (int i = 0; i < 20; ++i) {
board->cells[i] = FLAG_WALL;
board->cells[i + (20 * (10 - 1))] = FLAG_WALL;
}
// Left and right edges:
for (int i = 0; i < 10; ++i) {
board->cells[i * 20] = FLAG_WALL;
board->cells[i * 20 + 20 - 1] = FLAG_WALL;
}
// Add snake
board->cells[20 * 2 + 2] = FLAG_SNAKE;
return INIT_SUCCESS;
}
Think of the 1d array as a 2d one, the beginning of the last row would be at the position width * (height - 1) and the last cell of the last row at width * height almost the same logic goes for the sides.
board->cells[20 * 2 + 2] = FLAG_SNAKE; means it goes at the 2nd row in position 2. Or in (x;y) coordinates (2, 2). It's pure math. If you want to move in a 1d array like in a 2d one just multiply the length of one line by the index of the row you want to go (let's call it y) and then add x to reach the x cell.
board_init_status_t initialize_default_board(board_t* board) {
board->width = 20;
board->height = 10;
board->cells = calloc(20 * 10, sizeof(int));
// Set edge cells!
// Top and bottom edges:
for (int i = 0; i < 20; ++i) {
board->cells[i] = FLAG_WALL; // [0, 19] (top row)
board->cells[i + (20 * (10 - 1))] = FLAG_WALL; // [180, 199] (bottom row)
}
// Left and right edges:
for (int i = 0; i < 10; ++i) {
board->cells[i * 20] = FLAG_WALL; // (left row)
board->cells[i * 20 + 20 - 1] = FLAG_WALL; // (right row)
}
// Add snake
board->cells[20 * 2 + 2] = FLAG_SNAKE;
return INIT_SUCCESS;
}
Related
i am trying to make a blur filter in c that takes the neighboring pixels of the main pixel, takes the avarage of the rgb values and stores it in the temp array, them changes the image using the temp array values, it seems correct but it is not working as intended, giving an output of a very slightly blured image. I realy dont see my mistake and would be very thankful if someone helped, sorry if i made something horrible, started learning c last week.
i checked this post
Blurring an Image in c pixel by pixel - special cases
but i did not see were i went wrong.
im working with this data struct
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// ints to use later
int j;
int p;
RGBTRIPLE temp[height][width];
for(int n = 0; n < height; n++) // loop to check every pixel
{
for(int k = 0; k < width; k++)
{
int widx = 3;
int hghtx = 3;
// conditionals for border cases
int y = 0;
if(n == 0)
{
p = 0;
hghtx = 2;
}
if(n == height - 1)
{
p = -1;
hghtx = 2;
}
if(k == 0)
{
j = 0;
widx = 2;
}
if(k == width - 1)
{
j = -1;
widx = 2;
}
for(int u = 0; u < hghtx; u++) // matrix of pixels around the main pixel using the conditionals gathered before
for(int i = 0; i < widx; i++)
if(y == 1) // takes the average of color and stores it in the RGB temp
{
temp[n][k].rgbtGreen = temp[n][k].rgbtGreen + image[n + p + u][k + j + i].rgbtGreen / (hghtx * widx);
temp[n][k].rgbtRed = temp[n][k].rgbtRed + image[n + p + u][k + j + i].rgbtRed / (hghtx * widx);
temp[n][k].rgbtBlue = temp[n][k].rgbtBlue + image[n + p + u][k + j + i].rgbtBlue / (hghtx * widx);
}
else // get first value of temp
{
temp[n][k].rgbtGreen = (image[n + p + u][k + j + i].rgbtGreen) / (hghtx * widx);
temp[n][k].rgbtRed = (image[n + p + u][k + j + i].rgbtRed) / (hghtx * widx);
temp[n][k].rgbtBlue = (image[n + p + u][k + j + i].rgbtBlue) / (hghtx * widx);
y++;
}
}
}
// changes the original image to the blured one
for(int n = 0; n < height; n++)
for(int k = 0; k < width; k++)
image[n][k] = temp[n][k];
}
I think it's a combination of things.
If the code worked the way you expect, you would be still doing a blur of just 3x3 pixels and that can be hardly noticeable, especially on large images (I'm pretty sure it will be unnoticeable on an image 4000x3000 pixels)
There are some problems with the code.
As #Fe2O3 says, at the end of the first line, widx will change to 2 and stay 2 for the rest of the image.
you are reading from temp[][] without initializing it. I think that if you compile that in release mode (not debug), temp[][] will contain random data and not all zeros as you probably expect. (as #WeatherWane pointed out)
The way you calculate the average of the pixels is weird. If you use a matrix 3x3 pixels, each pixel value shoud be divided by 9 in the final sum. But you divide the first pixel nine times by 2 (in effect doing /256), the second one eight times by 2 (so its pixel/128) etc. until the last one is divided by 2. So basically, it's mostly the value of the bottom right pixel.
also, since your RGB values are just bytes, you may want to divide them first and only then add them, because otherwise, you'll get overflows with wild results.
Try using a debugger to see the values you are actually calculating. It can be quite an eye opener :)
I want to transform 2d array to 1d. I put the most important part of my code.
int mask[3][3] = {{0, -1, 0}, {-1, 4, -1}, {0, -1, 0}};
for (i = 1; i < rows - 1; i++) {
for (j = 1; j < cols - 1;j++) {
int s;
s = mask[0][0] * image[i-1][j-1]
+ mask[0][1] * image[i-1][j]
+ mask[0][2] * image[i-1][j+1]
+ mask[1][0] * image[i][j-1]
+ mask[1][1] * image[i][j]
+ mask[1][2] * image[i][j+1]
+ mask[2][0] * image[i+1][j-1]
+ mask[2][1] * image[i+1][j]
+ mask[2][2] * image[i+1][j+1];
}
}
my 1d array
for (k = rows + 1; k < (cols * rows) / 2; k++) {
int s;
s = 0 * image_in[k-rows-1]
- 1 * image_in[k-rows]
+ 0 * image_in[k-rows+1]
- 1 * image_in[k-1]
+ 4 * image_in[k]
- 1 * image_in[k+1]
+ 0 * image_in[k+rows-1]
- 1 * image_in[k+rows]
+ 0 * image_in[k+rows+1];
}
That should be the same but I don't know if I correctly doing transformations. Can someone tell me if that is ok?
First of all: Why do you want to get away with the 2D array? You think that 2D array dimensions must be constant? Well, in that case I have good news for you: You are wrong. This code should work perfectly:
int width = ..., height = ...;
//Create a 2D array on the heap with dynamic sizes:
int (*image_in)[width] = malloc(height * sizeof(*image_in));
//initialize the array
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
image_in[i][j] = ...;
}
}
You see, apart from the somewhat cryptic declaration of the array pointer, the indexing remains exactly the same as with an automatic 2D array on the stack.
Within your given loop, you want to address the cells relative to the center cell. This is easiest done by actually addressing relative to that cell:
for (i = 1; i < rows - 1; i++) {
for (j = 1; j < cols - 1;j++) {
int* center = &image_in[i][j];
int s = mask[0][0] * center[-width - 1]
+ mask[0][1] * center[-width]
+ mask[0][2] * center[-width + 1]
+ mask[1][0] * center[-1]
+ mask[1][1] * center[0]
+ mask[1][2] * center[1]
+ mask[2][0] * center[width - 1]
+ mask[2][1] * center[width]
+ mask[2][2] * center[width + 1];
}
}
This works because the 2D array has the same memory layout as your 1D array (this is guaranteed by the C standard).
The edge handling in a 1D loop is always wrong: It will execute the body of the loop for the first and last cells of each line. This cannot be fixed without introducing some if() statements into the loop which will significantly slow things down.
This may be ignored if the consequences are proven to be irrelevant (you still need to exclude the first and last lines plus a cell). However, the edge handling is much easier if you stick to a 2D array.
If the first part of your code gives you expected result, then you can do the same with 1d array this way :
for (i = 1; i < rows - 1; i++) {
for (j = 1; j < cols - 1;j++) {
int s;
s = mask[0][0] * image_in[i-1+rows*(j-1)]
+ mask[0][1] * image_in[i-1+rows*j]
+ mask[0][2] * image_in[i-1+rows*(j+1)]
+ mask[1][0] * image_in[i+rows*(j-1)]
+ mask[1][1] * image_in[i+rows*j]
+ mask[1][2] * image_in[i+rows*(j+1)]
+ mask[2][0] * image_in[i+1+rows*(j-1)]
+ mask[2][1] * image_in[i+1+rows*j]
+ mask[2][2] * image_in[i+1+rows*(j+1)];
}
}
This way, if you are good with 2d arrays, you can do the same without error with 1d array as if they were 2d.
Here is the code I am using. When I run it, it doesn't seem to change anything in the image except the last 1/4 of it. That part turns to a solid color.
void maxFilter(pixel * data, int w, int h)
{
GLubyte tempRed;
GLubyte tempGreen;
GLubyte tempBlue;
int i;
int j;
int k;
int pnum = 0;
int pnumWrite = 0;
for(i = 0 ; i < (h - 2); i+=3) {
for(j = 0 ; j < (w - 2); j+=3) {
tempRed = 0;
tempGreen = 0;
tempBlue = 0;
for (k = 0 ; k < 3 ; k++){
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
if ((data[pnum].g) > tempGreen){tempGreen = (data[pnum + k].g);}
if ((data[pnum].b) > tempBlue){tempBlue = (data[pnum + k].b);}
if ((data[(pnum + w)].r) > tempRed){tempRed = (data[(pnum + w)].r);}
if ((data[(pnum + w)].g) > tempGreen){tempGreen = (data[(pnum + w)].g);}
if ((data[(pnum + w)].b) > tempBlue){tempBlue = (data[(pnum + w)].b);}
if ((data[(pnum + 2 * w)].r) > tempRed){tempRed = (data[(pnum + 2 * w)].r);}
if ((data[(pnum + 2 * w)].g) > tempGreen){tempGreen = (data[(pnum + 2 * w)].g);}
if ((data[(pnum + 2 * w)].b) > tempBlue){tempBlue = (data[(pnum + 2 * w)].b);}
pnum++;
}
pnumWrite = pnum - 3;
for (k = 0 ; k < 3 ; k++){
((data[pnumWrite].r) = tempRed);
((data[pnumWrite].g) = tempGreen);
((data[pnumWrite].b) = tempBlue);
((data[(pnumWrite + w)].r) = tempRed);
((data[(pnumWrite + w)].g) = tempGreen);
((data[(pnumWrite + w)].b) = tempBlue);
((data[(pnumWrite + 2 * w)].r) = tempRed);
((data[(pnumWrite + 2 * w)].g) = tempGreen);
((data[(pnumWrite + 2 * w)].b) = tempBlue);
pnumWrite++;
}
}
}
}
I can see several problems with that code - being difficult to follow not being the least!
I think your main problem is that the loop is (as you probably intended) run through h/3 * w/3 times, once for each 3x3 block in the image. But the pnum index runs only increases by 3 for each block, and reaches a maximum of about h*w/3, rather than the intended h*w. That means that only the first third of your image will be affected by your filter. (And I suspect your painting is done 'bottom-up', so that's why you see the lowest part change. I remember .bmp files being structured that way, but perhaps there are others as well.)
The 'cheap' fix would be to add 2*w at the right point, but nobody will ever understand that code again. I suggest you rewrite your indexing instead, and explicitly compute pnum from i and j in each turn through the loop. That can be improved on for readability, but is reasonably clear.
There's another minor thing: you have code like
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
where the indexing on the right and on the left differ: this is probably also giving you results different from what you intended.
As Jongware points out, writing to the input array is always dangerous - your code is intended, I believe, to avoid that problem by only looking once into each 3x3 block, but his suggestion of a separate output array is very sensible - you probably don't want the blockiness your code gives anyway (you make each 3x3 block all one colour, don't you?), and his suggestion would let you avoid that.
I have a 2d array a[3][3] and the program reads 2 sets of IDs for 2 numbers on the array.
I need to print all the possible paths from one number to another.
So far, I know how to find how many paths exist every time:
scanf("%d %d",&ai,&aj);
scanf("%d %d",&bi,&bj);
distance_i = bi - ai;
if(distance_i<0){distance_i=distance_i*-1;}
distance_j = bj - aj;
if(distance_j<0){distance_j=ap_j*-1;}
path = 1+(distance_i*distance_j);
For example, if the array a is:
1 2 3
4 5 6
7 8 9
With
input_1: 0,0
input_2: 1,2
The output must be:
there are 3 possible paths:
a) 1,2,5,8
b) 1,4,5,8
c) 1,4,7,8
But I can't find a way to print them. Any ideas?
From location[v1][h1] to location[v2][h2]
Move kinds are: DOWN, RIGHT
The width is: (v2-v1) * DOWN
The height is: (h2-h2) * RIGHT
=> all path choice action list: [width, height] = [(v2-v1) * DOWN, (h2-h2) * RIGHT]
Example: from location[0][0] to location [2][1]
action list = [DOWN, DOWN, RIGHT]
all unique path choices are (It make minus the duplicate repeated permutation from a given list):
[DOWN, DOWN, RIGHT]
[DOWN, RIGHT, DOWN]
[RIGHT, DOWN, DOWN]
You will use backtracking (Depth-First Search) to find all possible routes.
See program test here http://ideone.com/GqWLa5
#define VALID(x) ((x) >= 0 && (x) < 3)
int arr[3][3];
// to detect previous visited cells and eliminate infinite recursion
short vis[3][3] = { 0 };
int xtar, ytar; // destination cell
int xsrc, ysrc; // source cell
// to move in directions: down, up, right, and left, respectively
const int dirx[] = { 0, 0, 1, -1 };
const int diry[] = { 1, -1, 0, 0 };
// temp buffer to print paths
// max size = size of arr + zero termination char
char tmp_path[3 * 3 + 1];
void rec(int x, int y, int idx) // idx is used to fill tmp_path
{
int i;
tmp_path[idx] = arr[y][x] + '0';
if (x == xtar && y == ytar) // basic case
{
tmp_path[idx + 1] = 0; // put zero char
printf("%s\n", tmp_path); // print path
return;
}
if (vis[y][x]) return; // already visited
vis[y][x] = 1; // otherwise, mark as visited
for (i = 0; i < 4; ++i) // for each of the 4 directions
if (VALID(y + diry[i]) && VALID(x + dirx[i]))
rec(x + dirx[i], y + diry[i], idx + 1);
vis[y][x] = 0; // reset visited so that can be visited again
}
main()
{
// input xtar, ytar, xsrc, ysrc, arr
rec(xsrc, ysrc, 0);
}
I know how to simulate a 2d array in a linear array using [x + y * width] as a linear index.
I can extend this to 3d arrays: [x + y * width + z * width * height].
Is there a general formula for N-dimensional array?
I'm looking for a language-agnostic answer.
Sure. Just extending your example gives x + y*width + z*width*height + w*width*height*depth + ...
In other words, dim1 + dim2*size1 + dim3*size1*size2 + dim4*size1*size2*size3 + ...
Eh, if you want some code... :-) C is language-agnostic enough, ya?
Assume input: location[dimensions]
Assume a table exists maxBound[dimensions] that contains the maximum boundaries of each dimension of the table.
int index = 0;
int multiplier = 1;
for (int i = 0;i < dimensions;i++)
{
index += location[i] * multiplier;
multiplier *= maxBound[i];
}
Your index will end up in the index field.
Test:
location = [3,4,5]
maxBound = [10,20,30]
loop initial: index = 0, multiplier = 1.
loop i=0: index = 3, multiplier = 10.
loop i=1: index = 43, multiplier = 200.
loop i=2: index = 1043, multipler = 6000.
I think this makes sense, but this is just coming out of the top of my head.