22
22
#include "answer07.h"
23
23
#include <stdlib.h>
24
24
#include <stdio.h>
25
+ #include <string.h>
26
+
27
+ #define TRUE 1
28
+ #define FALSE 0
25
29
26
30
/**
27
31
* Loads an ECE264 image file, returning an Image structure.
30
34
* Hint: Please see the README for extensive hints
31
35
*/
32
36
Image * Image_load (const char * filename ) {
33
- FILE * fp ;
37
+ FILE * fp = NULL ;
34
38
ImageHeader header ;
35
- Image image ;
39
+ Image * image = NULL ;
40
+
41
+ void _teardown () {
42
+ if (image ) {
43
+ Image_free (image );
44
+ image = NULL ;
45
+ }
46
+ fclose (fp );
47
+ }
36
48
37
49
// Open file for reading
38
- fp = fopen (filename , "r " );
50
+ fp = fopen (filename , "rb " );
39
51
if (!fp ) {
40
- fprintf (stderr , "Cannot open file '%s' for reading." , filename );
41
- return NULL ;
52
+ fprintf (stderr , "Cannot open file '%s' for reading.\n " , filename );
53
+ return image ;
42
54
}
43
55
44
56
// Read the header
45
57
if (fread (& header , sizeof (ImageHeader ), 1 , fp ) != 1 ) {
46
- fprintf (stderr , "Unable to read header." );
47
- return NULL ;
58
+ fprintf (stderr , "Unable to read header.\n" );
59
+ _teardown ();
60
+ return image ;
48
61
}
49
62
50
63
// Check the header's validity
51
64
if (header .magic_number != ECE264_IMAGE_MAGIC_NUMBER ) {
52
- fprintf (stderr , "Magic number in header does not match." );
53
- return NULL ;
65
+ fprintf (stderr , "Magic number in header does not match.\n" );
66
+ _teardown ();
67
+ return image ;
54
68
}
55
69
56
70
// Check width and height
57
71
if (header .width <= 0 || header .height <= 0 ) {
58
- fprintf (stderr , "Image file is not of valid width or height." );
59
- return NULL ;
72
+ fprintf (stderr , "Image file is not of valid width or height.\n" );
73
+ _teardown ();
74
+ return image ;
60
75
}
61
76
62
77
// Validate comment
63
- if (header .comment_len < 1 ) {
64
- fprintf (stderr , "Comment length in header is invalid." );
65
- return NULL ;
78
+ if (header .comment_len < 1 || header .comment_len > 1024 ) {
79
+ fprintf (stderr , "Comment length in header is invalid.\n" );
80
+ _teardown ();
81
+ return image ;
82
+ }
83
+
84
+ // Allocate space for image
85
+ if (!((image = malloc (sizeof (Image )))
86
+ && (image -> comment = malloc (header .comment_len * sizeof (char )))
87
+ && (image -> data = malloc (header .width * header .height * sizeof (uint8_t )))
88
+ )) {
89
+ fprintf (stderr , "Cannot allocate space for image.\n" );
90
+ _teardown ();
91
+ return image ;
66
92
}
67
93
94
+ // Set width and height
95
+ image -> width = header .width ;
96
+ image -> height = header .height ;
97
+
68
98
// Read the comment
69
- image .comment = malloc (header .comment_len * sizeof (char ));
70
- if (fread (image .comment , header .comment_len , 1 , fp ) != 1 ) {
71
- fprintf (stderr , "Cannot read comment." );
72
- free (image .comment );
73
- return NULL ;
99
+ if ((fread (image -> comment , header .comment_len , 1 , fp ) != 1 ) || image -> comment [header .comment_len - 1 ] != '\0' ) {
100
+ fprintf (stderr , "Cannot read comment.\n" );
101
+ _teardown ();
102
+ return image ;
74
103
}
75
104
76
105
// Read the image data
77
- image . data = malloc ( header .width * header .height * sizeof ( uint8_t ));
78
- if ( fread ( image . data , header . width * header . height , 1 , fp ) != 1 ) {
79
- fprintf ( stderr , "Cannot read pixel data." );
80
- free ( image . data ) ;
81
- // NOT DONE
106
+ if ( fread ( image -> data , header .width * header .height , 1 , fp ) != 1 ) {
107
+ fprintf ( stderr , "Cannot read pixel data.\n" );
108
+ _teardown ( );
109
+ return image ;
110
+ }
82
111
83
- return NULL ;
112
+ // Check if there are trailing bytes
113
+ uint8_t byte ;
114
+ if ((fread (& byte , sizeof (uint8_t ), 1 , fp ) != 0 ) || !feof (fp )) {
115
+ fprintf (stderr , "File has trailing bytes. Not continuing.\n" );
116
+ _teardown ();
117
+ return image ;
118
+ }
119
+
120
+ fclose (fp );
121
+ return image ;
84
122
}
85
123
86
124
/**
@@ -90,7 +128,44 @@ Image * Image_load(const char * filename) {
90
128
* Hint: Please see the README for extensive hints
91
129
*/
92
130
int Image_save (const char * filename , Image * image ) {
93
- return 0 ;
131
+ FILE * fp = NULL ;
132
+ ImageHeader header ;
133
+
134
+ fp = fopen (filename , "wb" );
135
+ if (!fp ) {
136
+ fprintf (stderr , "Cannot open file '%s' for writing.\n" , filename );
137
+ return FALSE;
138
+ }
139
+
140
+ // Build header
141
+ header .magic_number = ECE264_IMAGE_MAGIC_NUMBER ;
142
+ header .width = image -> width ;
143
+ header .height = image -> height ;
144
+ header .comment_len = strlen (image -> comment ) + 1 ;
145
+
146
+ // Write to file
147
+ if (fwrite (& header , sizeof (ImageHeader ), 1 , fp ) != 1 ) {
148
+ fprintf (stderr , "Unable to write header.\n" );
149
+ fclose (fp );
150
+ return FALSE;
151
+ }
152
+
153
+ // Write comment
154
+ if (fwrite (image -> comment , header .comment_len * sizeof (char ), 1 , fp ) != 1 ) {
155
+ fprintf (stderr , "Unable to write comment.\n" );
156
+ fclose (fp );
157
+ return FALSE;
158
+ }
159
+
160
+ // Image data
161
+ if (fwrite (image -> data , header .height * header .width * sizeof (uint8_t ), 1 , fp ) != 1 ) {
162
+ fprintf (stderr , "Unable to write image data.\n" );
163
+ fclose (fp );
164
+ return FALSE;
165
+ }
166
+
167
+ fclose (fp );
168
+ return TRUE;
94
169
}
95
170
96
171
/**
@@ -103,13 +178,35 @@ int Image_save(const char * filename, Image * image) {
103
178
* report an error.
104
179
*/
105
180
void Image_free (Image * image ) {
106
- return ;
181
+ if (image ) {
182
+ if (image -> data ) {
183
+ free (image -> data );
184
+ }
185
+ if (image -> comment ) {
186
+ free (image -> comment );
187
+ }
188
+ free (image );
189
+ }
107
190
}
108
191
109
192
/**
110
193
* Performs linear normalization, see README
111
194
*/
112
195
void linearNormalization (int width , int height , uint8_t * intensity ) {
113
- return ;
114
- }
196
+ int i ;
197
+ uint8_t min = 255 , max = 0 ;
198
+
199
+ // Find max and min
200
+ for (i = 0 ; i < width * height ; i ++ ) {
201
+ if (intensity [i ] > max ) {
202
+ max = intensity [i ];
203
+ } else if (intensity [i ] < min ) {
204
+ min = intensity [i ];
205
+ }
206
+ }
115
207
208
+ // Normalize image
209
+ for (i = 0 ; i < width * height ; i ++ ) {
210
+ intensity [i ] = (intensity [i ] - min ) * 255.0 / (max - min );
211
+ }
212
+ }
0 commit comments