ada337d245a5452869c8ad463b35668c3a474f62
[winnie] / src / pixmap.cc
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include "pixmap.h"
5
6 Pixmap::Pixmap()
7 {
8         width = height = 0;
9         pixels = 0;
10 }
11
12 Pixmap::Pixmap(const Pixmap &pixmap)
13 {
14         width = height = 0;
15         pixels = 0;
16         set_image(pixmap.width, pixmap.height, pixmap.pixels);
17 }
18
19 Pixmap &Pixmap::operator=(const Pixmap &pixmap)
20 {
21         if(this != &pixmap) {
22                 set_image(pixmap.width, pixmap.height, pixmap.pixels);
23         }
24
25         return *this;
26 }
27
28 Pixmap::~Pixmap()
29 {
30         if(pixels) {
31                 delete [] pixels;
32         }
33 }
34
35 int Pixmap::get_width() const
36 {
37         return width;
38 }
39
40 int Pixmap::get_height() const
41 {
42         return height;
43 }
44
45 Rect Pixmap::get_rect() const
46 {
47         Rect rect(0, 0, width, height);
48         return rect;
49 }
50
51 bool Pixmap::set_image(int x, int y, unsigned char *pix)
52 {
53         delete [] pixels;
54
55         pixels = new unsigned char[x * y * 4];
56         width = x;
57         height = y;
58
59         if(pix) {
60                 memcpy(pixels, pix, x * y * 4);
61         }
62         return true;
63 }
64
65 const unsigned char *Pixmap::get_image() const
66 {
67         return pixels;
68 }
69
70 unsigned char *Pixmap::get_image()
71 {
72         return pixels;
73 }
74
75 bool Pixmap::load(const char *fname)
76 {
77         FILE *fp;
78         int hdrline = 0;
79
80         if(!(fp = fopen(fname, "rb"))) {
81                 fprintf(stderr, "failed to open pixmap: %s: %s\n", fname, strerror(errno));
82                 return false;
83         }
84
85         /* read ppm header */
86         while(hdrline < 3) {
87                 char buf[64];
88
89                 if(!fgets(buf, sizeof buf, fp))
90                         goto err;
91                 
92                 /* skip comments */
93                 if(buf[0] == '#')
94                         continue;
95
96                 switch(hdrline++) {
97                 case 0:
98                         /* first header line should be P6 */
99                         if(strcmp(buf, "P6\n") != 0)
100                                 goto err;
101                         break;
102
103                 case 1:
104                         /* second header line contains the pixmap dimensions */
105                         if(sscanf(buf, "%d %d", &width, &height) != 2)
106                                 goto err;
107                         break;
108                 }
109         }
110
111         set_image(width, height, 0);
112
113         for(int i=0; i<width * height * 4; i++) {
114                 int c;
115                 if(i % 4 != 3) {
116                         c = fgetc(fp);
117                         if(c < 0)
118                                 goto err;
119                 }
120                 else {
121                         c = 255;
122                 }
123                 pixels[i] = c;
124         }
125         fclose(fp);
126         return true;
127
128 err:
129         fprintf(stderr, "failed to load pixmap: %s\n", fname);
130         fclose(fp);
131         return false;
132 }
133
134 bool Pixmap::save(const char *fname) const
135 {
136         if(!pixels) {
137                 return false;
138         }
139
140         FILE *fp = fopen(fname, "wb");
141         if(!fp) {
142                 fprintf(stderr, "failed to save pixmap: %s: %s\n", fname, strerror(errno));
143                 return false;
144         }
145
146         fprintf(fp, "P6\n%d %d\n255\n", width, height);
147
148         for(int i=0; i<width * height; i++) {
149                 fputc(pixels[i * 4], fp);
150                 fputc(pixels[i * 4 + 1], fp);
151                 fputc(pixels[i * 4 + 2], fp);
152         }
153
154         fclose(fp);
155         return true;
156 }