3 * CS5600 University of Utah
5 * mcgarvey@eng.utah.edu
20 int left
, right
, bottom
, top
;
24 raster_t
* raster_alloc(int width
, int height
, color_t fill
)
26 assert(0 < width
&& 0 < height
&& "zero-dimension raster not allowed");
27 size_t size
= width
* height
;
29 raster_t
* p
= (raster_t
*)mem_alloc(sizeof(raster_t
));
30 p
->pixels
= (color_t
*)mem_alloc(sizeof(color_t
) * size
);
33 raster_clear(p
, fill
);
34 raster_viewport(p
, 0, 0, width
, height
);
39 void raster_destroy(raster_t
* p
)
46 color_t
* raster_color(const raster_t
* p
, int x
, int y
)
48 return p
->pixels
+ p
->w
* y
+ x
;
51 int raster_width(const raster_t
* p
)
56 int raster_height(const raster_t
* p
)
61 void* raster_data(const raster_t
* p
)
63 size_t size
= p
->w
* p
->h
;
64 rgba_t
* data
= (rgba_t
*)mem_alloc(size
* sizeof(rgba_t
));
66 for (int i
= 0; i
< size
; ++i
) {
67 data
[i
] = rgba_from_color(p
->pixels
[i
]);
73 void raster_clear(raster_t
* p
, color_t fill
)
75 size_t size
= p
->w
* p
->h
;
76 for (int i
= 0; i
< size
; ++i
) {
82 void raster_viewport(raster_t
* p
, int x
, int y
, int width
, int height
)
91 #define _DO_OR_DIE(X) if ((X) <= 0) goto fail
93 int raster_export_ppm(const raster_t
* p
, const char* filename
)
95 FILE* file
= fopen(filename
, "w");
97 fail
: fprintf(stderr
, "Cannot write to %s: %s\n", filename
, strerror(errno
));
101 _DO_OR_DIE(fprintf(file
, "P3\n%u %u\n255\n", p
->w
, p
->h
));
102 for (int y
= (int)p
->h
- 1; y
>= 0; --y
) {
103 for (int x
= 0; x
< p
->w
; ++x
) {
105 color_split(p
->pixels
[y
* p
->w
+ x
], &r
, &g
, &b
, NULL
);
106 _DO_OR_DIE(fprintf(file
, "%hhu %hhu %hhu\n", r
, g
, b
));
114 int raster_export_bmp(const raster_t
* p
, const char* filename
)
117 * This function was adapted from sample code provided with the assignment
120 FILE* file
= fopen(filename
, "wb");
122 fail
: fprintf(stderr
, "Cannot write to %s: %s\n", filename
, strerror(errno
));
126 uint16_t magicNumber
= 0x4D42;
127 uint16_t reserved0
= 0;//0x4D41;
128 uint16_t reserved1
= 0;//0x5454;
129 uint32_t dataOffset
= 54;
130 uint32_t infoHeaderSize
= 40;
131 uint32_t width
= p
->w
;
132 uint32_t height
= p
->h
;
133 uint16_t colorPlanes
= 1;
134 uint16_t bitsPerPixel
= 32;
135 uint32_t compression
= 0;
136 uint32_t dataSize
= width
* height
* bitsPerPixel
/ 8;
137 uint32_t horizontalResolution
= 2835;
138 uint32_t verticalResolution
= 2835;
139 uint32_t paletteColorCount
= 0;
140 uint32_t importantPaletteColorCount
= 0;
141 uint32_t fileSize
= 54 + dataSize
;
144 * Check the return values to avoid loud warnings.
146 _DO_OR_DIE(fwrite(&magicNumber
, sizeof(magicNumber
), 1, file
));
147 _DO_OR_DIE(fwrite(&fileSize
, sizeof(fileSize
), 1, file
));
148 _DO_OR_DIE(fwrite(&reserved0
, sizeof(reserved0
), 1, file
));
149 _DO_OR_DIE(fwrite(&reserved1
, sizeof(reserved1
), 1, file
));
150 _DO_OR_DIE(fwrite(&dataOffset
, sizeof(dataOffset
), 1, file
));
151 _DO_OR_DIE(fwrite(&infoHeaderSize
, sizeof(infoHeaderSize
), 1, file
));
152 _DO_OR_DIE(fwrite(&width
, sizeof(width
), 1, file
));
153 _DO_OR_DIE(fwrite(&height
, sizeof(height
), 1, file
));
154 _DO_OR_DIE(fwrite(&colorPlanes
, sizeof(colorPlanes
), 1, file
));
155 _DO_OR_DIE(fwrite(&bitsPerPixel
, sizeof(bitsPerPixel
), 1, file
));
156 _DO_OR_DIE(fwrite(&compression
, sizeof(compression
), 1, file
));
157 _DO_OR_DIE(fwrite(&dataSize
, sizeof(dataSize
), 1, file
));
158 _DO_OR_DIE(fwrite(&horizontalResolution
, sizeof(horizontalResolution
), 1, file
));
159 _DO_OR_DIE(fwrite(&verticalResolution
, sizeof(verticalResolution
), 1, file
));
160 _DO_OR_DIE(fwrite(&paletteColorCount
, sizeof(paletteColorCount
), 1, file
));
161 _DO_OR_DIE(fwrite(&importantPaletteColorCount
, sizeof(importantPaletteColorCount
), 1, file
));
163 size_t size
= width
* height
;
164 for (int i
= 0; i
< size
; ++i
)
167 rgbachan_t b
, g
, r
, a
;
169 color_split(p
->pixels
[i
], &argb
.r
, &argb
.g
, &argb
.b
, &argb
.a
);
170 _DO_OR_DIE(fwrite(&argb
, sizeof(argb
), 1, file
));
178 raster_t
* raster_import(const char* filename
)
181 const char* ext
= strrchr(filename
, '.');
187 if (strcmp(ext
, "bmp") == 0) {
188 return raster_import_bmp(filename
);
190 if (strcmp(ext
, "ppm") == 0) {
191 return raster_import_ppm(filename
);
195 fprintf(stderr
, "Unknown file type: %s", filename
);
199 raster_t
* raster_import_ppm(const char* filename
)
201 FILE* file
= fopen(filename
, "r");
203 fprintf(stderr
, "Cannot read from %s: %s\n", filename
, strerror(errno
));
208 if (fscanf(file
, "P3 %d %d 255 ", &w
, &h
) != 2) {
209 fprintf(stderr
, "Cannot read header from %s: %s\n", filename
, strerror(errno
));
213 raster_t
* p
= raster_alloc(w
, h
, COLOR_WHITE
);
215 for (int y
= h
- 1; y
>= 0; --y
) {
216 for (int x
= 0; x
< w
; ++x
) {
218 /* mingw32 does not like %hhu conversion type */
219 if (fscanf(file
, "%hu %hu %hu ", &r
, &g
, &b
) != 3) {
220 fprintf(stderr
, "Failed reading color values from %s: %s\n", filename
, strerror(errno
));
226 rgbachan_t r
, g
, b
, a
;
229 u
.chan
.r
= (rgbachan_t
)r
;
230 u
.chan
.g
= (rgbachan_t
)g
;
231 u
.chan
.b
= (rgbachan_t
)b
;
233 p
->pixels
[y
* w
+ x
] = color_from_rgba(u
.rgba
);
243 fprintf(stderr
, "Unexpected file format in %s: %s\n", filename
, strerror(errno
));
247 raster_t
* raster_import_bmp(const char* filename
)
249 FILE* file
= fopen(filename
, "rb");
251 fprintf(stderr
, "Cannot read from %s: %s\n", filename
, strerror(errno
));
257 uint16_t magicNumber
;
258 uint16_t reserved0
;//0x4D41;
259 uint16_t reserved1
;//0x5454;
261 uint32_t infoHeaderSize
;
264 uint16_t colorPlanes
;
265 uint16_t bitsPerPixel
;
266 uint32_t compression
;
268 uint32_t horizontalResolution
;
269 uint32_t verticalResolution
;
270 uint32_t paletteColorCount
;
271 uint32_t importantPaletteColorCount
;
276 _DO_OR_DIE(fread(&magicNumber
, sizeof(magicNumber
), 1, file
));
277 _DO_OR_DIE(fread(&fileSize
, sizeof(fileSize
), 1, file
));
278 _DO_OR_DIE(fread(&reserved0
, sizeof(reserved0
), 1, file
));
279 _DO_OR_DIE(fread(&reserved1
, sizeof(reserved1
), 1, file
));
280 _DO_OR_DIE(fread(&dataOffset
, sizeof(dataOffset
), 1, file
));
281 _DO_OR_DIE(fread(&infoHeaderSize
, sizeof(infoHeaderSize
), 1, file
));
282 _DO_OR_DIE(fread(&width
, sizeof(width
), 1, file
));
283 _DO_OR_DIE(fread(&height
, sizeof(height
), 1, file
));
284 _DO_OR_DIE(fread(&colorPlanes
, sizeof(colorPlanes
), 1, file
));
285 _DO_OR_DIE(fread(&bitsPerPixel
, sizeof(bitsPerPixel
), 1, file
));
286 _DO_OR_DIE(fread(&compression
, sizeof(compression
), 1, file
));
287 _DO_OR_DIE(fread(&dataSize
, sizeof(dataSize
), 1, file
));
288 _DO_OR_DIE(fread(&horizontalResolution
, sizeof(horizontalResolution
), 1, file
));
289 _DO_OR_DIE(fread(&verticalResolution
, sizeof(verticalResolution
), 1, file
));
290 _DO_OR_DIE(fread(&paletteColorCount
, sizeof(paletteColorCount
), 1, file
));
291 _DO_OR_DIE(fread(&importantPaletteColorCount
, sizeof(importantPaletteColorCount
), 1, file
));
293 p
= raster_alloc((int)width
, (int)height
, COLOR_WHITE
);
295 size
= width
* height
;
296 for (int i
= 0; i
< size
; ++i
)
301 rgbachan_t r
, g
, b
, a
;
304 _DO_OR_DIE(fread(&u
, sizeof(u
), 1, file
));
305 rgbachan_t t
= u
.chan
.r
;
316 p
->pixels
[i
] = color_from_rgba(u
.rgba
);
327 fprintf(stderr
, "Unexpected file format in %s: %s\n", filename
, strerror(errno
));