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 color_t
raster_uv(const raster_t
* p
, vec_t uv
)
53 uv
.x
= scal_clamp(uv
.x
, S(0.0), S(1.0));
54 uv
.y
= scal_clamp(uv
.y
, S(0.0), S(1.0));
56 int x
= (int)((scal_t
)p
->w
* uv
.x
);
57 int y
= (int)((scal_t
)p
->h
* uv
.y
);
64 return *raster_color(p
, x
, y
);
67 int raster_width(const raster_t
* p
)
72 int raster_height(const raster_t
* p
)
77 void* raster_data(const raster_t
* p
)
79 size_t size
= p
->w
* p
->h
;
80 rgba_t
* data
= (rgba_t
*)mem_alloc(size
* sizeof(rgba_t
));
82 for (int i
= 0; i
< size
; ++i
) {
83 data
[i
] = rgba_from_color(p
->pixels
[i
]);
89 void raster_clear(raster_t
* p
, color_t fill
)
91 size_t size
= p
->w
* p
->h
;
92 for (int i
= 0; i
< size
; ++i
) {
98 void raster_viewport(raster_t
* p
, int x
, int y
, int width
, int height
)
101 p
->right
= x
+ width
;
107 #define _DO_OR_DIE(X) if ((X) <= 0) goto fail
109 int raster_export_ppm(const raster_t
* p
, const char* filename
)
111 FILE* file
= fopen(filename
, "w");
113 fail
: fprintf(stderr
, "Cannot write to %s: %s\n", filename
, strerror(errno
));
117 _DO_OR_DIE(fprintf(file
, "P3\n%u %u\n255\n", p
->w
, p
->h
));
118 for (int y
= (int)p
->h
- 1; y
>= 0; --y
) {
119 for (int x
= 0; x
< p
->w
; ++x
) {
121 color_split(p
->pixels
[y
* p
->w
+ x
], &r
, &g
, &b
, NULL
);
122 _DO_OR_DIE(fprintf(file
, "%hhu %hhu %hhu\n", r
, g
, b
));
130 int raster_export_bmp(const raster_t
* p
, const char* filename
)
133 * This function was adapted from sample code provided with the assignment
136 FILE* file
= fopen(filename
, "wb");
138 fail
: fprintf(stderr
, "Cannot write to %s: %s\n", filename
, strerror(errno
));
142 uint16_t magicNumber
= 0x4D42;
143 uint16_t reserved0
= 0;//0x4D41;
144 uint16_t reserved1
= 0;//0x5454;
145 uint32_t dataOffset
= 54;
146 uint32_t infoHeaderSize
= 40;
147 uint32_t width
= p
->w
;
148 uint32_t height
= p
->h
;
149 uint16_t colorPlanes
= 1;
150 uint16_t bitsPerPixel
= 32;
151 uint32_t compression
= 0;
152 uint32_t dataSize
= width
* height
* bitsPerPixel
/ 8;
153 uint32_t horizontalResolution
= 2835;
154 uint32_t verticalResolution
= 2835;
155 uint32_t paletteColorCount
= 0;
156 uint32_t importantPaletteColorCount
= 0;
157 uint32_t fileSize
= 54 + dataSize
;
160 * Check the return values to avoid loud warnings.
162 _DO_OR_DIE(fwrite(&magicNumber
, sizeof(magicNumber
), 1, file
));
163 _DO_OR_DIE(fwrite(&fileSize
, sizeof(fileSize
), 1, file
));
164 _DO_OR_DIE(fwrite(&reserved0
, sizeof(reserved0
), 1, file
));
165 _DO_OR_DIE(fwrite(&reserved1
, sizeof(reserved1
), 1, file
));
166 _DO_OR_DIE(fwrite(&dataOffset
, sizeof(dataOffset
), 1, file
));
167 _DO_OR_DIE(fwrite(&infoHeaderSize
, sizeof(infoHeaderSize
), 1, file
));
168 _DO_OR_DIE(fwrite(&width
, sizeof(width
), 1, file
));
169 _DO_OR_DIE(fwrite(&height
, sizeof(height
), 1, file
));
170 _DO_OR_DIE(fwrite(&colorPlanes
, sizeof(colorPlanes
), 1, file
));
171 _DO_OR_DIE(fwrite(&bitsPerPixel
, sizeof(bitsPerPixel
), 1, file
));
172 _DO_OR_DIE(fwrite(&compression
, sizeof(compression
), 1, file
));
173 _DO_OR_DIE(fwrite(&dataSize
, sizeof(dataSize
), 1, file
));
174 _DO_OR_DIE(fwrite(&horizontalResolution
, sizeof(horizontalResolution
), 1, file
));
175 _DO_OR_DIE(fwrite(&verticalResolution
, sizeof(verticalResolution
), 1, file
));
176 _DO_OR_DIE(fwrite(&paletteColorCount
, sizeof(paletteColorCount
), 1, file
));
177 _DO_OR_DIE(fwrite(&importantPaletteColorCount
, sizeof(importantPaletteColorCount
), 1, file
));
179 size_t size
= width
* height
;
180 for (int i
= 0; i
< size
; ++i
)
183 rgbachan_t b
, g
, r
, a
;
185 color_split(p
->pixels
[i
], &argb
.r
, &argb
.g
, &argb
.b
, &argb
.a
);
186 _DO_OR_DIE(fwrite(&argb
, sizeof(argb
), 1, file
));
194 raster_t
* raster_import(const char* filename
)
197 const char* ext
= strrchr(filename
, '.');
203 if (strcmp(ext
, "bmp") == 0) {
204 return raster_import_bmp(filename
);
206 if (strcmp(ext
, "ppm") == 0) {
207 return raster_import_ppm(filename
);
211 fprintf(stderr
, "Unknown file type: %s", filename
);
215 raster_t
* raster_import_ppm(const char* filename
)
217 FILE* file
= fopen(filename
, "r");
219 fprintf(stderr
, "Cannot read from %s: %s\n", filename
, strerror(errno
));
224 if (fscanf(file
, "P3 %d %d 255 ", &w
, &h
) != 2) {
225 fprintf(stderr
, "Cannot read header from %s: %s\n", filename
, strerror(errno
));
229 raster_t
* p
= raster_alloc(w
, h
, COLOR_WHITE
);
231 for (int y
= h
- 1; y
>= 0; --y
) {
232 for (int x
= 0; x
< w
; ++x
) {
234 /* mingw32 does not like %hhu conversion type */
235 if (fscanf(file
, "%hu %hu %hu ", &r
, &g
, &b
) != 3) {
236 fprintf(stderr
, "Failed reading color values from %s: %s\n", filename
, strerror(errno
));
242 rgbachan_t r
, g
, b
, a
;
245 u
.chan
.r
= (rgbachan_t
)r
;
246 u
.chan
.g
= (rgbachan_t
)g
;
247 u
.chan
.b
= (rgbachan_t
)b
;
249 p
->pixels
[y
* w
+ x
] = color_from_rgba(u
.rgba
);
259 fprintf(stderr
, "Unexpected file format in %s: %s\n", filename
, strerror(errno
));
263 raster_t
* raster_import_bmp(const char* filename
)
265 FILE* file
= fopen(filename
, "rb");
267 fprintf(stderr
, "Cannot read from %s: %s\n", filename
, strerror(errno
));
273 uint16_t magicNumber
;
274 uint16_t reserved0
;//0x4D41;
275 uint16_t reserved1
;//0x5454;
277 uint32_t infoHeaderSize
;
280 uint16_t colorPlanes
;
281 uint16_t bitsPerPixel
;
282 uint32_t compression
;
284 uint32_t horizontalResolution
;
285 uint32_t verticalResolution
;
286 uint32_t paletteColorCount
;
287 uint32_t importantPaletteColorCount
;
292 _DO_OR_DIE(fread(&magicNumber
, sizeof(magicNumber
), 1, file
));
293 _DO_OR_DIE(fread(&fileSize
, sizeof(fileSize
), 1, file
));
294 _DO_OR_DIE(fread(&reserved0
, sizeof(reserved0
), 1, file
));
295 _DO_OR_DIE(fread(&reserved1
, sizeof(reserved1
), 1, file
));
296 _DO_OR_DIE(fread(&dataOffset
, sizeof(dataOffset
), 1, file
));
297 _DO_OR_DIE(fread(&infoHeaderSize
, sizeof(infoHeaderSize
), 1, file
));
298 _DO_OR_DIE(fread(&width
, sizeof(width
), 1, file
));
299 _DO_OR_DIE(fread(&height
, sizeof(height
), 1, file
));
300 _DO_OR_DIE(fread(&colorPlanes
, sizeof(colorPlanes
), 1, file
));
301 _DO_OR_DIE(fread(&bitsPerPixel
, sizeof(bitsPerPixel
), 1, file
));
302 _DO_OR_DIE(fread(&compression
, sizeof(compression
), 1, file
));
303 _DO_OR_DIE(fread(&dataSize
, sizeof(dataSize
), 1, file
));
304 _DO_OR_DIE(fread(&horizontalResolution
, sizeof(horizontalResolution
), 1, file
));
305 _DO_OR_DIE(fread(&verticalResolution
, sizeof(verticalResolution
), 1, file
));
306 _DO_OR_DIE(fread(&paletteColorCount
, sizeof(paletteColorCount
), 1, file
));
307 _DO_OR_DIE(fread(&importantPaletteColorCount
, sizeof(importantPaletteColorCount
), 1, file
));
309 if ((int)width
< 0 || (int)height
< 0) {
310 fprintf(stderr
, "Unexpected file format in %s: Try a ppm file instead\n", filename
);
314 p
= raster_alloc((int)width
, (int)height
, COLOR_WHITE
);
316 size
= width
* height
;
317 for (int i
= 0; i
< size
; ++i
)
322 rgbachan_t r
, g
, b
, a
;
325 _DO_OR_DIE(fread(&u
, sizeof(u
), 1, file
));
326 rgbachan_t t
= u
.chan
.r
;
337 p
->pixels
[i
] = color_from_rgba(u
.rgba
);
348 fprintf(stderr
, "Unexpected file format in %s: %s\n", filename
, strerror(errno
));