initial commit
[chaz/rasterize] / pixmap.c
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <string.h>
12
13 #include "pixmap.h"
14
15
16 struct pixmap
17 {
18 color_t* pixels;
19 int w;
20 int h;
21 int left, right, bottom, top;
22 mat_t modelview;
23 mat_t projection;
24 mat_t final;
25 };
26
27
28 pixmap_t* pixmap_alloc(int width, int height, color_t fill)
29 {
30 assert(0 < width && 0 < height && "zero-dimension pixmap not allowed");
31 size_t size = width * height;
32
33 pixmap_t* p = (pixmap_t*)mem_alloc(sizeof(pixmap_t));
34 p->pixels = (color_t*)mem_alloc(sizeof(color_t) * size);
35 p->w = width;
36 p->h = height;
37 p->left = p->bottom = 0;
38 p->right = width;
39 p->top = height;
40 pixmap_clear(p, fill);
41 return p;
42 }
43
44 void pixmap_destroy(pixmap_t* p)
45 {
46 mem_free(p->pixels);
47 mem_free(p);
48 }
49
50
51 void pixmap_clear(pixmap_t* p, color_t fill)
52 {
53 size_t size = p->w * p->h;
54 for (int i = 0; i < size; ++i) {
55 p->pixels[i] = fill;
56 }
57 }
58
59
60 static void _pixmap_set_transformation(pixmap_t* p)
61 {
62 /*
63 * Just including a viewport transformation in the final transformation.
64 * This could probably be faster by separating this out.
65 */
66 mat_t viewport = MAT_VIEWPORT(p->left, p->bottom, p->right - p->left, p->top - p->bottom);
67 p->final = mat_mult(p->projection, p->modelview);
68 p->final = mat_mult(viewport, p->final);
69 }
70
71
72 void pixmap_viewport(pixmap_t* p, int x, int y, int width, int height)
73 {
74 p->left = x;
75 p->right = x + width;
76 p->bottom = y;
77 p->top = y + height;
78 _pixmap_set_transformation(p);
79 }
80
81 void pixmap_modelview(pixmap_t* p, const mat_t* transform)
82 {
83 p->modelview = *transform;
84 _pixmap_set_transformation(p);
85 }
86
87 void pixmap_projection(pixmap_t* p, const mat_t* transform)
88 {
89 p->projection = *transform;
90 _pixmap_set_transformation(p);
91 }
92
93
94 #define _CHECK_WRITE(X) if ((X) <= 0) goto fail
95
96 int pixmap_export_ppm(const pixmap_t* p, const char* filename)
97 {
98 FILE* file = fopen(filename, "w");
99 if (file == NULL) {
100 fail: fprintf(stderr, "Cannot write to %s: %s\n", filename, strerror(errno));
101 return -1;
102 }
103
104 _CHECK_WRITE(fprintf(file, "P3\n%u %u\n255\n", p->w, p->h));
105 for (int y = (int)p->h - 1; y >= 0; --y) {
106 for (int x = 0; x < p->w; ++x) {
107 rgbachan_t r, g, b;
108 color_split(p->pixels[y * p->w + x], &r, &g, &b, NULL);
109 _CHECK_WRITE(fprintf(file, "%hhu %hhu %hhu\n", r, g, b));
110 }
111 }
112
113 fclose(file);
114 return 0;
115 }
116
117 int pixmap_export_bmp(const pixmap_t* p, const char* filename)
118 {
119 /*
120 * This function was adapted from sample code provided with the assignment
121 * instructions.
122 */
123 FILE* file = fopen(filename, "wb");
124 if (file == NULL) {
125 fail: fprintf(stderr, "Cannot write to %s: %s\n", filename, strerror(errno));
126 return -1;
127 }
128
129 uint16_t magicNumber = 0x4D42;
130 uint16_t reserved0 = 0;//0x4D41;
131 uint16_t reserved1 = 0;//0x5454;
132 uint32_t dataOffset = 54;
133 uint32_t infoHeaderSize = 40;
134 uint32_t width = p->w;
135 uint32_t height = p->h;
136 uint16_t colorPlanes = 1;
137 uint16_t bitsPerPixel = 32;
138 uint32_t compression = 0;
139 uint32_t dataSize = width * height * bitsPerPixel / 8;
140 uint32_t horizontalResolution = 2835;
141 uint32_t verticalResolution = 2835;
142 uint32_t paletteColorCount = 0;
143 uint32_t importantPaletteColorCount = 0;
144 uint32_t fileSize = 54 + dataSize;
145
146 /*
147 * Check the return values to avoid loud warnings.
148 */
149 _CHECK_WRITE(fwrite(&magicNumber, sizeof(magicNumber), 1, file));
150 _CHECK_WRITE(fwrite(&fileSize, sizeof(fileSize), 1, file));
151 _CHECK_WRITE(fwrite(&reserved0, sizeof(reserved0), 1, file));
152 _CHECK_WRITE(fwrite(&reserved1, sizeof(reserved1), 1, file));
153 _CHECK_WRITE(fwrite(&dataOffset, sizeof(dataOffset), 1, file));
154 _CHECK_WRITE(fwrite(&infoHeaderSize, sizeof(infoHeaderSize), 1, file));
155 _CHECK_WRITE(fwrite(&width, sizeof(width), 1, file));
156 _CHECK_WRITE(fwrite(&height, sizeof(height), 1, file));
157 _CHECK_WRITE(fwrite(&colorPlanes, sizeof(colorPlanes), 1, file));
158 _CHECK_WRITE(fwrite(&bitsPerPixel, sizeof(bitsPerPixel), 1, file));
159 _CHECK_WRITE(fwrite(&compression, sizeof(compression), 1, file));
160 _CHECK_WRITE(fwrite(&dataSize, sizeof(dataSize), 1, file));
161 _CHECK_WRITE(fwrite(&horizontalResolution, sizeof(horizontalResolution), 1, file));
162 _CHECK_WRITE(fwrite(&verticalResolution, sizeof(verticalResolution), 1, file));
163 _CHECK_WRITE(fwrite(&paletteColorCount, sizeof(paletteColorCount), 1, file));
164 _CHECK_WRITE(fwrite(&importantPaletteColorCount, sizeof(importantPaletteColorCount), 1, file));
165
166 size_t size = width * height;
167 for (int i = 0; i < size; ++i)
168 {
169 rgbachan_t a, r, g, b;
170 color_split(p->pixels[i], &r, &g, &b, &a);
171 uint32_t argb = PACK(argb, 3, a);
172 argb = PACK(argb, 2, r);
173 argb = PACK(argb, 1, g);
174 argb = PACK(argb, 0, b);
175 _CHECK_WRITE(fwrite(&argb, sizeof(argb), 1, file));
176 }
177
178 fclose(file);
179 return 0;
180 }
181
182
183 void pixmap_draw_tri(pixmap_t* p, const tri_t* triangle)
184 {
185 tri_t t = tri_transform(*triangle, p->final);
186
187 for (int y = p->bottom; y < p->top; ++y) {
188 for (int x = p->left; x < p->right; ++x) {
189 vec_t pt = vec_new((scal_t)x, (scal_t)y, S(0.0));
190 vec_t b = tri_barycentric(&t, pt);
191 if (vec_is_barycentric(b)) {
192 color_t* c = p->pixels + y * p->w + x;
193 color_t color = color_new(
194 t.a.c.r * b.x + t.b.c.r * b.y + t.c.c.r * b.z,
195 t.a.c.g * b.x + t.b.c.g * b.y + t.c.c.g * b.z,
196 t.a.c.b * b.x + t.b.c.b * b.y + t.c.c.b * b.z,
197 S(1.0)
198 );
199 *c = color;
200 }
201 }
202 }
203 }
204
This page took 0.052669 seconds and 4 git commands to generate.