1 /*
2 * img.cc - Game image object (255 colours + transparency)
3 * AYM 2000-06-13
4 */
5
6
7 /*
8 This file is part of Yadex.
9
10 Yadex incorporates code from DEU 5.21 that was put in the public domain in
11 1994 by Rapha�l Quinet and Brendon Wyber.
12
13 The rest of Yadex is Copyright � 1997-2003 Andr� Majorel and others.
14
15 This program is free software; you can redistribute it and/or modify it under
16 the terms of the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any later
18 version.
19
20 This program is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along with
25 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
26 Place, Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29
30 #include "yadex.h"
31 #include "help1.h"
32 #include "img.h"
33 #include "wadfile.h"
34 #include "wads.h"
35
36
37 // Holds the private data members
38 class Img_priv
39 {
40 public:
Img_priv()41 Img_priv () { buf = 0; width = 0; height = 0; opaque = false; }
~Img_priv()42 ~Img_priv () { if (buf != 0) delete[] buf; }
43 img_pixel_t *buf;
44 img_dim_t width;
45 img_dim_t height;
46 bool opaque;
47 };
48
49
50 /*
51 * Img::Img - default constructor
52 *
53 * The new image is a null image.
54 */
Img()55 Img::Img ()
56 {
57 p = new Img_priv;
58 }
59
60
61 /*
62 * Img::Img - constructor with dimensions
63 *
64 * The new image is set to the specified dimensions.
65 */
Img(img_dim_t width,img_dim_t height,bool opaque)66 Img::Img (img_dim_t width, img_dim_t height, bool opaque)
67 {
68 p = new Img_priv;
69 resize (width, height);
70 set_opaque (opaque);
71 }
72
73
74 /*
75 * Img::~Img - dtor
76 */
~Img()77 Img::~Img ()
78 {
79 delete p;
80 }
81
82
83 /*
84 * Img::is_null - return true iff this is a null image
85 */
is_null() const86 bool Img::is_null () const
87 {
88 return p->buf == 0;
89 }
90
91
92 /*
93 * Img::width - return the current width
94 *
95 * If the image is null, return 0.
96 */
width() const97 img_dim_t Img::width () const
98 {
99 return p->width;
100 }
101
102
103 /*
104 * Img::height - return the current height
105 *
106 * If the image is null, return 0.
107 */
height() const108 img_dim_t Img::height () const
109 {
110 return p->height;
111 }
112
113
114 /*
115 * Img::buf - return a const pointer on the buffer
116 *
117 * If the image is null, return a null pointer.
118 */
buf() const119 const img_pixel_t *Img::buf () const
120 {
121 return p->buf;
122 }
123
124
125 /*
126 * Img::wbuf - return a writable pointer on the buffer
127 *
128 * If the image is null, return a null pointer.
129 */
wbuf()130 img_pixel_t *Img::wbuf ()
131 {
132 return p->buf;
133 }
134
135
136 /*
137 * Img::clear - clear the image
138 */
clear()139 void Img::clear ()
140 {
141 if (p->buf != 0)
142 memset (p->buf, IMG_TRANSP, p->width * p->height);
143 }
144
145
146 /*
147 * Img::set_opaque - set or clear the opaque flag
148 */
set_opaque(bool opaque)149 void Img::set_opaque (bool opaque)
150 {
151 p->opaque = opaque;
152 }
153
154
155 /*
156 * Img::resize - resize the image
157 *
158 * If either dimension is zero, the image becomes a null
159 * image.
160 */
resize(img_dim_t width,img_dim_t height)161 void Img::resize (img_dim_t width, img_dim_t height)
162 {
163 if (width == p->width && height == p->height)
164 return;
165
166 // Unallocate old buffer
167 if (p->buf != 0)
168 {
169 delete[] p->buf;
170 p->buf = 0;
171 }
172
173 // Is it a null image ?
174 if (width == 0 || height == 0)
175 {
176 p->width = 0;
177 p->height = 0;
178 return;
179 }
180
181 // Allocate new buffer
182 p->width = width;
183 p->height = height;
184 p->buf = new img_pixel_t[width * height + 10]; // Some slack
185 clear ();
186 }
187
188
189 /*
190 * Img::save - save an image to file in packed PPM format
191 *
192 * Return 0 on success, non-zero on failure
193 *
194 * If an error occurs, errno is set to:
195 * - ECHILD if PLAYPAL could not be loaded
196 * - whatever fopen() or fclose() set it to
197 */
save(const char * filename) const198 int Img::save (const char *filename) const
199 {
200 int rc = 0;
201 FILE *fp = 0;
202
203 // Load palette 0 from PLAYPAL
204 MDirPtr dir = FindMasterDir (MasterDir, "PLAYPAL");
205 if (dir == 0)
206 {
207 errno = ECHILD;
208 return 1;
209 }
210 unsigned char *pal = new unsigned char[768];
211 dir->wadfile->seek (dir->dir.start);
212 if (dir->wadfile->error ())
213 {
214 /*warn ("%s: can't seek to %lXh\n",
215 dir->wadfile->filename, (unsigned long) ftell (dir->wadfile->fp));
216 warn ("PLAYPAL: seek error\n");*/
217 rc = 1;
218 errno = ECHILD;
219 goto byebye;
220 }
221 dir->wadfile->read_bytes (pal, 768);
222 if (dir->wadfile->error ())
223 {
224 /*warn ("%s: read error", dir->wadfile->where ());
225 warn ("PLAYPAL: read error\n");*/
226 rc = 1;
227 errno = ECHILD;
228 goto byebye;
229 }
230
231 // Create PPM file
232 fp = fopen (filename, "wb");
233 if (fp == NULL)
234 {
235 rc = 1;
236 goto byebye;
237 }
238 fputs ("P6\n", fp);
239 fprintf (fp, "# %s\n", what ());
240 fprintf (fp, "%d %d 255\n", p->width, p->height);
241 {
242 const img_pixel_t *pix = p->buf;
243 const img_pixel_t *pixmax = pix + (unsigned long) p->width * p->height;
244 for (; pix < pixmax; pix++)
245 {
246 if (*pix == IMG_TRANSP && ! p->opaque)
247 {
248 putc ( 0, fp); // DeuTex convention, rgb:0/2f/2f
249 putc (47, fp);
250 putc (47, fp);
251 }
252 else
253 {
254 putc (pal[3 * *pix ], fp);
255 putc (pal[3 * *pix + 1], fp);
256 putc (pal[3 * *pix + 2], fp);
257 }
258 }
259 }
260 if (ferror (fp))
261 rc = 1;
262
263 byebye:
264 if (fp != 0)
265 if (fclose (fp))
266 rc = 1;
267 delete[] pal;
268 return rc;
269 }
270
271
272