I'm currently making a program for my school project. It's supposed to read a ppm image and return a gradient as an output. But I'm having a problem with large image such as 420 x 360. It works fine with image below 300 pixels on both side. Could anyone tell me what's wrong with my code? Thx. Oh and it's in C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct imageHeader{
char code[3];
char startComment;
char comment[1000];
int width;
int height;
int offset;
} header;
struct imagePixel{
int red;
int green;
int blue;
int total;
};
int main(){
FILE *image;
FILE *imageOut;
image = fopen("sunset.ppm", "rb");
imageOut = fopen("output.ppm", "wb");
fseek(image, 0, SEEK_SET);
fseek(imageOut, 0, SEEK_SET);
// ********* Get the right Code *************
fgets(header.code, sizeof(header.code), image);
if(strcmp(header.code, "P3")){
puts("Not suitable file format!");
}
fputs(header.code, imageOut);
fputs("\n", imageOut);
//*********** SKIP THE COMMENT IF EXIST *****************
header.startComment = fgetc(image);
if(header.startComment = '#'){
fgets(header.comment, sizeof(header.comment), image);
}
fputs(header.comment, imageOut);
//**************** Get the Width of the picture ***************
fscanf(image, "%d", &header.width);
fprintf(imageOut, "%d ", header.width);
//**************** Get the Height of the picture **************
fscanf(image, "%d", &header.height);
fprintf(imageOut, "%d\n", header.height);
//***************** Get the offset color of the picture ************
fscanf(image, "%d", &header.offset);
fprintf(imageOut, "%d\n", header.offset);
struct imagePixel *ptrOne;
ptrOne = (struct imagePixel*) malloc(sizeof(ptrOne) * header.height *header.width);
if (ptrOne == NULL){
printf("Error! Run out of memory!");
return 1;
}
struct imagePixel number[header.height][header.width];
//**************read the image*****************
for(int i = 0; i <= header.height - 1; i++){
for(int j = 0; j <= header.width - 1; j++){
fscanf(image, "%d", &number[i][j].red);
fscanf(image, "%d", &number[i][j].green);
fscanf(image, "%d", &number[i][j].blue);
number[i][j].total = (0.2126 * number[i][j].red) + (0.7152 * number[i][j].green) + (0.0722 * number[i][j].blue);
//number[i][j].total = (number[i][j].red) + (number[i][j].green) + (number[i][j].blue);
}
}
for(int i = 0; i <= header.height - 1; i++){
for(int j = 0; j <= header.width - 1; j++){
int axisXswap = i;
int axisYswap = j;
for(int x = i; x <= header.height - 1; x++){
for(int y = j; y <= header.width - 1; y++){
if(number[x][y].total > number[axisXswap][axisYswap].total){
axisXswap = x;
axisYswap = y;
}
}
}
struct imagePixel temp;
temp.red = number[i][j].red;
temp.green = number[i][j].green;
temp.blue = number[i][j].blue;
temp.total = number[i][j].total;
number[i][j].red = number[axisXswap][axisYswap].red;
number[i][j].green = number[axisXswap][axisYswap].green;
number[i][j].blue = number[axisXswap][axisYswap].blue;
number[i][j].total = number[axisXswap][axisYswap].total;
number[axisXswap][axisYswap].red = temp.red;
number[axisXswap][axisYswap].green = temp.green;
number[axisXswap][axisYswap].blue = temp.blue;
number[axisXswap][axisYswap].total = temp.total;
}
}
for(int i = 0; i <= header.height-1; i++){
for(int j = 0; j <= header.width-1; j++){
fprintf(imageOut, "%d %d %d\n", number[i][j].red, number[i][j].green, number[i][j].blue);
}
}
fclose(image);
fclose(imageOut);
}
Instead of allocating on the stack you should use the heap:
struct imagePixel **number; // two dimensional array of pixels
// allocate rows
number = malloc(sizeof(struct imagePixel *) * header.height);
for (i = 0; i < header.height; ++i) {
// allocate columns for each row
number[0] = malloc(sizeof(struct imagePixel) * header.width);
}
// do free() in reverse as above
Related
I want to change my color image file to grayscale image file.
I can't use OPENCV and other library.
My code algorithm is like this.
T[3] = {0.299, 0.589, 0.114}
N = size of vertical
M = size of horizontal
for j = 1 ~ N
{
for i = 1 ~ M
Writebuf[i][j] = Readbuf[0][i+M][i] * T[0] + Readbuf[1][i+M][i] * T[1] + Readbuf[2][i+M][i] * T[2]
}
This is my code following algorithm.
#include <stdio.h>
#pragma warning(disable:4996)
int main() {
FILE* fp;
double T[3] = { 0.299, 0.587, 0.114 };
int N = 374;
int M = 374;
int i = 0;
int j = 0;
unsigned char Readbuf[374][374];
unsigned char Writebuf[374][374];
fp = fopen("lena_color.bmp", "rb");
if (fp == NULL)
printf("FIle Read Error");
for (i = 0; i < N; i++)
fread(Readbuf[i], 1, N, fp);
fclose(fp);
for (i = 0; i < N; i++)
{
for (j = 0; j < M; j++)
{
Writebuf[j][i] = Readbuf[0][j + M][i] * T[0] + Readbuf[1][j + M][i] * T[1] + Readbuf[2][j + M][i] * T[2];
}
}
fp = fopen("111.bmp", "wb");
for (i = 0; i < 374; i++);
fwrite(Writebuf[i], 1, 374, fp);
fclose(fp);
return 0;
}
It doesn't save image
Please help me.
I am using eclipse 3.2020 on WIN10 and I have a problem executing my main function.
When I run the program as it is, I get no output to conole, even when I add a printf in the first line, and the exit code is -1,073,741,819. When I comment out/ delete the line solve(s); the code run as intended and gives exit code 0.
Edit: added full code (both solve and print_sol are in solver.c)
Edit 2: As mentioned in the comments, the problem was in the code (bug) and not eclipse, I just assumed that an error message will be printed if there is one.
p.s.: I still find the fact a printf in the start won't print if there is a runtime error in another part of the main function quite weird.
main.c:
#include "solver.h"
#include <stdlib.h>
int main(int argc, char** argv){
int **grid = (int**) malloc(sizeof(int*) * 4);
for (int i = 0; i < 4 ; i++){
grid[i] = (int*) malloc(sizeof(int) * 4);
}
int mat[4][4] = {{1,0,3,0}
,{2,0,0,0}
,{3,0,0,0}
,{4,2,0,0}};
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
grid[i][j] = mat[i][j];
}
}
solver *s = create_solver(4, &grid);
solve(s);
print_sol(s);
}
solver.h:
#ifndef SOLVER_H_
#define SOLVER_H_
typedef struct sudoku_solver solver;
/*creates a new solver using the length of one row of the board.
*Then, the user will follow the instructions on screen to input the board*/
solver* create_solver(int row_len, int ***input_board_ptr);
/*if solver is NULL, an error will appear.
*Otherwise, The board that was given won't be changed, and neither
*the solver nor the solution (unless saved before using get_sol)
*will be accessible after this*/
void destroy_solver(solver *solver);
/*if solver is NULL, an error will appear.
*Otherwise, it will solve the inputed board*/
void solve(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, it will print a solution to the inputed board*/
void print_sol(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, returns a solution to the inputed board as a matrix of integers*/
int** get_sol(solver *solver);
#endif /* SOLVER_H_ */
solver.c:
#include "solver.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
/*the board will be represented by an array of size NxN.
*the value of every board cell is between 0 and N when 0
*means "default value"*/
typedef struct sudoku_solver{
/*length of one row of the board*/
int N;
/*a pointer to the solution board*/
int ***sol_ptr;
}solver;
solver* create_solver(int row_len, int ***input_board_ptr){
solver *s = (solver*) malloc(sizeof(solver));
/*throw an ERROR if the malloc failed*/
/*row_len is a variable, so we have to declare everything dynamically */
/*allocating the sol matrix as an array of pointers (1 out of 2D)*/
int **sol = (int**) malloc(row_len * sizeof(int*));
for (int i = 0; i < row_len; i++){
/*allocating every row (the second D)
*while making sol equal to input_board*/
sol[i] = (int*) malloc(row_len * sizeof(int));
for (int j = 0; j < row_len; j++){
sol[i][j] = (*input_board_ptr)[i][j];
}
}
s->N = row_len;
/*if row_len != pow(sqrt(row_len),2) then throw invalid input ERROR*/
s->sol_ptr = /
return s;
}
void destroy_solver(solver *s){
for (int i = 0; i < s->N; i++){
free((*(s->sol_ptr))[i]);
}
free(*(s->sol_ptr));
free(s->sol_ptr);
free(s);
}
int* calc_next(int x, int y, int *next, solver *s);
bool isSafe(int x, int y, int val, solver *s);
bool solve_rec(int x, int y, solver *s);
void solve(solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0){
next[0] = 0;
next[1] = 1;
}
else{
calc_next(0, 0, next, s);
}
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
printf("no sol");
return;
}
bool solve_rec(int x, int y, solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
if (x == n - 1 && y == n - 1){
return true;
}
//find next empty space
calc_next(x, y, next, s);
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return true;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
return false;
}
bool isSafe(int x, int y, int val, solver *s){
int n = s->N;
int ***sp = s->sol_ptr;
/*check row*/
for (int j = 0; j < n; j++){
if ((*sp)[x][j] == val){
return false;
}
}
/*check col*/
for (int i = 0; i < n; i++){
if ((*sp)[i][y] == val){
return false;
}
}
/*check block
*the index of a block in a grid is just like the index of entry in block.
*In sudoku, there are bs*bs blocks, and each has bs rows and bs columns*/
int bs = sqrt(n); // block size
int block_x_index = x / bs;
int block_y_index = y / bs;
for(int i = block_x_index * bs; i < bs * (block_x_index + 1); i++){
for(int j = block_y_index * bs; j < bs * (block_y_index + 1); j++){
if ((*sp)[i][j] == val){
return false;
}
}
}
return true;
}
/*assuming x,y is not the last place in the grid,
* finds the next empty place after it*/
int* calc_next(int x, int y, int *next, solver *s){
int n;
int ***sp = s->sol_ptr;
/*find the first empty place*/
do{
n = s->N;
if (y == n - 1){
x++;
y = 0;
}
else{
y++;
}
}while ((*sp)[x][y] != 0);
next[0] = x;
next[1] = y;
return next;
}
void print_sol(solver *s){
int n = s->N;
int bs = sqrt(n); // block size
char curr;
int rows_passed, col_passed;
for (int i = 0; i < n + bs - 1; i++){
for (int j = 0; j < n + bs - 1; j++){
//if it's a grid row
if (i == bs || ((i - bs) % (bs + 1)) == 0){
//if it's also a grid col
if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '+';
}
else{
curr = '-';
}
}
//if it's only a grid col
else if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '|';
}
else{
rows_passed = i / (bs + 1);
col_passed = j / (bs + 1);
curr = '0' + (*(s->sol_ptr))[i-rows_passed][j-col_passed];
}
printf("%c",curr);
}
printf("\n");
}
}
int** get_sol(solver *solver){
return *(solver->sol_ptr);
}
Thank you.
Please learn how to use your debugger. In this case, it would take you directly to the problem: you're crashing with an access violation (Windows 0xc0000005) here:
void solve(solver *s) {
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0) { // <-- Access violation here: "sp" incorrectly initialized!
next[0] = 0;
next[1] = 1;
}
The underlying problem is that although sudoku_solver.N was initialized to "4" ... sudoku_solver.sol_ptr[0][0] is pointing to uninitialized memory.
PS:
Yes, it's very definitely "executing". It wouldn't crash if it didn't run ;)
Firstly, I am sorry for my English.
I am trying to read an integer array which represents some sparse matrix from a binary and I have to print this matrix.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
//on this way i have written the matrix in the binary
typedef struct{
int lin,col;
double val;
}termen;
typedef struct{
int nl,nc,nn;
termen* term;
}sparse_matrix;
void afisare_mat(sparse_matrix m){
int i,j,k = 0;
for(i = 0; i < m.nl; i++){
for(j = 0; j < m.nc; j++){
if(i == m.term[k].lin && j == m.term[k].col){
printf("%3.2lf ",m.term[k].val);
k++;
}else{
printf("%d ",0);
}
}printf("\n");
}
}
int main(){
/*this is the code used for write in the binary file
//i tried to print these values and seems to be ok
sparse_matrix m1,m2,m3;
m1.term = malloc(2*sizeof(termen));
m1.nl = 3;
m1.nc = 3;
m1.nn = 2;
m1.term[0].lin = 0;
m1.term[0].col = 1;
m1.term[0].val = 3.2;
m1.term[1].lin = 1;
m1.term[1].col = 2;
m1.term[1].val = 5.6;
afisare_mat(m1);
m2.term = malloc(3*sizeof(termen));
m2.nl = 4;
m2.nc = 4;
m2.nn = 3;
m2.term[0].lin = 0;
m2.term[0].col = 0;
m2.term[0].val = 1.9;
m2.term[1].lin = 1;
m2.term[1].col = 2;
m2.term[1].val = 0.5;
m2.term[2].lin = 2;
m2.term[2].col = 3;
m2.term[2].val = 6.960;
afisare_mat(m2);
m3.term = malloc(1*sizeof(termen));
m3.nl = 3;
m3.nc = 3;
m3.nn = 1;
m3.term[0].lin = 1;
m3.term[0].col = 2;
m3.term[0].val = 6.75;7
afisare_mat(m3);
FILE *f = fopen("in.bin","wb");
fwrite(&m1,sizeof(sparse_matrix),1,f);
fwrite(&m2,sizeof(sparse_matrix),1,f);
fwrite(&m3,sizeof(sparse_matrix),1,f);
fclose(f);
*/
FILE *f = fopen("in.bin","rb");
int n, v[10], i, j, k,nr = 0,it; //n=number of matrix asked, v=array with
//number(s)(<= n) of matrix which have to print
scanf("%d",&n);
sparse_matrix m;
while(fread(&k,sizeof(int),1,f) > 0){
fseek(f,2*sizeof(int),SEEK_CUR);
fseek(f,sizeof(termen*),SEEK_CUR);
nr++;
}
for(i = 0; i < n; i++){
scanf("%d",&v[i]);
if(v[i] > nr)
printf("That matrix not exist\n");
}
fseek(f,0,0);
j = 0;
while(fread(&k,sizeof(int),1,f) > 0){ //citesc nl din fiecare matrice
for(i = 0; i < n; i++){
if(j == v[i]){ //number of matrix which i read;
//print matrix
m.nl = k;
fread(&m.nc,sizeof(int),1,f);
fread(&m.nn,sizeof(int),1,f);
m.term = malloc(m.nn*sizeof(termen));
fread(m.term,sizeof(termen),m.nn,f);
afisare_mat(m);
free(m.term);
fseek(f,(j+1)*sizeof(sparse_matrix),0);
}
}j++;
}
fclose(f);
return 0;
}
This code prints on my screen the form of matrix but full of zeroes. I think that the rest of the elements (!= 0) aren't read ok from the binary file. Can you help me, please?
I have written a program in C. The problem is when I compile this program in a Linux/Unix environment I get a segfault. But when I compile it in Windows with minGW It works fine. Basically in the program I have a multidimensional array. When I compile and debug in gdb in Linux/Unix I lose one row of the multidimensional array randomly. When I try to access every column in that row all of them suddenly cannot be accessed. My whole row gets lost.
Error:Program received signal SIGSEGV, Segmentation fault.
Note: isItDone(), oneToTwo(), and checkAroundTwo() are very likely not the problem. I tried running program without them and it still showed the error.
The code:
int main( int argc, char *argv[] ){
FILE * output;
output = fopen("output.txt", "w");
srand(time(NULL));
int size = 0; // Resetting before taking arguments
int evaltime = 0; // Resetting before taking arguments
int rand1, rand2;
int counter, counter2, counter3;
if(argc == 3){
size = atoi(argv[1]);
evaltime = atoi(argv[2]);
}
else{
return 0;
}
double *evaltimes = (double*)calloc(evaltime , sizeof(double)); // The array of the results we got.
for(counter2 = 0; counter2 < evaltime; counter2++){
int cellnumbers = 0;
int **ground = (int**)malloc(size * sizeof(int)); //Mallocating for every iteration
for(counter = 0; counter < size; counter++){
ground[counter] = (int*)calloc(size, sizeof(int)); // Initializing all the 0.
}
while(!isItDone(ground, size)){ // It's finished when last row is 2.
rand1 = rand() % size;
rand2 = rand() % size; // Take two random numbers for picking in array limit.
printf("%d %d\n", rand1, rand2);
if(rand1 == 0){ // Is it a top cell
if(ground[rand1][rand2] == 0){
ground[rand1][rand2] = 2;
cellnumbers++; // Increment when a cell is picked.
}
}
else{
if(ground[rand1][rand2] == 1 || ground[rand1][rand2] == 2) // The cell is already opened
continue;
else{
ground[rand1][rand2] = 1; // Defaulting to 1 before control
cellnumbers++;
oneTotwo(ground, size, rand1, rand2);
}
}
}
if(counter2 == evaltime - 1){ // Printing the last variation
for(counter3 = 0; counter3 < size; counter3++){
for(counter = 0; counter < size; counter++){
fprintf(output, "%d ",ground[counter3][counter]);
}
fprintf(output, "\n");
}
}
evaltimes[counter2] = (double)cellnumbers / (double)(size*size);
for(counter = 0; counter < size; counter++)
free(ground[counter]);
free(ground);
}
double meany = mean(evaltimes, evaltime);
double stddeviation = stddev(evaltimes, evaltime, meany);
fprintf(output, "mean() = %f \n", meany);
fprintf(output, "stddev() = %f",stddeviation);
fclose(output);
return 0;
}
I think the bug is most likely lies in main but here are my functions.
int isItDone(int **p, int size){
int counter;
for(counter = 0; counter < size; counter++){
if(p[size - 1][counter] == 2 && (p + size - 1) != 0)
return 1;
}
return 0;
}
void oneTotwo(int **p, int size, int rand1, int rand2){
//Checking the Upper Cells
if(rand1 < size - 1){ // Making sure no control if it is the last cell.
if(p[rand1 + 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
}
void checkAroundTwo(int **p, int size, int rand1, int rand2){
if(rand1 < size - 1){
if(p[rand1 + 1][rand2] == 1){
p[rand1 + 1][rand2] = 2;
checkAroundTwo(p, size, rand1 + 1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 1){
p[rand1 - 1][rand2] = 2;
checkAroundTwo(p, size, rand1 - 1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 1){
p[rand1][rand2 + 1] = 2;
checkAroundTwo(p, size, rand1, rand2 + 1);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 1){
p[rand1][rand2 - 1] = 2;
checkAroundTwo(p, size, rand1, rand2 - 1);
}
}
}
double mean(double *p, int size){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += p[counter];
return sum / (double)(size);
}
double stddev(double *p, int size, double mean){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += sqr(((double)p[counter] - mean));
return sqrt(sum / (double)(size - 1));
}
double sqr(double x){
return x*x;
}
double sqrt(double x){
int counter = 0;
while(sqr(counter) < x){
counter++;
}
double s = counter;
for(counter = 0; counter < 50; counter++){
s = (double)1/2 * (double)(s + x/s);
}
return s;
}
Let's assume int array[10][10]
One more weird thing is that in gdb when I for example lose array[5] row I try to access it from the row before it. For example with array[4][10]. When I do it "array[4][10] = 49". Why is this? Rest is (array[4][12], array[4][13] etc.) is 0 as I specified. Why suddenly the first element of the 5th row achieved from the 4th row becomes 49 ? That I dont understand.
When you assign memory to a 2D array, you're assigning an array of pointers, each of which points to a block of memory.
This means when you do your initial malloc you need to assign ...sizeof(int*) and not ...sizeof(int).
In short, change this line:
int **ground = (int**)malloc(size * sizeof(int));
to:
int **ground = (int**)malloc(size * sizeof(int*));
I am new to C and wondering why I am not getting any kind of output. I am trying to get my program to convert a hexadecimal number to binary.
#include <stdio.h>
#include <stdlib.h>
int* hex2binary(int hex_array[], int input_array_size, int* return_array_size) {
int hex_size = input_array_size;
int binary_array_size = 4 * hex_size;
int *binary_array = (int*) malloc(binary_array_size * sizeof(int));
int hex_index, binary_index;
for (hex_index = 0; hex_index < hex_size; hex_index++) {
int hex_num = hex_array[hex_index];
binary_index = hex_index * 4;
int bit_count;
for (bit_count = 3; bit_count <= 0; bit_count--) {
binary_array[binary_index + bit_count] = hex_num % 2;
hex_num = hex_num / 2;
}
hex_index++;
}
*return_array_size = binary_array_size;
return binary_array;
}
int main() {
char baseString[11];
int count = 0;
int i, j;
int original, wanted;
int size;
printf("Welcome to use this number base converter program.\n");
printf("Please input the original base: ");
scanf("%d", &original);
printf("Please input a base-%d number with more more than 10 digits: ",
original);
scanf("%s", baseString);
while (baseString[count] != '\0')
count++;
int *baseNumber = (int*) malloc(count * sizeof(int));
for (i = 0; i < count; i++) {
baseNumber[i] =
baseString[i] <= '9' ? baseString[i] - '0' : baseString[i] - 'A' + 10;
}
int* result_array;
printf("Please input the target base: ");
scanf("%d", &wanted); //doesn't read anything past this point
printf("Target base: %d", wanted);
if (original == 16) {
if (wanted == 2) {
result_array = hex2binary(baseNumber, count, size);
for (j = 0; j < size; j++) {
printf("Result: %d", result_array[j]);
}
}
}
}
I know it can't be something to difficult, but I can't seem to figure out why it isn't even producing some kind of output.
This line
result_array = hex2binary(baseNumber, count, size);
is incorrect because this function needs a pointer argument
int* hex2binary(int hex_array[], int input_array_size, int* return_array_size)
So it should be called like this
result_array = hex2binary(baseNumber, count, &size); // note the &
Then the subsequent loop
for (j = 0; j < size; j++)
will no longer be using the uninitialised variable size.