-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPPM.c
185 lines (158 loc) · 5.25 KB
/
PPM.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "PPM.h"
// writes a PPM header with a given file name
int write_header(uint8_t magic, uint8_t maxval, uint64_t width, uint64_t height, FILE * outputFile){
return fprintf(outputFile, "P%hhu\n%lu %lu\n%hhu\n", magic, width, height, maxval);
}
// basically just a printf wrapper that writes the pixel for you
int write_p3_pixel(pixel out, FILE * outputFile)
{
return fprintf(outputFile, "%hhu %hhu %hhu\n", out.red, out.green, out.blue);
}
// writes the raw components of the pixel to the output file, returning write number
int write_p6_pixel(pixel out, FILE * outputFile)
{
int i=0;
// writes out the bytes for each color component
i+=fwrite(&out.red, 1, 1, outputFile);
i+=fwrite(&out.green, 1, 1, outputFile);
i+=fwrite(&out.blue, 1,1, outputFile);
// returns the number of successful writes (<3 indicates write failure)
return i;
}
// reads in and returns a pixel read from the file
pixel read_p3_pixel(FILE * inputFile){
pixel newPixel;
fscanf(inputFile, " %hhu %hhu %hhu", &newPixel.red, &newPixel.green, &newPixel.blue);
return newPixel;
}
pixel read_p6_pixel(FILE * inputFile){
// temporary array to hold 1 pixel value
uint8_t buffer[3];
// reads in 3 bytes (3 pixels per byte)
fread(buffer, 3, 1, inputFile);
// creates pixel from values in buffer
pixel newPixel={buffer[0], buffer[1], buffer[2]};
return newPixel;
}
header readHeader(FILE * inputFile){
header new_header;
// max length of line is 70
char buffer[71];
char strings[4][71];
// stores the pointer to the location of the # symbol to ignore comments
char* comment_start;
char dummy_arr[71];
char * dummy=dummy_arr;
int string_count=0;
// gets 4 valid strings that contain the header
while(string_count<4)
{
fgets(buffer, 71, inputFile);
//finds and eliminates everything after a comment
comment_start=strchr(buffer, '#');
if(comment_start!=NULL){
comment_start[0]='\0';
}
// collects any values on this line
for(dummy=strtok(buffer, " "); dummy !=NULL; dummy=strtok(NULL," "))
{
// copies the individual tokens into strings
strncpy(strings[string_count], dummy, 71);
string_count++;
}
}
// parses the strings to make a header
sscanf(strings[0], " P%hhu", &new_header.magic);
sscanf(strings[1], " %lu", &new_header.width);
sscanf(strings[2], " %lu", &new_header.height);
int check = sscanf(strings[3], " %hhu%c", &new_header.maxval, dummy);
// checks if a value was read for maxval (fails when too large)
if(check<1){
printf("Error: image color depth too large\n");
}
// returns a header structure
return new_header;
}
// reads a p3 image into an array of rgb pixels
pixel * read_p3(FILE * file, header metadata){
size_t pixel_count=metadata.width*metadata.height;
pixel * image=(pixel*)malloc(pixel_count*sizeof(pixel));
int i=0;
for(i=0; i<pixel_count; i++){
image[i]=read_p3_pixel(file);
}
fclose(file);
return image;
}
void write_p3(pixel * image, header metadata, char* filename){
// opens file for writes
FILE * file=fopen(filename, "w");
//writes a p3 header
write_header(3, metadata.maxval, metadata.width, metadata.height,file);
// calculates number of pixels
long long pixel_count=metadata.width*metadata.height;
int i;
int j = 0;
for(i=0; i<pixel_count; i++){
// writes out image in p3 format
j=write_p3_pixel(image[i], file);
if(j<1){
printf("Error: failed to write pixel\n");
break;
}
}
fclose(file);
}
pixel * read_p6(FILE * file, header metadata){
size_t pixel_count=metadata.width*metadata.height;
pixel * image=(pixel*)malloc(pixel_count*sizeof(pixel));
int i=0;
for(i=0; i<pixel_count; i++){
image[i]=read_p6_pixel(file);
}
fclose(file);
return image;
}
void write_p6(pixel * image, header metadata, char* filename){
FILE * file=fopen(filename, "w");
// writes a p6 header for the file
write_header(6, metadata.maxval, metadata.width, metadata.height,file);
// calculates the necessary number of pixels to write out
long long pixel_count=metadata.width*metadata.height;
int i;
int j = 0;
for(i=0; i<pixel_count; i++){
// writes out the pixel from the image in a p6 format
j=write_p6_pixel(image[i], file);
if(j<3){
printf("Error: failed to write pixel\n");
break;
}
}
fclose(file);
}
void write_image(image out, char * filename){
if(out.metadata.magic==3)
{
write_p3(out.pixmap, out.metadata, filename);
}
else if (out.metadata.magic==6)
{
write_p6(out.pixmap, out.metadata, filename);
}
}
header make_header(uint8_t magic, uint8_t maxval, uint64_t width, uint64_t height){
header newHeader;
newHeader.maxval=maxval;
newHeader.magic=magic;
newHeader.width=width;
newHeader.height=height;
return newHeader;
}
pixel * make_pixmap(header metadata){
size_t image_size=metadata.width * metadata.height;
return (pixel *) malloc(sizeof(pixel)*image_size);
}
void free_image(image destroy){
free(destroy.pixmap);
}