I'm writing a program to manipulate images .PPM based on a template given by my professor. The template has these structures:
typedef struct {
unsigned char gray;
} PPMGrayPixel;
typedef struct {
int x, y;
PPMGrayPixel *data;
} PPMGrayImage;
I'm trying to convert a regular .ppm to a gray scale .ppm. Actually, in this case, I already have an empty grayscale image with the same size that my original image. This grayscale file just have one channel of color (the original has three). I'm okay with the formula to convert, but I think I'm missing something while I try to access the elements of the grayscale file.
I'm not worried to set the right number, I just want to set the values for black and white now. I want to be sure that I'm accessing the right pixel.
This is my code:
PPMGrayImage * ConvertToGrayFromColorImage(PPMImage *img) {
PPMGrayImage *img2;
img2 = CreateEmptyGrayImageFromColorImage(img);
for (int i=0; i < img2->x*img2->y; i++) {
if (i % 2 == 0) {
img2.data[i].gray = 0;
}
else {
// sign 1
}
}
Am I missing something in the logic of the problem or in sintax?
img2.data[i].gray = 0;
img2 is a pointer to struct, so you cannot access its members directly. You have to write:
(*img2).data[i].gray = 0;
or:
img2->data[i].gray = 0;
Related
The for loop should be replaced with a fread I believe, however, I am very unclear on how fread will work.
How does fread know the value of green pixel # given location and where to save the value. My understanding is that I have a chunk of heap memory, a rectangle has a tbd number of pixels. Each pixel has 3 values. How will fread (or any other method I can use)?
If anyone could just explain how the fread line below would work with my code? This is for an assignment, I am just trying to understand what is going on since it is one we will be building on.
fread(pixelD, sizeof(Pixel), width*height, file);
typdef struct
{
unsigned char green;
unsigned char blue;
unsigned char red;
}pixelD;
typedef struct
{
pixelD * pixel;
} Color;
Image * ReadImage(char *filename)
{
int width, height, maxval;
int imgSize = width * height * sizeof(pixel);
//fscanf line was given by prof
fscanf(f_in, "%s\n%d %d\n%d\n", magicNum, &width, &height, &maxval);
pixel = malloc(imgSize);
for(int i = 0; i <imgSize; i++)
{
pixel.green = pixel[i]; ????
pixel.blue = ;
pixel.red = ;
}
}
From the looks of it you are reading a PPM file.
Read the header doing something like this:
int width, height, max;
my_assert(3==fscanf(f_in, "P6%d%d%d ", &width, &height, &max));
/* TODO: error handling */
The format specifiers tells it to read the expected magic number ("P6"), then second, third and fourth words as integers (implicitly skipping any whitespace between), and then consume a whitespace ("mostly a newline" according PPM) to set the file read position to where the binary data starts. You should probably make sure width/height/max being within what your application expects and can cope with.
And then read the rest of the data into memory. fread read from the current read position size*count bytes; no formatting:
int channel_width = max < 256 ? 1 : 2; /* PPM channel width can be either 1- or 2-byte */
int rgb = 3;
int imgsize = width*height*rgb*channel_width;
void* texture = malloc(imgsize);
my_assert(imgsize==fread(texture, 1, imgsize, f_in));
/* do something with the texture memory */
At that point you can just cast the texture pointer to whatever struct you like to use, e.g. pixel1D* pixs = texture (just be careful if channels are 2-byte long since your posted struct is not). I find a structure carrying the meta and a typeless memory block more flexible since mostly working with OpenGL. Maybe that is what you meant to do with the Image type.
The code is completely untested. Have fun debugging it.
I'm reading a code from a ppm file and store the value of each pixel in p1, array of pixel, which is a struct of .red .green .blue (int). I managed to create a "Negative Filter" of the picture, however. I'm trying to get a black and white by taking the mean of red, green, and blue pixel.
I have pixel p1, pixel p2(negative filter) and int p3(b&w). However every action that have p3 = ...., will stop responding. such as
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < HEIGHT; j++) {
p3[i][j] = ((p1[i][j].red + p1[i][j].green + p1[i][j].blue)/3);
}
}
or
for (i = 0; i < WIDTH; i++) {
for (j = 0; j < HEIGHT; j++) {
fprintf(pf3, "%d", p3[i][j]);
}
}
However when I change int p3[WIDTH][HEIGHT] to char p3[WIDTH][HEIGHT], the program runs but gives a wrong output. Both int and char, compiled successfully. Can someone help me? thanks.
EDIT:
What I'm hoping is I could create a .pgm black and white extension of picture from .ppm by inputting .ppm value to pixel p1[WIDTH][HEIGHT] in .red, .green, and .blue. Then calculate the mean of RGB and assign it in int p3 before being written in .pgm.
What I got when using int p3, it crashes when I run the .exe stopped working without giving any error.
When I use char p3, it run perfectly, but it gives all negative value for the mean of all the pixel. (This already being helped by putting unsigned infront of the char thanks to #egoteclair)
My new question would be why can't I use int instead of unsigned char?
Normal char size is 8-bit. The first bit will be used for the sign extension. In a 24 bit png file each color-field contains 8 bits.
24 / 3 = 8
So try to use unsigned char instead of char. This allows you to use the complete 8 bits of the char.
I am writing in C and I have to write code that will invert the RGB values for each pixel in an image. It's a simple process in that you take the max color value and subtract the actual RGB values. I have successfully read in the max color value, but when trying to invert the values, everything is returned as 0 and when written to a new file is not readable. Below is the code, any ideas?
Inverting the picture
int i,j;
for(i=0; i<myPic->rows;++i) {
//Moves up and down the columns reaching all Pixels
//Moves across left to right across all columns
for (j=0;j<myPic->cols;++j) {
//Inverstion requires the actual value to be subtracted from the max
myPic->pixels[i][j].red = myPic->colors - myPic->pixels[i][j].red;
myPic->pixels[i][j].green = myPic->colors - myPic->pixels[i][j].green;
myPic->pixels[i][j].blue = myPic->colors - myPic->pixels[i][j].blue;
}
}
return myPic;
}
Output of the image
fprintf(name,"P3\n%d %d\n%d\n",myPic->rows,myPic->cols,myPic->colors);
//The P3,rows,columns,and color values are all printed first
int i,j;
for(i=0; i< myPic->rows;++i) {
for(j=0; j<myPic->cols;++j) { //Each Pixel is printed one at a time
fprintf(name,"%d",myPic->pixels[i][j].red); //Red printed first
fprintf(name,"%d",myPic->pixels[i][j].green); //Green printed second
fprintf(name,"%d",myPic->pixels[i][j].blue); //Blue printed third
fprintf("\n");
}
}
}
Thanks for the help guys, this is what I'm using now and it works
When writing the pixel data, this line
myPic->pixels[i] = malloc(sizeof(Pixel) *myPic->cols);
overwrites the existing pointer, and makes it point to new (and more importantly, uninitialized) data.
Copy-paste programming (which you seem to have been doing) can work sometimes, but you have to take care to modify the copied code properly.
On an unrelated note, you don't print a newline after each line, so the resulting PPM file will actually not be correct.
#Joachim is correct. so do something like this:
int i,j;
for(i=0; i<myPic->rows;++i) {
Pixel[myPic->cols] temp = *myPic->pixels[i];
//Moves up and down the columns reaching all Pixels
myPic->pixels[i] = malloc(sizeof(Pixel) *myPic->cols);
//Moves across left to right across all columns
for (j=0;j<myPic->cols;++j) {
//Inverstion requires the actual value to be subtracted from the max
myPic->pixels[i][j].red = myPic->colors - temp[j].red;
myPic->pixels[i][j].green = myPic->colors - temp[j].green;
myPic->pixels[i][j].blue = myPic->colors - temp[j].blue;
}
}
return myPic;
}
Im having trouble with fwrite corrupting files.
The idea behind this program is to just create a RAW image file that exists out of pixels that I inserted into an array called Colors[]. Basically is should be making straight lines of the different colors im placing into the arrays. Now ive tried a whole lot of methods to write it into a file but if it hasnt been written out in bit mode it just doesnt work on my RAW image display program that I have created although other RAW images do work on it though.
Would there be any easier ways of doing exactly this that I want to do ?
There a version of this program where i use an array of chars to fill the buffer but its a whole lot more code. eX //unsigned char Col[] = {'f','f','f','f','f','f'};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *readFile(char *fileName);
int main()
{
unsigned int i;
//Pixels in 24Bit mode
unsigned int Colors[] = {0x00ff00,0x00ffff,0xffff00,0xffff00};
FILE *fpw;
fpw=fopen("MF.bin", "wb");
/*A Buffer array for the pixels to be stored in before fwrite will be used to
dump the entire array to a file.
640pixels by 480pixels * 3(each pixel has 3 ints)
*/
unsigned int Buff[640*480*3];
int y,z,CP=0;
unsigned long x;
for (y=0;y<=(480);y++)
{
if (x>=640)
{
CP = 0;
}
for(x=0;x<=640;x++)//3840);x++)
{
if ((x>=320))
{
CP = 1;
}
if ((x>=159) && (x<319))
{
CP = 1;
}
else if ((x>=319) && (x<439))
{
CP = 2;
}
else if ((x>=439) && (x<640))
{
CP = 0;
}
else if (x>=640)
{
CP =0;
}
Buff[480*y + x] = Colors[CP];
printf("%u--%u,%u\n",(480*y + x),Buff[480 + x], Colors[CP]);
}
unsigned int xx = fwrite(Buff, 1, sizeof(Buff)/sizeof(Buff[0]), fpw);
printf("--&z--",xx);
}
fclose(fpw);
}
There are a few mistakes...
Buff[480*y + x] = Colors[CP];
should be
Buff[640*y + x] = Colors[CP];
and the y loop should be < 480 not <=, same for x.
You are using unsigned ints so you don't need to multiply by 3 in your new. Using fwrite to directly write out 24 bit data won't work like that, as you have an array of 32 bit data, and your calculation for how many bytes to write is incorrect (you need to multiply not divide, but as stated above that would also be wrong because you have 32 bit data instead of 24).
There's no 24 bit data type, so you should use an array of unsigned char not unsigned long and do each colour component individually.
We are programming a ST269 microcontroller which has two IR distance sensors. To calibrate these sensors we made one table for each sensor with the distance we measured and the corresponding value we get from the ADC.
Now we want to use one function to approximate the values in between. So we defined two two-dimensional arrays (one for each sensor) as global variables. In our function we then want to copy the one array we want to work with to a working array and approximate our values.
So here's the code:
...
unsigned int ir_werte_re[][] = {
{8,553},
...
{83,133}
};
unsigned int ir_werte_li[][] = {
{8,566},
...
{83,147}
};
...
unsigned int geradenaproximation(unsigned int messwert, unsigned int seite)
{
unsigned int working_array[16][16];
unsigned int i = 0;
if (seite == 0) {
for (i = 0; i < sizeof(working_array); i++) {
working_array[i][0] = ir_werte_li[i][0];
i++;
}
}
else {
for (i = 0; i < sizeof(working_array); i++) {
working_array[i][0] = ir_werte_re[i][0];
i++;
}
}
i = 0;
unsigned int y1 = 0;
unsigned int x1 = 0;
...
}
This code is in a file called sensor.c. We didn't write anything about our global arrays in the sensor.h should we? The sensor.h of course is included in our main.c and there the function is called.
We also tried to copy the arrays via
memcpy(working_array, ir_werte_li, sizeof(working_array));
And in every way we do this we get a
syntax error near unsigned
in the line where we're declaring
unsigned int y1 = 0;
and I'm pretty sure that there is no syntax error in this line : )
The last time I spend coding in C is a few years away so I'm not sure if the way we try to do this is good. Perhaps we can solve this by using a pointer instead of really copying the array or something. So please help me out I'll appreciate your bits on this.
In C (pre-C99), all variable definitions must appear at the top of the current block scope.