Writing an image to a text/raw file in C - c

#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char **T;
int H[256];
int I[256][256];
int i,j,a,aux[256];
FILE *fp=fopen("Collines400300.ima","rb");
FILE *fp1=fopen("image4.raw","wb");
int height = 300;
int width = 400;
T=(unsigned char**)malloc(height*sizeof(unsigned char*));
for(i=0;i<height;i++)
{
if (feof(fp))
{
//handle error... could just malloc and memset to zero's
break;
}
T[i]=(unsigned char*)malloc(width*sizeof(unsigned char*));
fread(T[i],1,400,fp);
}
for(i=0;i<256;i++)
H[i]=0;
//filling up the histogram
for(i=0;i<300;i++)
{
for(j=0;j<400;j++)
H[T[i][j]]++;
}
//printing out the values of each gray scale value in the histogram
for(i=0;i<256;i++)
printf("%d ",H[i]);
//converting the values from a scale of 3000 to a scaale of 256 to fit in our new image
for(i=0;i<256;i++)
{
a=(H[i]+6)/12;
aux[i]=a;
}
//initialising the 2D image to white
for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
I[i][j]=255;
}
//the loop to make the graph for my histogram. This is where the problem is.
for(i=0;i<256;i++)
{
for(j=254;j>254-aux[i];j--)
{
I[j][i]=0;
fwrite(I[i],1,aux[i],fp1);
}
}
fclose(fp);
fclose(fp1);
return 0;
}
Given an image I am supposed to make a histogram of the image, which I did. Then make a graph of the histogram in a 2D image and write it to a file. I am not getting the graph I want, but a very blurry image with no sense to it. Thank you for any help beforehand.

I[j][i]=0; fwrite(I[i],1,aux[i],fp1); Did you mean to write the column row to file here? It doesn't work that way. You are modifying an element in (column number i) row number j in memory and then writing row number i to file.

Related

How to find overlap in a linearized 64x64 array

I am working with a linearized 64x64 array. There are either horizontal or vertical lines with "colors" in them set as color codes in each spot in the array, and I am trying to find the color that has no overlap.
An example of what I mean is here: https://imgur.com/a/geE73aK
It is clear that in this example, since none of the yellow are overlapped by any other colors, yellow's color code would be the solution.
It checks left/right and above/below the current position to see if the color is the same. If the color is the same, it will continue. If the color is different (AKA overlap is found), it will make that color code zero and by the end of the program all but one color code will be zero, making it easy to find the non-zero (AKA non-overlapping) color code.
I currently have this as my code. I am stuck on how to find if there is overlap and make the overlapping color code 0. Any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#define DEBUG 1 // RESET THIS TO 0 BEFORE SUBMITTING YOUR CODE
int main(int argc, char *argv[]) {
int PileInts[1024];
int NumInts, TopColor=0;
int Load_Mem(char *, int *);
// This allows you to access the pixels (individual bytes)
// as byte array accesses (e.g., Pile[25] gives pixel 25):
char *Pile = (char *)PileInts;
if (argc != 2) {
printf("usage: ./P1-1 valuefile\n");
exit(1);
}
NumInts = Load_Mem(argv[1], PileInts);
if (NumInts != 1024) {
printf("valuefiles must contain 1024 entries\n");
exit(1);
}
if (DEBUG){
printf("Pile[0] is Pixel 0: 0x%02x\n", Pile[0]);
printf("Pile[107] is Pixel 107: 0x%02x\n", Pile[107]);
}
/* Your program goes here */
int i;
int j;
/*
int black = 0;
int pink = 1;
int red = 2;
int green = 3; // all colors and their codes
int blue = 4;
int orange = 5;
int yellow = 6;
int skyblue = 7;
*/
int rows = 63;
int cols = 63;
int colors[] = [1, 2, 3, 4, 5, 6, 7]; // color codes in array format
int current = Pile[i*64 + j]; //current position in linearized 64x64 array
for (i=1; i<63; i++){ //run through 63 rows
for (j=1; j<63; j++){ //run through 63 columns
// CHECK HORIZONTAL OVERLAP
if (current == Pile[i*64+j+1]) //check to the right current position
if (current == Pile[i*64+j-1]) //check to the left current position
// CHECK VERTICAL OVERLAP
if (current == Pile[(i-1)*64+j]) //check above current position
if (current == Pile[(i+1)*64+j]) //check below current position
}
}
//CHECK FOR COLORS WHICH DID NOT OVERLAP - THAT WILL BE SOLUTION, AS THERE SHOULD ONLY BE ONE
for (int k=0; k<8; k++){
if colors[k] != 0 {
TopColor = k;
}
}
}
As for it running from 1-63, that is okay. There will be no colors along the borders.
Clarifying information about the specifics: There will only be one line in each vertical and horizontal. each vertical or horizontal line will be at least one row/column from the other. There will be exactly one color that does not overlap.

Retrieving an array from a file and find it's size C

I have a file that I have to read some numbers from and put them into an array. The only problem is that I don't know how to find the size of it. I am given the maximum size of the array but the numbers don't fill the array completely. I tried many different ways to make it work but it doesn't read the correct values from the file. Is there any other way to do it without sizeof?
#include<stdio.h>
#define MAX_NUMBER 25
int main(void)
{
int test[];
int size;
FILE* sp_input;
int i;
sp_input = fopen("a20.dat", "r");
if (sp_input == NULL)
printf("\nUnable to open the file a20.dat\n");
else
{
while( fscanf(sp_input, "%d", &test[i])!=EOF)
{
size=sizeof(test)/sizeof(test[0]);
}
for(i = 0; i < size; i++)
printf("\na[%d]=%d has a size of %d\n", i,test[i],size);
fclose(sp_input);
}
return 0;
}
If you increment i each time you successfully do a fscanf, it will serve as a count of the number of items read.
i = 0;
while (fscanf(sp_input, "%d", &test[i]) == 1) {
i = i + 1;
}
// Now, i is the number of items in the list, and test[0] .. test[i-1]
// are the items.
Edit: As #chux pointed out, in this case it's better to compare to 1, the expected number of items scanned, on each call. If a bogus input is provided (non-digits), there's still a problem and you should stop.
Define a maximum size array and continue looping as able.
File input need not fill the array, just populate it as it can. Keep track, i, of how many of test[] was used and be sure not to overfill the array.
#define MAX_NUMBER 25
int test[MAX_NUMBER];
FILE* sp_input = fopen("a20.dat", "r");
...
// Use `size_t` for array indexing
size_t i;
// do not read too many `int`
for (i=0; i<MAX_NUMBER; i++) {
if (fscanf(sp_input, "%d", &test[i]) != 1) {
break;
}
printf("test[%zu]=%d\n", i, test[i]);
}

Enlarging bitmap in c

The following code takes in a bmp and enlarges it, rotates it or flips it. Everything is working properly except when i call the enlarge command line. the pictures comes up but it does not look any bigger.
This is the enlarge funtions:
int enlarge(PIXEL* original, int rows, int cols, int scale,
PIXEL** new, int* newrows, int* newcols)
{
int row, col, i, j;
if((rows<=0)|| (cols<=0))
{
return -1;
}
*newrows=rows * scale;
*newcols=cols * scale;
*new=(PIXEL*)malloc((scale*rows)*(scale*cols)*sizeof(PIXEL));
for(row=0;row<rows;row++)
{
for(col=0;col<cols;col++)
{
PIXEL *o=original + row*cols +col;
for(j=0; j<scale;j++)
{
for(i=0; i<scale;i++)
{
PIXEL *n=(*new)+(row*scale+i)*(*newcols)+(col*scale+j);
*n=*o;
}
}
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
and this is the main function:
int degree, scale;
int is_rotate=0, is_scale=0, is_flip=0;
char *inputFile=NULL, *outputFile=NULL;
int r, c, check;
PIXEL *b, *nb;
int nr,nc;
int error;
//readFile("example.bmp",&r,&c,&b);
while((check=getopt(argc,argv,"s:r:o:f")) != -1)
{
switch (check)
{
case 's':
is_scale=is_scale+1;
//enlarge(nb,nr,nc,optarg,&nb,&nr,&nc);
scale=atoi(optarg);
if(is_scale==2)
{
printf("bmptool: -s: scale can only be called once in commmand line");
error=1;
}
if(scale<0)
{
printf("bmptool: -s : the scale must be a positive integer");
error=1;
}
//printf("This is working s");
break;
case 'r':
is_rotate= is_rotate+1;
//rotate(b,r,c,optarg,&b,&r,&c);
degree=atoi(optarg);
if(is_rotate==2)
{
printf("bmptool: -r: rotation can only be called once in commmand line");
error=1;
}
if(degree%90 != 0)
{
printf("bmptool: -r: the degree of rotation must be a multiple of 90");
error=1;
}
//printf("this is working r");
break;
case 'f':
is_flip=is_flip+1;
if(is_flip==2)
{
printf("bmptool: -f: flip can only be called once in command line");
}
break;
case 'o':
outputFile=(optarg);
//printf(outputFile);
//readFile(outputFile,&r,&c,&b);
break;
}
}
if(error==1)
{
return 0;
}
if(is_rotate==0 && is_scale==1 && is_flip==0)
{
enlarge(nb,nr,nc,scale,&nb,&nr,&nc);
writeFile(inputFile,r,c,b);
}
I only added the if statement that contains the enlarge. Thanks in advance for the help.
Try this:
int enlarge(PIXEL* original, int rows, int cols, float scale,
PIXEL** enlarged, int* newrows, int* newcols)
{
int row, col;
if((rows<=0)|| (cols<=0))
{
return -1;
}
(*newrows)=(int)((float)rows * scale);
(*newcols)=(int)((float)cols * scale);
*enlarged=(PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for(row=0;row<(*newrows);row++)
{
for(col=0;col<(*newcols);col++)
{
(*enlarged)[row * (*newcols) + col] = original[(row * rows / (*newrows)) * cols + col * cols / (*newcols)];
}
}
/* THIS IS THE METHOD THAT YOU SHOULD WRITE */
return 0;
}
NOTE: i change scale type to float in order to you could scale in any factor, but you could change to int with any problem
You must pass newrows and newcols by ref (not pointer)
EDIT: function usage
scale = 2.0f;
readFile("example.bmp",&r,&c,&b);
enlarge(b,r,c,scale,&nb,&nr,&nc);
writeFile("enlarge.bmp",nr,nc,nb);
free(nb);
If this is a standard Windows bitmap, then newrows must be of a scanline size. A bitmap image consists of scanlines. A scanline consists of pixels. A pixel consists of one or more components (colors).
A scanline must be a multiple of 4 bytes. So after the last component of the last pixel of a scanline, there may follow some unused bytes.
So your scaled bitmap must have scanlines of the appropriate size. See also
Dealing with padding in a BMP file in C of how to calculate scanline sizes and iterate over an image.
Note also that if you just "scale" with an integer, you can scale 1, 2, 3... integer times (100%, 200%,...). Scaling with non-integers requires smearing the pixels out over the new width and hight. Numerous algorithms and ready-to-use code are available on the internet.

Using recursion to print strings in C

Let me start with saying I am not looking for someone to do this for me. I am hoping for a hint or suggestion.
I know there is a smarter way to do this. Code is posted below. I am trying to print an outline. My code works up to a depth of 3. (The depth is the number of subsections - so 3 would be section 1, section 1.A, and section 1.A.1). It also works for a width (number of sections and each type of subsection) of 26, where it is capped. However, to get a larger depth, it would involve many more loops. Not only is that terrible code, it also freezes up the terminal I'm working on.
I believe recursion would make it much nicer, but I'm struggling to grasp the idea when using a string (I understand when it is a number).Thanks!
#include <stdio.h>
int sec(int width, int snum) {
char section[100];
sprintf(section, "Section ");
printf("%s %i", section, snum);
return 0;
}
int ssec_num(int width, int i) {
char num[100];
sprintf(num, "%i", i);
printf(".%s", num);
}
int ssec_let(int width, char z) {
char let[100];
sprintf(let, ".%c", z);
printf("%s", let);
}
int main(int argc, char* argv[]) {
int depth = atoi(argv[1]);
int width = atoi(argv[2]);
int sec_int=1;
int sec_wid = width;
int let_wid;
int num_int;
int num_dep;
int num_wid;
int dep;
char z = 'A';
while(sec_wid > 0) {
sec(width, sec_int);
let_wid = width;
dep = depth-1;
printf("\n");
while(dep > 0) {
while(let_wid > 0) {
num_wid = width;
num_int = 1;
sec(width, sec_int);
ssec_let(let_wid, z);
printf("\n");
num_dep = depth-2;
while(num_dep > 0) {
while(num_wid > 0) {
sec(width, sec_int);
ssec_let(let_wid, z);
ssec_num(width, num_int);
num_wid--;
num_int++;
printf("\n");
num_dep--;
}
}
let_wid --;
z++;
}
dep --;
}
sec_int++;
sec_wid--;
z = 'A';
}
}
If depth is 3 and width is 2 then it would be
Section 1
Section 1.A
Section 1.A.1
Section 1.A.2
Section 1.B
Section 1.B.1
Section 1.B.2
Section 2
Section 2.A
Section 2.A.1
Section 2.A.2
Section 2.B
Section 2.B.1
Section 2.B.2
The algorithm you described uses a width to declare how many times each (sub)section is repeated. This kind of repetition you can achieve with a loop.
The algorithm also uses a depth to determine how many (sub)sections you have. Here is the tricky part, and you can use recursion to solve it. A recursive function is basically a function that calls itself a limited number of times. There must always be a condition to stop the recursion, otherwise the function would call itself until the call stack overflows, abnormally stopping the program execution.
For your problem, you can have a function that receives a counter, that determines at with (sub)section depth it currently is. It would loop width times (as described above) and call itself depth times, until the counter reaches the value of depth. This way, you'll have a function that has a depth number of (sub)sections, each with a width number of items.
As you need to print the (sub)sections at the previous depths, you can use a buffer to store the section values at each depth, like int buffer[MAX_DEPTH];, with #define MAX_DEPTH 100 to set the maximum depth your program supports.
Then you'll have something like
#include <stdio.h>
#define MAX_DEPTH 100
void print_section(const int *const buffer, const int current_depth) {
// print all the (sub)section values stored at the buffer so far
// use a loop like for (i = 0; i <= current_depth; i++)
}
void recursive(int *const buffer, const int current_depth,
const int depth, const int width) {
if (current_depth < depth) {
// continue recursion
int current_width;
for (current_width = 1; current_width <= width; current_width++) {
buffer[current_depth] = current_width;
print_section(buffer, current_depth);
recursive(buffer, current_depth + 1, depth, width);
}
}
// else stop recursion
}
int main(int argc, char* argv[]) {
// ...
int buffer[MAX_DEPTH];
recursive(buffer, 0, depth, width);
return 0;
}
You'll also need some extra logic to determine when to print a letter or a number at each (sub)section depth.
EDIT: To print the (sub)section title just use the following
void print_section(const int *const buffer, const int current_depth) {
int i;
printf("Section ");
for (i = 0; i <= current_depth; i++) {
printf(i == 0 ? "%i" : ".%i", buffer[i]);
}
printf("\n");
}

Are my solutions to printing an error due to file size and storing values right?

PART 1: What I need to do is print out an error if the file size exceeds the 500 by 500 measurements (defined at the top as max_width and height). I
PART 2: The other part is that I have to read the pixel information from the input file and store it into a 2d array. Each pixel has 3 values for red, green, and blue, but I'm not sure if this matters.
My attempt at the solution:
PART 1:
void check_file_size //I'm not sure what to put as arguments since width/height are global
{
if (width > 500 && height > 500)
{
perror("Error: File size too big.\n");
}
}
PART 2:
#define max_width 500
#define max_height 500
int width, height
void read_header(FILE *new)
{
int max_color;
char P[10];
fgets(P, 10, new);
fscanf(new, "%d %d", &width, &height);
fscanf(new, "%d", &max_color);
}
void store_into_array(FILE *input)
{
int array[max_width][max_height];
for (x = 0; x < width; x++)
{
for (y = height; y >=0; y--)
{
fscanf(input, "%d", &array[x][y]);
}
}
}
Part 1
Function should take void arguments - this means none.
You want an or. Error if width OR height are too big.
Minor style note, you should be using the #defines here and they should be all uppercase.
void check_file_size(void) {
if (width > MAX_WIDTH || height > MAX_HEIGHT) {
perror("Error: File size too big.\n");
}
}
Part 2
You can loop through an array here like you are, but it's actually much nicer to cheat.
A C array of arrays or a straight array is the same thing with slightly different syntactic sugar.
Read the whole file into an array, see Reading the whole text file into a char array in C for implementation hints.
Cast the buffer into the final structure that you want.
// Make struct rgb match your data, details not supplied in the question
struct rgb {
uint8_t red;
uint8_t green;
uint8_t blue;
}
// Get width & height info as before
uint32_t buffer_size;
void* buffer;
load_file('filename', buffer, &buffer_size);
// Should verify that buffer_size == width * height * 3
struct rgb (*image_data)[width] = (struct rgb(*)[width])buffer;
// Note the above variable length array is a C99 feature
// Pre-C99 the same trick is a touch more ick
// Data can now be accessed as image_data[x][y].red; etc.
Sorry about the stdint.h variables, a habit I can't (and don't want to) break.

Resources