Image flipping incorrectly...Why? - c

I am trying to flip my image on a Y Axis, and it does flip, but it leaves odd spaces in the middle and on the right side, it wont flip the entire image perfectly, I am limiting the images to 450 by 450 and a P3...Anyone have any ideas, because my algorithm is correct
for(j=0; j < imgur.width/2; j++)
{
for(i=0; i < imgur.height; i++)
{
temp.red = imgur.image[i][j].red;
imgur.image[i][j].red = imgur.image[i][imgur.height-j-1].red;
imgur.image[i][imgur.height-j-1].red = temp.red;
temp.green = imgur.image[i][j].green;
imgur.image[i][j].green = imgur.image[i][imgur.height-j-1].green;
imgur.image[i][imgur.height-j-1].green = temp.green;
temp.blue = imgur.image[i][j].blue;
imgur.image[i][j].blue = imgur.image[i][imgur.height-j-1].blue;
imgur.image[i][imgur.height-j-1].blue = temp.blue;
}
}
Here's my algorithm... Before that I am printing out the P3, the comment, the width and height, and the maxColor. I am using two structs to get the data and reading in a file from the terminal...
Here's how I'm printing out the data. Anyone have any ideas?
for(i=imgur.height-1; i >= 0; i--)
{
for(j=0; j < imgur.width; j++)
{
printf("%i\n", imgur.image[i][j].red);
printf("%i\n", imgur.image[i][j].green);
printf("%i\n", imgur.image[i][j].blue);
}
}

my symmetric detector is confused by (in the upper part)
for(j=0; j < imgur.width/2; j++) {
for(i=0; i < imgur.height; i++) {
and (in the lower part)
for(i=imgur.height-1; i >= 0; i--) {
for(j=0; j < imgur.width; j++) {

You have made a little typo mistake in the flip algorithm: as you flip upside-down, you have to scan all lines entirely and half of the height of the image, not the inverse.
for(j=0; j < imgur.width; j++)
{
for(i=0; i < imgur.height/2; i++)
{
//code of your loop, removed for compactness
}
}
EDIT
In fact, for left-right swapping, you have also inverted the complement of index j. j is along the X-axis, belonging the range 0:width-1, so the complement is width-1-j.
I have coded a version of this algorithm a long time ago, it was like that:
for (i=0; i!=h; i++) {
for (j=0; j!=w/2; j++) {
temp = src[i][w-1-j];
dst[i][w-1-j] = src[i][j];
dst[i][j] = temp;
}
}
I think it works fine (As you are working with a pixel struct, it is perfectly correct to swap the whole pixel like this).

Related

Face detector program in C via arrays

So I need to make a "face detector" program in C. Basically I need to input the number of "face detections", resolution height and width (max 120), and the coordinates of the "face". Then the input is three h*w arrays which serve as RGB values.
The output of the program should be the same RGB values from the input, but with a green rectangle connecting the coordinates (thus highlighting the face on the picture), and the alpha values in the rectangle being 255 (the rest being alpha=127).
The issue I have is that the outputs are completely wrong. The first test case, which is a 5x5 black square with false coordinates, works fine. But the other test cases are actual pictures with 100x80 resolution. In those cases instead of a green rectangle, its random green lines and dots around the picture. The alpha value is simmilarly wrong, where its randomly 127 and randomly 255. I've tried rewriting my code several times, but the result is the same every time, just random values for alpha and G.
#include <stdio.h>
#define MAX 120
int main() {
FILE* fin = fopen("input.txt", "r");
FILE* fout = fopen("output.txt", "w");
int R[MAX][MAX], G[MAX][MAX], B[MAX][MAX], x1[MAX], y1[MAX], x2[MAX],
y2[MAX], A[MAX][MAX];
int h, w, n, i, j, k;
fscanf(fin, "%d %d %d", &n, &h, &w);
for (i = 0; i < n; i++) {
fscanf(fin, "%d %d %d %d", &x1[i], &y1[i], &x2[i], &y2[i]);
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &R[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &G[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fscanf(fin, "%d ", &B[i][j]);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
A[i][j] = 127;
}
}
for (k = 0; k < n; k++) {
for (i = x1[k]; i <= x2[k]; ++i) {
G[i][y1[k]] = 255;
G[i][y2[k]] = 255;
A[i][y1[k]] = 255;
A[i][y2[k]] = 255;
R[i][y1[k]] = 0;
R[i][y2[k]] = 0;
B[i][y1[k]] = 0;
B[i][y2[k]] = 0;
}
for (j = y1[k]; j <= y2[k]; ++j) {
G[x1[k]][j] = 255;
G[x2[k]][j] = 255;
A[x1[k]][j] = 255;
A[x2[k]][j] = 255;
R[x1[k]][j] = 0;
R[x2[k]][j] = 0;
B[x1[k]][j] = 0;
B[x2[k]][j] = 0;
}
}
for (k = 0; k < n; k++) {
for (i = x1[k] + 1; i <= x2[k] - 1; i++) {
for (j = y1[k] + 1; j <= y2[k] - 1; j++) {
A[i][j] = 255;
}
}
}
fprintf(fout, "/image %d %d RGBA\n", h, w);
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
fprintf(fout, "%d %d %d %d ", R[i][j], G[i][j], B[i][j], A[i][j]);
}
}
return 0;
}
I don't see anything wrong with the logic you have so I would step through your solution with testcases like yano suggested to see if you are having issues reading things in.
You do make the mistake of not setting the R and B values to 0 when you set the G value to 255 for the rectangle.
Next I would do two things: sanitize your inputs and simplify your loops.
For sanitizing your inputs just make sure that your with, height, and number of faces are less than your max. The coordinates you receive for each face rectangle should all be less than w and h, but greater than 0. Also double check that your face rectangles are always in the format of: [bottom-left x val, bottom-left y val, top-right x val, top-right y val] like you assume when you do all of these calculations. If there were an input problem here, that would be my guess at the most likely to cause hidden issues.
You can simplify your loops to avoid touching anything outside of your rectangles when coloring the Alpha and Green.
For the Green values, just loop over the sides. Loop through all of the faces (n) like you are doing, but just do:
for (i = x1[n]; i <= x2[n]; ++i) { G[i][y1[n]] = 255; G[i][y2[n]] = 255; // Also set A to 255 as well as R and B to 0 here }
for (j = y1[n]; j <= y2[n]; ++j) { G[x1[n]][j] = 255; G[x2[n]][j] = 255; // Also set A to 255 as well as R and B to 0 here }
And then cover the Alpha values inside the rectangle by looping from x1[n] + 1 to x2[n] - 1 and y1[n] + 1 to y2[n] - 1. This will not only make your program quicker, but should stop any erroneous green or alpha values to show up anywhere outside of your given points.
After fixing those things it should be much easier to debug and see where errors are when you get unexpected behavior.
Edit: I missed a case for input sanitation.

C 2D Arrays removing certain predetermined rows by shifting the ones below it

This is my first post here.
An assignment of my online course in C asked me to remove each row in a real(non dynamically allocated, pointers are not used) whose average sum is greater than the average sum of the whole matrix. The rows should be "removed" by shifting the ones below it up by one position.
I have set up a matrix with the following code:
int matrix[100][100]
Now, my idea was to create a regular 1D array which stores the indexes of the rows to-be-removed.
This is how I did it:
k = 0;
for (i = 0; i < no_of_rows; i++) {
average_sum_of_row = 0;
for (j = 0; j < no_of_columns; j++) {
average_sum_of_row += matrix[i][j];
}
average_sum_of_row = average_sum_of_row / no_of_columns;
if (average_sum_of_row > average_sum_of_matrix) {
indexes_of_rows_to_remove[k] = i;
k++;
l++;
}
}
Which works just fine! I get an array whose elements are the indexes of the rows which need to be removed. However, while implementing my code into the following:
m = 0;
for (i = 0; i < V; i++) {
if (indexes_of_rows_to_remove[m] == i) {
for (k = i; k < no_of_rows - 1; k++) {
for (j = 0; j < no_of_columns; j++) {
matrix[k][j] = matrix[k + 1][j];
}
}
i--;
no_of_rows--;
}
m++;
}
It does not work. What I used is my existing code of removing a row by shifting the ones below it up and decreasing the number of rows by one, but this simply doesn't work and I don't know why.
I tried using a separate integer(m) to go through all elements of the array of indexes, but for some reason it does not work.
Thanks all!
You can use this algorithm, which skips the rows to be deleted:
k = 0
For i in number of rows:
If i not to be deleted:
matrix[k] = matrix[i] # copy the whole row here
k++
The algorithm you are trying to implement is complicated and very inefficient.

Was told my C program was "hard coded" and I don't understand why

I turned in my assignment to my online C programming class and was docked huge due to the fact that my program was "hard coded, and I can't see how it would be considered "hard coded" as I ask for user input. The following was my code:
#include <stdio.h>
#include <stdlib.h>
#define IMAX 3
#define JMAX 4
int main()
{
float a[IMAX][JMAX];
float avgrow[5];
float avgcol[5];
int i,j;
char c;
printf ("This program will allow you to enter numbers for 3 rows and 4 columns from left to right then filling down, and take the averages of the rows and columns and list them next to the row and under the columns. You may use decimals but only 2 will display in the results. Press enter!\n");
scanf ("%c",&c);
printf("Enter 12 numbers here for your rows and columns:\n");
for(i = 0; i < IMAX; i++)
{
for(j = 0; j < JMAX; j++)
{
scanf("%f",&a[i][j]);
}
}
for(j = 0; j < JMAX; j++)
{
avgrow[0] = (a[0][0]+a[0][1]+a[0][2]+a[0][3])/JMAX;
avgrow[1] = (a[1][0]+a[1][1]+a[1][2]+a[1][3])/JMAX;
avgrow[2] = (a[2][0]+a[2][1]+a[2][2]+a[2][3])/JMAX;
}
for(i=0; i < IMAX; i++)
{
avgcol[0] = (a[0][0]+a[1][0]+a[2][0])/IMAX;
avgcol[1] = (a[0][1]+a[1][1]+a[2][1])/IMAX;
avgcol[2] = (a[0][2]+a[1][2]+a[2][2])/IMAX;
avgcol[3] = (a[0][3]+a[1][3]+a[2][3])/IMAX;
}
printf(" Column1 Column2 Column3 Column4 Row Average\n\n");
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[0][0],a[0][1],a[0][2],a[0][3],avgrow[0]);
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[1][0],a[1][1],a[1][2],a[1][3],avgrow[1]);
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[2][0],a[2][1],a[2][2],a[2][3],avgrow[2]);
printf("\n");
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t\n",avgcol[0],avgcol[1],avgcol[2],avgcol[3]);
return 0;
}
All it was supposed to do was make a 2-d array with 3 rows and 4 columns, then take the average of the rows and display that next to to the row in a table. Than take the average of the columns and display them beneath the columns in the table.
This was his comments on my assignment "Well, you got the correct answers, but when dealing with a 2-D array, you should use nested for loops. Not one for loop and then a lot of "hard coding" values into the program."
Any help deciphering this would be appreciated as I though I was finally understanding programming until this.
First of all it's not meaningful to talk about a program being hard coded or not. Rather one would talk about specific values being hard coded. What this means is that you wrote their values directly into the code rather than putting them in a constant or variable that can easily be changed.
In this case the values you hard-coded are the number of rows and the number of columns. You do have constants for these, but you don't use them consistently. That is if you changed your constants to turn the array into a 5x5 array, your code would now break because parts of the code would still act like it is an 3x4 array.
Specifically there are two loops in your code where you're accessing the indices [0][0] through [2][3] by spelling out each index in that range specifically rather than using a loop. This means that if you change IMAX and JMAX, it will still use those same indices, which aren't correct any more.
So your array indices are hard-coded and changing the array dimensions breaks your program.
for(j = 0; j < JMAX; j++)
{
avgrow[0] = (a[0][0]+a[0][1]+a[0][2]+a[0][3])/JMAX;
avgrow[1] = (a[1][0]+a[1][1]+a[1][2]+a[1][3])/JMAX;
avgrow[2] = (a[2][0]+a[2][1]+a[2][2]+a[2][3])/JMAX;
}
for(i=0; i < IMAX; i++)
{
avgcol[0] = (a[0][0]+a[1][0]+a[2][0])/IMAX;
avgcol[1] = (a[0][1]+a[1][1]+a[2][1])/IMAX;
avgcol[2] = (a[0][2]+a[1][2]+a[2][2])/IMAX;
avgcol[3] = (a[0][3]+a[1][3]+a[2][3])/IMAX;
}
Notice the copying/pasting of nearly identical code? That's often a sign of hardcoding -- the presence of constants in the code's text or structure. How do you change the 3 and the 4? They're "hard" -- built into the code.
The proof it's a problem -- you have:
#define IMAX 3
#define JMAX 4
But if you actually change those, the code will break. Look at this line of code:
avgrow[0] = (a[0][0]+a[0][1]+a[0][2]+a[0][3])/JMAX;
That's an average if, and only if, JMAX is 4. The code was build with the understanding that JMAX had to be 4 -- JMAX was "hard coded" to 4.
Looking at the following code:
for(j = 0; j < JMAX; j++)
{
avgrow[0] = (a[0][0]+a[0][1]+a[0][2]+a[0][3])/JMAX;
avgrow[1] = (a[1][0]+a[1][1]+a[1][2]+a[1][3])/JMAX;
avgrow[2] = (a[2][0]+a[2][1]+a[2][2]+a[2][3])/JMAX;
}
This code assumes that a always has 3 rows and 4 columns, regardless of how a was actually declared. If you changed JMAX to 2, for example, then your code above would break because a would have dimension 3x2, and you'd be attempting to access elements outside of the array bounds.
What your instructor was looking for was something along these lines:
for(j = 0; j < JMAX; j++)
{
float sum = 0.0;
for (i = 0; i < IMAX; i++ )
{
sum += a[i][j];
}
avgrow[j] = sum/JMAX;
}
This code makes no assumptions about the dimensions of a beyond what is specified by IMAX and JMAX.
Note also that your declarations for avgrow and avgcol are hard-coded to 5, when they should also be based on IMAX and JMAX:
float avgrow[IMAX];
float avgcol[JMAX];
float avgrow[5];
float avgcol[5];
for(j = 0; j < JMAX; j++)
{
avgrow[0] = (a[0][0]+a[0][1]+a[0][2]+a[0][3])/JMAX;
avgrow[1] = (a[1][0]+a[1][1]+a[1][2]+a[1][3])/JMAX;
avgrow[2] = (a[2][0]+a[2][1]+a[2][2]+a[2][3])/JMAX;
}
for(i=0; i < IMAX; i++)
{
avgcol[0] = (a[0][0]+a[1][0]+a[2][0])/IMAX;
avgcol[1] = (a[0][1]+a[1][1]+a[2][1])/IMAX;
avgcol[2] = (a[0][2]+a[1][2]+a[2][2])/IMAX;
avgcol[3] = (a[0][3]+a[1][3]+a[2][3])/IMAX;
}
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[0][0],a[0][1],a[0][2],a[0][3],avgrow[0]);
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[1][0],a[1][1],a[1][2],a[1][3],avgrow[1]);
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t%8.2f\n",a[2][0],a[2][1],a[2][2],a[2][3],avgrow[2]);
printf("\n");
printf("%8.2f\t%8.2f\t%8.2f\t%8.2f\t\n",avgcol[0],avgcol[1],avgcol[2],avgcol[3]);
THESE ALL STEPS YOU HAVE TAKEN ARE HARD CODING AS YOU ARE SPECIFICALLY MENTIONING THE INDICES IF SUPOSE the value imax and jmax changes then you have to manually change/add avgcol[index] in taking averages as well as in output...
Your programm should be independent of it it should only depend on the value of i max and jamx
for a reference you can view a sample of your code in which i have removed hardcoding
http://ideone.com/mXymKS
Although this code could be simplied to a great extent...
You have used explicit integer values for the array indices of avgrow and avgcol. To avoid hard-coding, try using a loop with an integer variable as index, e.g.,
for(int k=0; k<4; ++k)
and then assign values to avgrow[k].
Your professor expected you to be able to modify the number of line and columns in your program easily. The disadvantage of the program you wrote is that a modification of one of those two parameters require you to change the whole program. You can achieve more flexibility for instance like this:
#include <stdio.h>
#include <stdlib.h>
#define IMAX 3
#define JMAX 4
int main()
{
float a[IMAX][JMAX];
float avgrow[IMAX] = {0};
float avgcol[JMAX] = {0};
printf ("This program will allow you to enter numbers for %d rows"
"and %d columns from left to right then filling down, and"
" take the averages of the rows and columns and list them"
" next to the row and under the columns. You may use "
"decimals but only 2 will display in the results. Press"
" enter!\n", IMAX, JMAX);
char c;
scanf ("%c",&c);
printf("Enter %d numbers here for your rows and columns:\n", IMAX * JMAX);
for(int i = 0; i < IMAX; i++) {
for(int j = 0; j < JMAX; j++) {
scanf("%f",&a[i][j]);
}
}
for(int i = 0; i < IMAX; i++) {
for(int j = 0; j < JMAX; j++) {
avgrow[i] += a[i][j];
}
avgrow[i] /= JMAX;
}
for(int j = 0; j < JMAX; j++) {
for(int i = 0; i < IMAX; i++) {
avgcol[j] += a[i][j];
}
avgcol[j] /= IMAX;
}
for(int i = 0; i < IMAX; i++) {
printf("Column%d\t", i);
}
printf("Row-Average\n\n");
for(int j = 0; j < JMAX; j++) {
for (int i = 0; i < IMAX; i++) {
printf("%8.2f\t", a[i][j]);
}
printf("%8.2f\n", avgrow[j]);
}
for(int i = 0; i < IMAX; i++) {
printf("%8.2f\t", avgcol[i]);
}
return 0;
}
In addition to the rich answers already exist, I'd like to point out something about acquiring data and computing averages without much repetitions :
So define your average arrays like this :
float avgrow[IMAX] ={0};
float avgcol[JMAX] ={0};
Then in the same loop where you scanf user's entries you can simultaneously compute averages like this:
printf("Enter %d numbers here for your rows and columns:\n", IMAX*JMAX);
for(i = 0; i < IMAX; i++)
{
for(j = 0; j < JMAX; j++)
{
scanf("%f",&a[i][j]);
avgrow[i] += a[i][j]/JMAX;
avgcol[j] += a[i][j]/IMAX;
}
}
Next step is just to print out everything, and let it be automated too :)
for(i=1; i<= JMAX; i++) printf("Column%d\t\t", i);
printf("Row Average\n");
for(i=0; i<IMAX; i++)
{
for(j=0; j<JMAX; j++)
{
printf("%8.2f\t", a[i][j]);
}
printf("%8.2f\n", avgrow[i]);
}
for(i=0; i<JMAX; i++)
printf("%8.2f\t", avgcol[i]);
By the END
you have a code that computes row and col averages for any sizes. i.e. try changing IMAX or JMAX

Loop interchange versus Loop tiling

Which of these optimizations is better and in what situation? Why?
Intuitively, I am getting the feeling that loop tiling will in general
be a better optimization.
What about for the below example?
Assume a cache which can only store about 20 elements in it at any time.
Original Loop:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
a[i] += a[i]*b[j];
}
}
Loop Interchange:
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 10; j++)
{
a[j] += a[j]*b[i];
}
}
Loop Tiling:
for(int k = 0; k < 1000; k += 20)
{
for(int i = 0; i < 10; i++)
{
for(int j = k; j < min(1000, k+20); j++)
{
a[i] += a[i]*b[j];
}
}
}
The first two cases you are exposing in your question are about the same. Things would really change in the following two cases:
CASE 1:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
b[i] += a[i]*a[j];
}
}
Here you are accessing the matrix "a" as follows: a[0]*a[0], a[0]*a1, a[0]*a[2],.... In most architectures, matrix structures are stored in memory like: a[0]*a[0], a1*a[0], a[2]*a[0] (first column of first row followed by second column of first raw,....). Imagine your cache only could store 5 elements and your matrix is 6x6. The first "pack" of elements that would be stored in cache would be a[0]*a[0] to a[4]*a[0]. Your first acces would cause no cache miss so a[0][0] is stored in cache but the second yes!! a0 is not stored in cache! Then the OS would bring to cache the pack of elements a0 to a4. Then you do the third acces: a[0]*a[2] wich is out of cache again. Another cache miss!
As you can colcude, case 1 is not a good solution for the problem. It causes lots of cache misses that we can avoid changing the code for the following:
CASE 2:
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 1000; j++)
{
b[i] += a[i]*a[j];
}
}
Here, as you can see, we are accessing the matrix as it's stored in memory. Consequently it's much better (faster) than case 1.
About the third code you posted about loop tiling, loop tiling and also loop unrolling are optimizations that in most cases the compiler does automaticaly. Here's a very interesting post in stackoverflow explaining these two techniques;
Hope it helps! (sorry about my english, I'm not a native speaker)

Glitch initialising matrix in C

I am trying to create a matrix in C in order to solve the LaPlacian
However, this is going wrong. I have located the problem at the initialisation stage of the matrix. Every time the program is run, it places a seemingly random value in one element. This number changes each time suggesting an instability in the code, and happens if the matrix is made to be greater than 9x9.
Why could this be happening?
Thanks
The code I am using to show the matrix is:
// create matrix
double mat[meshno][meshno] = { {0} }; // x direction defined by i, y by j
//variables
int i, j, k;
//print initial matrix
for (i=0;i<=meshno;i++)
{
for(j=0;j<= meshno;j++)
{
printf("%f ", mat[i][j]);
}
printf("\n");
}
You are looking at an element past the end of each array.
Your for loops should use < and not <=:
for (i = 0; i < meshno; ++i)
{
for(j = 0; j < meshno; ++j)
{
Change to
for (i=0; i< meshno;i++)
{
for(j=0; j< meshno;j++)
{

Resources