1 /*
2    Copyright (C) 1999/2000/2001/2002/2004 Alexandre Courbot
3    Part of the Adonthell Project <http://adonthell.nongnu.org>
4 
5    Adonthell is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    Adonthell is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with Adonthell.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 
20 /**
21  * @file   image.cc
22  * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
23  *
24  * @brief  Defines the image class.
25  *
26  *
27  */
28 
29 #include "image.h"
30 #include "pnm.h"
31 #include <iostream>
32 
33 using namespace std;
34 
image()35 image::image () : surface ()
36 {
37 }
38 
image(u_int16 l,u_int16 h,const u_int8 & scale)39 image::image (u_int16 l, u_int16 h, const u_int8 & scale) : surface (scale)
40 {
41     resize (l, h);
42 }
43 
image(SDL_Surface * s,const SDL_Color & color)44 image::image (SDL_Surface *s, const SDL_Color & color) : surface (screen::scale())
45 {
46     set_alpha(SDL_ALPHA_OPAQUE, true);
47     resize((s->w+screen::scale()-1)/screen::scale(), (s->h+screen::scale()-1)/screen::scale());
48 
49     SDL_Surface *dest = to_sw_surface(NULL);
50     SDL_SetColorKey (s, 1, SDL_MapRGB (s->format, color.r, color.g, color.b));
51     SDL_BlitSurface (s, NULL, dest, NULL);
52 
53     unlock();
54 
55     SDL_FreeSurface (dest);
56     SDL_FreeSurface (s);
57 }
58 
~image()59 image::~image ()
60 {
61 }
62 
resize(u_int16 l,u_int16 h)63 void image::resize (u_int16 l, u_int16 h)
64 {
65     surface::resize (l, h);
66 }
67 
clear()68 void image::clear ()
69 {
70     surface::clear ();
71 }
72 
get(igzstream & file)73 s_int8 image::get (igzstream& file)
74 {
75     s_int8 ret;
76 
77     u_int8 m;
78     u_int8 a;
79 
80     m << file;
81     a << file;
82 
83     ret = get_raw (file);
84     if (!ret)
85     {
86         set_mask (m);
87         set_alpha (a);
88     }
89     return ret;
90 }
91 
load(string fname)92 s_int8 image::load (string fname)
93 {
94     igzstream file (fname);
95     s_int8 ret = 0;
96 
97     if (!file.is_open ())
98         return 1;
99     ret = get (file);
100     file.close ();
101     return ret;
102 }
103 
get_raw(igzstream & file)104 s_int8 image::get_raw (igzstream& file)
105 {
106     void * rawdata;
107 
108     u_int16 l, h;
109 
110     clear ();
111 
112     l << file;
113     h << file;
114 
115     rawdata = new char[l * h * 3];
116     file.get_block (rawdata, l * h * 3);
117 
118     raw2display (rawdata, l, h);
119 
120     delete[] (char *) rawdata;
121 
122     if (!Surface) return -1;
123 
124     return 0;
125 }
126 
127 
load_raw(string fname)128 s_int8 image::load_raw (string fname)
129 {
130     igzstream file (fname);
131     s_int8 ret = 0;
132 
133     if (!file.is_open ())
134 	{
135     	std::cout << "cannot find file " << fname << std::endl;
136     	return 1;
137 	}
138     ret = get_raw (file);
139     file.close ();
140     return ret;
141 }
142 
143 
get_pnm(SDL_RWops * file)144 s_int8 image::get_pnm (SDL_RWops * file)
145 {
146     void *rawdata;
147     u_int16 l, h;
148 
149     clear ();
150 
151     rawdata = pnm::get (file, &l, &h);
152 
153     raw2display (rawdata, l, h);
154 
155     free (rawdata);
156 
157     if (!Surface) return -1;
158 
159     return 0;
160 }
161 
162 
load_pnm(string fname)163 s_int8 image::load_pnm (string fname)
164 {
165     SDL_RWops *file;
166     s_int8 ret = 0;
167 
168     file = SDL_RWFromFile (fname.c_str (), "rb");
169     if (!file)
170     {
171     	std::cout << "cannot find file " << fname << std::endl;
172     	return 1;
173     }
174     ret = get_pnm (file);
175     SDL_RWclose (file);
176     return ret;
177 }
178 
put(ogzstream & file) const179 s_int8 image::put (ogzstream& file) const
180 {
181     bool m = is_masked ();
182     s_int8 a = alpha ();
183 
184     m >> file;
185     a >> file;
186 
187     put_raw (file);
188 
189     return 0;
190 }
191 
save(string fname) const192 s_int8 image::save (string fname) const
193 {
194     ogzstream file (fname);
195     s_int8 ret = 0;
196 
197     if (!file.is_open ())
198         return 1;
199     ret = put (file);
200     file.close ();
201     return ret;
202 }
203 
put_raw(ogzstream & file) const204 s_int8 image::put_raw (ogzstream& file) const
205 {
206     length () >> file;
207     height () >> file;
208 
209     if (!length () || !height ()) return 0;
210 
211     void *rawdata = get_data(3, R_MASK, G_MASK, B_MASK, 0);
212 	file.put_block ((u_int8 *) rawdata, length () * height() * 3);
213 	free(rawdata);
214 
215     return 0;
216 }
217 
save_raw(string fname) const218 s_int8 image::save_raw (string fname) const
219 {
220     ogzstream file (fname);
221     s_int8 ret = 0;
222 
223     if (!file.is_open ())
224         return 1;
225     ret = put_raw (file);
226     file.close ();
227     return ret;
228 }
229 
put_pnm(SDL_RWops * file) const230 s_int8 image::put_pnm (SDL_RWops * file) const
231 {
232     void *rawdata = get_data(3, R_MASK, G_MASK, B_MASK, 0);
233     pnm::put (file, rawdata, length (), height ());
234     free(rawdata);
235 
236     return 0;
237 }
238 
save_pnm(string fname) const239 s_int8 image::save_pnm (string fname) const
240 {
241     SDL_RWops *file;
242     s_int8 ret = 0;
243 
244     file = SDL_RWFromFile (fname.c_str (), "wb");
245     if (!file)
246         return 1;
247     ret = put_pnm (file);
248     SDL_RWclose (file);
249     return ret;
250 }
251 
zoom(const surface & src,u_int16 l,u_int16 h,u_int16 x,u_int16 y)252 void image::zoom (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
253 {
254     // Calculate the step per pixel.
255     // While the surface positions are u_int16s, we use u_int32s for step
256     // and position during zoom, that we'll divide by 65535 ( >> 16). That
257     // way,  we can perform our zoom without having to divide two times per
258     // pixel we proceed (we can replace the divides with shift, much much
259     // faster.
260     u_int32 xstep = (u_int32) (((double) src.length () / (double) l) * 65535);
261     u_int32 ystep = (u_int32) (((double) src.height () / (double) h) * 65535);
262     u_int32 xcur;
263     u_int32 ycur;
264 
265     u_int32 col;
266 
267     lock ();
268     src.lock ();
269     ycur = 0;
270     u_int16 i, j;
271     for (j = y; j < h + y; j++)
272     {
273         xcur = 0;
274         for (i = x; i < l + x; i++)
275         {
276             col = src.get_pix ((u_int16)(xcur >> 16), (u_int16)(ycur >> 16));
277             put_pix (i, j, col);
278             xcur += xstep;
279         }
280         ycur += ystep;
281     }
282     src.unlock ();
283     unlock ();
284 }
285 
tile(const surface & src,u_int16 l,u_int16 h,u_int16 x,u_int16 y)286 void image::tile (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
287 {
288     u_int16 posx;
289     u_int16 posy;
290 
291     drawing_area da (x, y, l, h);
292 
293     for (posy = 0; posy < h; posy += src.height ())
294         for (posx = 0; posx < l; posx += src.length ())
295             src.draw (x + posx, y + posy, &da, this);
296 }
297 
brightness(const surface & src,u_int8 cont,bool proceed_mask)298 void image::brightness (const surface& src, u_int8 cont, bool proceed_mask)
299 {
300     u_int16 i, j;
301     u_int8 ir, ig, ib, ia;
302     u_int32 temp = 0;
303 
304     clear();
305     set_scale(src.scale());
306     resize (src.length (), src.height ());
307 
308     u_int16 real_height = height() * scale();
309 	u_int16 real_length = length() * scale();
310 
311     lock ();
312     src.lock ();
313 	for (j = 0; j < real_height; j++)
314 		for (i = 0; i < real_length; i++)
315         {
316             temp = src.get_pix (i, j);
317             if ((proceed_mask) || temp != screen::trans_col ())
318             {
319             	unmap_color (temp, ir, ig, ib, ia);
320                 ir = (ir * cont) >> 8;
321                 ig = (ig * cont) >> 8;
322                 ib = (ib * cont) >> 8;
323                 temp = map_color(ir, ig, ib, ia);
324             }
325             put_pix (i, j, temp);
326         }
327     src.unlock ();
328     unlock ();
329 }
330 
operator =(const image & src)331 image& image::operator = (const image& src)
332 {
333     (surface&) (*this) = (surface&) src;
334     return *this;
335 }
336 
337 
338 
339 
340 // Private methods
341 
342 
343 
raw2display(void * rawdata,u_int16 l,u_int16 h)344 void image::raw2display (void * rawdata, u_int16 l, u_int16 h)
345 {
346 	set_data(rawdata, l, h, 3, R_MASK, G_MASK, B_MASK, 0);
347 }
348