PPM Image format, height and width not displaying - C - c

My program that is meant to read and display a PPM image is not printing the actual format or height or width of the image being read. It's probably a really basic mistake, but I've not been using C for very long.
EDIT: I've actually just noticed where I check the image format is valid, I'm checking whether it == 2, but it should be != 2 (correct me if I'm wrong) so it says my image format is invalid either way. I'll try run my code on another image.
If anyone can help that would be great.
Current output:
PPM FILE PROGRAM
Memory allocation successful
File format is correct
89~
Image size: 3680602 544108293
Desired output:
PPM FILE PROGRAM
Memory allocation successful
File format is correct
P3
Image size: 125 100
Code:
#include <stdio.h>
#include <stdlib.h>
#define MAX_HEIGHT 600
#define MAX_WIDTH 400
struct PPM {
char format[3]; //PPM format code
int height, width; //image pixel height and width
int max; //max rgb colour value
};
struct PPM_Pixel {
//Create variables to hold the rgb pixel values
int red;
int green;
int blue;
};
struct PPM *getPPM(FILE * file);
void showPPM(struct PPM * image);
int main( void ){
printf("PPM FILE PROGRAM \n");
FILE *file;
// get image file
// FILE *file;
file = fopen("aab(1).ppm", "r");
//if there is no file then return an error
if(file == NULL){
fprintf(stderr, "File does not exist\n");
return 0;
}
struct PPM *newPPM = getPPM(file);
showPPM(file);
fclose(file);
}
struct PPM *getPPM(FILE * file){
char buffer[3];
int c;
struct PPM *image = NULL;
if(NULL == (image = malloc(sizeof(struct PPM)))){
perror("memory allocation for PPM file failed\n");
exit(1);
}
else {
printf("Memory allocation succesful\n");
}
//read the image of the format
if(!fgets(buffer, sizeof(buffer), file)){
exit(1);
}
//checks the format of the ppm file is correct
if(buffer[0] != 'P' || buffer[1] != '3'){
fprintf(stderr, "Invalid image format! \n");
exit(1);
}else{
printf("File format is correct\n");
printf("%s\n", image->format);
}
//checks whether the next character is a comment and skips it
c = getc(file);
while(c == '#'){
while(getc(file) != '\n'){
c = getc(file);
}
}
//check the image size is valid
if(fscanf(file, "%d %d", &image->height, &image->width) == 2){
printf("Invalid imaze size\n");
exit(1);
}else{
printf("Image size: %d %d ", image->height, image->width);
}
return image;
}
void showPPM(struct PPM * image){
struct PPM_Pixel rgb_array[MAX_HEIGHT][MAX_WIDTH];
int i;
int j;
for(i = 0; i<MAX_HEIGHT; i++){
for(j = 0; j<MAX_WIDTH; j++){
struct PPM_Pixel newPPM_Pixel;
if(fscanf(image, "%d %d %d", &newPPM_Pixel.red, &newPPM_Pixel.green, &newPPM_Pixel.blue) == 3){
rgb_array[i][j] = newPPM_Pixel;
}
}
}
}
Apologies, I'm not sure how to change the output text to just text.

Although you forget to include the code of showPPM(), his prototype is
void showPPM(struct PPM * image);
and you are passing a FILE *:
FILE *file;
...
showPPM(file);

Related

Write bitstream to file in C

I'm currently trying to use a CMP decompressor: https://web.archive.org/web/20070113004119/http://rewiki.regengedanken.de:80/wiki/.CMP
It does in fact decompress the cmp, but it does not write it into a file.
So i tried myself.
int main(int argc, char** argv)
{
int length, dstLength;
unsigned char* fileInMem; //compressed data
unsigned char* dstFile; //decompressed data
if (argc < 2) {
fprintf(stderr, "give filename.cmp as parameter\n");
return 1;
}
printf("%s", argv[1]);
fileInMem = loadFile(argv[1], &length); //compressed data read
if (fileInMem == NULL) {
return 1;
}
dstFile = parseCmp(fileInMem, length, &dstLength); //decompress and assign data to dstFile
if (dstFile) {
/* Now we can save the file from dstFile, dstLength bytes */
printf("%d bytes depacked\n", dstLength);
for (int i = 0; i < 16; i++) {
dataArray[i] = fileInMem[i];
}
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
fclose(writer);
free(dstFile);
}
free(fileInMem);
return 0;
}
As you can see the decompressed data is a pointer to an unsigned char (according to the website a bitstream) and I tried fputs() from stdio.h, but the resulting file contains only 4 Bytes when viewed in a hex-editor.
If you need more information, please comment.
Thank you in advance.
Edit: This is what I was able to change thanks to your help, but when I open the file, it is still empty:
FILE* writer = fopen(argv[2], "wb");
fwrite(dstFile, 192, 192, writer);
192, because the length of the first decompressed Image is 192 Bytes large.
This is a common issue.
First, you need to open the output file writer for writing in binary mode ("wb").
FILE *writer = fopen(argv[2], "wb");
Second, you can't use fputs to write arbitrary data to a file, since it expects a string. Use fwrite instead: (assuming writer is the output file, dstFile the decompressed data and dstLength the amount of bytes to write)
fwrite(dstFile, 1, dstLength, writer);
If you examine the resulting file with an hex editor, you will see it is identical to the decompressed data.
Test-update
I wrote some test-code to see what is wrong, share your results so we can help you.
Add these functions to your code:
void printDataToScreen(unsigned char *dataptr, int datalen)
{
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
}
printf("> Dumping %d bytes of data into the terminal...\n", datalen);
for (int i = 0; i < datalen; i++)
{
if (i % 16 == 0)
printf("\n ");
printf("%02X ", dataptr[i]);
}
printf("\n\n");
}
void writeDataToFile(char *fileName, unsigned char *dataptr, int datalen)
{
FILE *file = fopen(fileName, "wb");
if (dataptr == NULL)
{
printf("[!] ERROR, NULL POINTER PROVIDED!\n");
return;
} else if (file == NULL)
{
printf("[!] ERROR WHILE OPENING FILE '%s'!\n", fileName);
return;
}
printf("> Writting %d bytes of data to '%s'...\n", datalen, fileName);
int writtenBytes = fwrite(dataptr, 1, datalen, file);
printf(" Done, %d bytes written!\n\n", writtenBytes);
fclose(file);
}
void runTest(char *fileName, unsigned char *dataptr, int datalen)
{
printf("Running tests... [0/2 done]\n");
printDataToScreen(dataptr, datalen);
printf("Running tests... [1/2 done]\n");
writeDataToFile(fileName, dataptr, datalen);
printf("Finished! [2/2 done]\n");
}
Call it like this:
runTest(argv[2], dstFile, dstLength);
Add the call to this place in your code (comment this code, also the line where you close writer):
FILE *writer = fopen(argv[2], "r+");
//fputs(fileInMem, writer);
//fputs(dstFile, writer);
Please share your results.

ppm format that have magic code P3

how i can read ppm image that have magic code P3. in c language?
this code reading ppm image that have magic code P3 but there a problem with loading method,this code enters into in infinite loop when reading the value of pixles?
/* This is for reading and Writing images file in PPM
Also example of making Negative images
- Use this file as an example of reading (loading) and writing (storing) images files.
- This program loads an PPM image and store a new image that is the negative of the original image.
*/
typedef struct pdata {
int red;
int green;
int blue;
} pdata;
typedef struct ppm {
int w;
int h;
int max;
pdata *pData;
} ppm;
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
//#define kernelW 3
//#define kernelH 3
//#define imageW 403
//#define imageH 332
char filename[256];
/*
This LoadPGM function is an updated version that will deal with
comments in file headers and do at least some basic checking if the
file can be opened or is the correct format. It does assume the file
is actually a valid length once the header has been read.
You are of course free to use your own file reading functions.
*/
void LoadPGM( char* filename, ppm* pPgm ) {
FILE* ifp;
int word;
int nRead = 0;
char readChars[256];
//open the file, check if successful
ifp = fopen( filename, "r" );
if (!ifp) {
printf("Error: Unable to open file %s.\n\n", filename);
exit(1);
}
//read headers from file
printf ("Reading PPM file: %s...\n", filename);
fscanf (ifp, "%s", readChars);
if (strcmp(readChars, "P3") == 0) {
//valid file type
//get a word from the file
fscanf (ifp, "%s", readChars);
while (readChars[0] == '#') {
//if a comment, get the rest of the line and a new word
fgets (readChars, 255, ifp);
fscanf (ifp, "%s", readChars);
}
//ok, comments are gone
//get width, height, color depth
sscanf (readChars, "%d", &pPgm->w);
fscanf (ifp, "%d", &pPgm->h);
fscanf (ifp, "%d", &pPgm->max);
// allocate some memory, note that on the HandyBoard you want to
// use constant memory and NOT use calloc/malloc
pPgm = (ppm *)malloc(sizeof(ppm));
pPgm->pData = (pdata*)malloc(pPgm->w *pPgm->h * sizeof(pPgm->pData));
fscanf(ifp, "%d" ,&word);
pPgm->pData[0].red = word;
printf (" %d \n", word);
for (nRead = 0; nRead < pPgm->w * pPgm->h; nRead++) {
fscanf(ifp, "%d" ,&word);
// printf (" %d \n",word);
pPgm->pData[nRead].red = word;
fscanf(ifp, "%d" ,&word);
pPgm->pData[nRead].green = word;
fscanf(ifp, "%d" ,&word);
pPgm->pData[nRead].blue = word;
}
printf ("Loaded PPM. Size: %dx%d, Greyscale: %d \n",
pPgm->w, pPgm->h, pPgm->max + 1);
}
else {
printf ("Error: Read file type %s. Format unsupported.\n\n", readChars);
exit(1);
}
fclose(ifp);
}
/* Simply saves the PGM file to a file whose name is in filename */
void WritePGM( char* filename, ppm* pPgm ) {
FILE* ofp;
int w, h, max;
int nWrite = 0;
int i,j;
strcat(filename, ".out.ppm");
ofp = fopen(filename, "w");
if (!ofp) {
printf("Error: Unable to open file %s.\n\n", filename);
exit(1);
}
printf ("Writing ouput PPM: %s\n\n", filename);
//write the header
fprintf( ofp, "P3\n" );
fprintf( ofp, "%d %d\n", pPgm->w, pPgm->h );
// printf("Done. Have a nice day...\n\n");
fprintf( ofp, "%d\n", pPgm->max );
//write the image data
for (i = 0; i < pPgm->h;i++) {
for (j = 0; j < pPgm->w; j++)
fprintf(ofp,"%d ",*(pPgm->pData + i * pPgm->w + j));
fprintf(ofp,"\n");
}
fclose(ofp);
}
int main(int argc, char * argv[]) {
ppm* image, *r1,*r2;
// char filename[256];
int val;
int errchk;
char f1[256];
//check if a filename was given, if not, ask for one
if (argc > 1) {
strcpy(filename, argv[1]);
}
else {
printf ("Enter filename: ");
scanf ("%s", filename);
}
//allocate memory for the pgm struct
image = (ppm *) malloc (sizeof(ppm));
//read the file
LoadPGM(filename, image);
int h,w;
w=image->w;
h=image->h;
int* pBuff1;
int* pBuff2;
int size;
int sum=0;
WritePGM(filename, image);
// end of the program
}
This line
malloc(pPgm->w *pPgm->h * sizeof(pPgm->pData))
allocates the wrong size. It allocates sizeof(pointer) while you need it sizeof(pdata), your own RGB struct.
Typically, one only needs RGB as 3 unsigned char, and had you used that the error would have been invisible, since pointers are usually 4 bytes long (and nowadays can even be longer). But since you made your values each an int, the structure uses 12 bytes in total. Somewhere after the first third has been read (give or take), your code starts overwriting other stuff in memory and you get toasted.

C - Mirror a PPM from left to right

I have to write a program where I take user input for a PPM image and then mirror the image from left to right (basically flipping it over the y-axis). So if the image was <, the new image would now be >. This should not be a 180 degree rotation, as that would make the image upside down. It should still be the same, just reflected.
I have the code here that I used to input and output the PPM, but I don't know how to mirror it. I made a function that would theoretically be used for the mirror code, but I'm not sure if that's the best way to do it either. If you know a better place to put the code, be my guest.
I have researched this topic quite a bit, but was only able to find issues where people needed to rotate the image.
Here is what I have so far:
#include<stdio.h>
#include<stdlib.h> //for fopen()
typedef struct {
unsigned char red,green,blue;
} pixel_t; //struct for pixels
typedef struct {
int x, y;
pixel_t *data;
} PPMImage; //struct for creating the image
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);} //opens the ppm and checks to make sure it can be opened
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);} //read the format of the image
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);} //checks to see if the format is ppm
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);} //allocates the memory needed to form the input image
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}//checks for comments
ungetc(c, fp);
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);} //reads the size of the image, height becomes img->y, and width becomes img->x
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);} //reads how much of each color there is
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);} //makes sure the the component is 8 bits
while (fgetc(fp) != '\n') ;
img->data = (pixel_t*)malloc(img->x * img->y * sizeof(pixel_t));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);} //allocates the memory need for the pixel data
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);} //reads the pixel data
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);} //opens the file for output
//write the header file
//image format
fprintf(fp, "P6\n");
//image size
fprintf(fp, "%d %d\n",img->x,img->y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel data
fwrite(img->data, 3 * img->x, img->y, fp);
fclose(fp);
}
void mirror(PPMImage *img)
{
//this is where I want to insert the code for mirroring the image
}
int main(int argc, char* argv[]){ //takes command line parameters
PPMImage *image;
char* filename = argv[1];
image = readPPM(filename);
mirror(image);
writePPM("OutputFile.ppm",image); //creates the output file
printf("Press Enter");
getchar();
}
Your mirror() function can work on the image one row at a time. For each row, take the left-most pixel in the row and swap its value with the value of the right-most pixel in the row. Then take the second-left-most pixel and swap its value with the second-right-most pixel, and so on, until the column-positions of the pixels you are swapping "meet in the middle". (Then move on to the next row and do the same thing to it, until you've done all the rows).
Note that if the image contains an odd number of columns, there will be one column in the center of the image that stays unmodified (since it forms the axis around which the mirroring occurs). With an even number of columns, all columns will be swapped.
To mirror image vertically you can use this function:
void mirrorVert(PPMImage *img)
{
int y;
int x;
const int middleX = img->x / 2;
pixel_t tmp;
pixel_t* p;
for (y = 0; y < img->y; ++y)
{
p = img->data + y * img->x;
for (x = 0; x < middleX; ++x)
{
// swap pixels
tmp = p[x];
p[x] = p[img->x - 1 - x];
p[img->x - 1 - x] = tmp;
}
}
}
And to mirror it horizontally:
void mirrorHoriz(PPMImage *img)
{
const int line_size = img->x * sizeof(pixel_t);
const int middle = img->y / 2;
int y;
// allocate swap buffer
pixel_t* buff = (pixel_t*)malloc(line_size);
pixel_t* top;
pixel_t* bottom;
for (y = 0; y < middle; ++y)
{
// swap lines from top and bottom
top = img->data + (y * img->x);
bottom = img->data + ((img->y - y - 1) * img->x);
memcpy(buff, top, line_size);
memcpy(top, bottom, line_size);
memcpy(bottom, buff, line_size);
}
}

Steganography in C

Trying to do basic Steganography on a PPM Image.
I have the basic algorithm completed. Read in the file, check the header starts with P6, get the image width and height, and the pixel data.
I need to have a total of four methods: ReadPPM, WritePPM, WriteMsg and ReadMsg.
I have the ReadImg and WriteImg methods down, but where I am stuck is with my WriteMsg method. This is basic steganography that just writes each bit of the string to the last bit in each byte. The first 8 bytes are suppose to contain the size of the string being hidden, then each byte after that starts the hidden message.
My idea was to create a massive array that holds the binary code for the size of the string, then the binary code of the string itself. I'm just trying to figure out how I would take that array and add it to each byte in the image.
Any help is much appreciated. Here is my current code:
#include<stdio.h>
#include<stdlib.h>
typedef struct {
unsigned char red,green,blue;
} PPMPixel;
typedef struct {
int x, y;
PPMPixel *data;
} PPMImage;
#define CREATOR "RPFELGUEIRAS"
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
//open PPM file for reading
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//read image format
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);
}
//check the image format
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);
}
//alloc memory form image
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//check for comments
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}
ungetc(c, fp);
//read image size information
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);
}
//read rgb component
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
//check rgb component depth
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);
}
while (fgetc(fp) != '\n') ;
//memory allocation for pixel data
img->data = (PPMPixel*)malloc(img->x * img->y * sizeof(PPMPixel));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//read pixel data from file
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);
}
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
//open file for output
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//write the header file
//image format
fprintf(fp, "P6\n");
//comments
fprintf(fp, "# Created by %s\n",CREATOR);
//image size
fprintf(fp, "%d %d\n",img->x,img->y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel data
fwrite(img->data, 3 * img->x, img->y, fp);
fclose(fp);
}
void writeMsg(PPMImage *img, char *s)
{
int i;
int len;
len = sizeof(s);
if (img)
{
j = 0;
for (i=0; i < img->x * img->y; i++)
{
while(j < 8)
{
if(len & 0x80)
{
img->data[i].red= img->data[i].red | 0x01;
}
else
{
img->data[i].red= img->data[i].red & 0xFE;
}
len=len << 1;
j++;
if (len & 0x80)
{
img->data[i].green= img->data[i].green | 0x01;
}
else
{
img->data[i].green= img->data[i].green & 0xFE;
}
len = len << 1;
j++;
if (len & 0x80)
{
img->data[i].blue= img->data[i].blue | 0x01;
}
else
{
img->data[i].blue= img->data[i].blue & 0xFE;
}
j++;
}
}
}
}
To extract just a single bit from a byte, do this:
bit(i) = byte >> i & 0x1
This shifts the byte's bits to the right i times, and then ands it with 0000 0001 (such that all bits except the lowest are zeroed, and the lowest bit is 0 for 0 and 1 for 1).
You can do similar for 16 bit short, 32 bit int, 64 bit long... And even for the chars of a string. You can use sizeof(char) to see how many bytes are in a char.
But of course you'll have more than one char (or long or int or...) to extra bits from. To decide which element to extra a bit from:
If you want the ith bit and elements are x bits wide, then get the i%x bit from element [i/x]
Now that you have this bit, to place it inside of a byte (or int or char or...), do:
steganographybyte = originalbyte&(~0x1) + bit
What this means is, you take the number ... 0000 0001, invert its bits so it's ... 1111 1110, and it with the original byte so all of its bits are preserved EXCEPT the lowest, then just add your bit in.

read PPM file and store it in an array; coded with C

I need to read a PPM file and store it in an array written in C.
Can anybody help me out doing this?
Thanks a lot.
The following code shows how to read, change the pixel colour and write an image in
PPM format. I hope it helps.
#include<stdio.h>
#include<stdlib.h>
typedef struct {
unsigned char red,green,blue;
} PPMPixel;
typedef struct {
int x, y;
PPMPixel *data;
} PPMImage;
#define CREATOR "RPFELGUEIRAS"
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
//open PPM file for reading
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//read image format
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);
}
//check the image format
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);
}
//alloc memory form image
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//check for comments
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}
ungetc(c, fp);
//read image size information
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);
}
//read rgb component
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
//check rgb component depth
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);
}
while (fgetc(fp) != '\n') ;
//memory allocation for pixel data
img->data = (PPMPixel*)malloc(img->x * img->y * sizeof(PPMPixel));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//read pixel data from file
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);
}
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
//open file for output
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//write the header file
//image format
fprintf(fp, "P6\n");
//comments
fprintf(fp, "# Created by %s\n",CREATOR);
//image size
fprintf(fp, "%d %d\n",img->x,img->y);
// rgb component depth
fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);
// pixel data
fwrite(img->data, 3 * img->x, img->y, fp);
fclose(fp);
}
void changeColorPPM(PPMImage *img)
{
int i;
if(img){
for(i=0;i<img->x*img->y;i++){
img->data[i].red=RGB_COMPONENT_COLOR-img->data[i].red;
img->data[i].green=RGB_COMPONENT_COLOR-img->data[i].green;
img->data[i].blue=RGB_COMPONENT_COLOR-img->data[i].blue;
}
}
}
int main(){
PPMImage *image;
image = readPPM("can_bottom.ppm");
changeColorPPM(image);
writePPM("can_bottom2.ppm",image);
printf("Press any key...");
getchar();
}
Here is the
PPM specification.
The PPM file is built in 9 sections separated by white-spaces.
Open the file
read until the first white space and check you got P6. Then skip other white-spaces.
read until the next white space, convert your buffer to an integer width. Then skip other white-spaces
read until the next white space, convert your buffer to an integer height. Then skip other white-spaces
Allocate a 2D array of integers in the size of height*width
read the max-val
read line by line and fill the array

Resources