Advanced Strategic Command
fieldimageloader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  textfile_evaluation.cpp - description
3  -------------------
4  begin : Thu Oct 06 2002
5  copyright : (C) 2002 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <vector>
19 #include <algorithm>
20 #include <iostream>
21 #include <SDL_image.h>
22 #include <boost/regex.hpp>
23 
24 #include "global.h"
25 #include "ascstring.h"
26 #include "fieldimageloader.h"
27 #include "typen.h"
28 #include "graphics/blitter.h"
29 
30 #include "basestreaminterface.h"
31 #include "stringtokenizer.h"
32 #include "graphics/surface2png.h"
33 
34 
35 const char* fileNameDelimitter = " =*/+<>,";
36 
37 
38 void snowify( Surface& s, bool adaptive )
39 {
40  if ( !s.valid() )
41  return;
42 
43  if ( s.GetPixelFormat().BitsPerPixel() != 32 )
44  return;
45 
46 
47  const int targetWhite = 210;
48 
49  float avg = 0;
50  if ( adaptive ) {
51  for ( int y = 0; y < s.h(); ++y ) {
52  const char* c = (char*) s.pixels();
53  c += y * s.pitch();
54  for ( int x = 0; x < s.w(); ++x ) {
55  uint32_t* i = (uint32_t*) c;
56  avg += ((*i >> s.GetPixelFormat().Rshift()) & 0xff )
57  + ((*i >> s.GetPixelFormat().Gshift()) & 0xff )
58  + ((*i >> s.GetPixelFormat().Bshift()) & 0xff ) ;
59  c += 4;
60  }
61  }
62 
63  avg /= float(s.h() * s.w() * 3);
64  } else
65  avg = 150;
66 
67  for ( int y = 0; y < s.h(); ++y ) {
68  char* c = (char*) s.pixels();
69  c += y * s.pitch();
70  for ( int x = 0; x < s.w(); ++x ) {
71  uint32_t* i = (uint32_t*) c;
72  if ( ((*i >> s.GetPixelFormat().Ashift()) & 0xff ) != Surface::transparent ) {
73  int v = ((*i >> s.GetPixelFormat().Rshift()) & 0xff )
74  + ((*i >> s.GetPixelFormat().Gshift()) & 0xff )
75  + ((*i >> s.GetPixelFormat().Bshift()) & 0xff ) ;
76  v /= 3;
77 
78  int nv = targetWhite + ( v - int(avg)) * (255-targetWhite) / 64;
79  if ( nv > 255)
80  nv = 255;
81  if ( nv < 0 )
82  nv = 0;
83 
84  *i = (nv << s.GetPixelFormat().Rshift()) | (nv << s.GetPixelFormat().Gshift() ) | (nv << s.GetPixelFormat().Bshift()) | (*i & s.GetPixelFormat().Amask() );
85  }
86  c += 4;
87  }
88  }
89 }
90 
91 bool imageEmpty( const Surface& s )
92 {
93  bool allWhite = true;
94  bool allTransparent = true;
95  int amask = s.GetPixelFormat().Amask();
96  int areference = Surface::transparent << s.GetPixelFormat().Ashift();
97 
98  int colmask = s.GetPixelFormat().Rmask() | s.GetPixelFormat().Gmask() | s.GetPixelFormat().Bmask();
99  int colref = (0xff << s.GetPixelFormat().Rshift()) | (0xff << s.GetPixelFormat().Gshift()) | (0xff << s.GetPixelFormat().Bshift());
100 
101  for ( int y = 0; y < s.h(); ++y ) {
102  const char* c = (char*) s.pixels();
103  c += y * s.pitch();
104  for ( int x = 0; x < s.w(); ++x ) {
105  const uint32_t* i = (uint32_t*) c;
106  if( (*i & amask) != areference )
107  allTransparent = false;
108 
109  if ( (*i & colmask) != colref )
110  allWhite = false;
111 
112  c += 4;
113  }
114  if ( !allWhite && !allTransparent )
115  return false;
116  }
117  return allWhite || allTransparent;
118 }
119 
120 vector<Surface> loadASCFieldImageArray ( const ASCString& file, int num )
121 {
122  vector<Surface> images;
123 
124  tnfilestream fs ( file, tnstream::reading );
125 
126  Surface s ( IMG_Load_RW ( SDL_RWFromStream( &fs ), 1));
127  if ( !s.valid() )
128  fatalError("could not read image " + file );
129 
130  if ( s.GetPixelFormat().BitsPerPixel() == 8 )
132 
133 
134  int depth = s.GetPixelFormat().BitsPerPixel();
135 
136  for ( int i = 0; i < num; i++ ) {
137  int x1 = (i % 10) * 100;
138  int y1 = (i / 10) * 100;
139  if ( depth > 8 && depth < 32 )
140  depth = 32;
141 
143 
144  if ( s2.GetPixelFormat().BitsPerPixel() != 8 || s.GetPixelFormat().BitsPerPixel() != 8 ) {
145 
146  bool colorKeyAllowed = false;
147  static boost::regex pcx( ".*\\.pcx$");
148  boost::smatch what;
149  if( boost::regex_match( copytoLower(file) , what, pcx)) {
150  // warningMessage("Truecolor PCX image detected: " + file);
151  colorKeyAllowed = true;
152  }
153 
154  if ( s.GetPixelFormat().BitsPerPixel() == 32 ) {
156  blitter.setSrcRectangle(SDLmm::SRect(SPoint(x1,y1),fieldsizex,fieldsizey));
157  blitter.blit( s, s2, SPoint(0,0) );
158  } else {
159  s2.Blit( s, SDLmm::SRect(SPoint(x1,y1),fieldsizex,fieldsizey), SPoint(0,0));
160  }
161  applyLegacyFieldMask(s2,0,0, colorKeyAllowed);
162  if ( colorKeyAllowed )
164 
165  s2.detectColorKey();
166  if ( depth != 32 || imageEmpty(s2))
167  images.push_back( Surface() );
168  else
169  images.push_back ( s2 );
170 
171  } else {
172  // we don't want any transformations from one palette to another; we just assume that all 8-Bit images use the same colorspace
174  blitter.setSrcRectangle(SDLmm::SRect(SPoint(x1,y1),fieldsizex,fieldsizey));
175  blitter.blit( s, s2, SPoint(0,0) );
176  applyFieldMask(s2);
177  s2.detectColorKey();
178  images.push_back ( s2 );
179  }
180  }
181  return images;
182 }
183 
184 Surface loadASCFieldImage ( const ASCString& file, bool applyFieldMaskToImage )
185 {
186  StringTokenizer st ( file, fileNameDelimitter );
187  FileName fn = st.getNextToken();
188  fn.toLower();
189 
190  displayLogMessage ( 6, "loading file " + file + "\n" );
191 
192  if ( fn.suffix() == "png" ) {
193  SDLmm::Surface* s = NULL;
194  do {
195  tnfilestream fs ( fn, tnstream::reading );
196  RWOPS_Handler rwo( SDL_RWFromStream( &fs ) );
197  SDLmm::Surface s2 ( IMG_LoadPNG_RW ( rwo.Get() ));
198  rwo.Close();
199  // s2.SetAlpha ( SDL_SRCALPHA, SDL_ALPHA_OPAQUE );
200  if ( !s )
201  s = new SDLmm::Surface ( s2 );
202  else {
203  int res = s->Blit ( s2 );
204  if ( res < 0 )
205  warningMessage ( "ImageProperty::operation_eq - couldn't blit surface "+fn);
206  }
207 
208  fn = st.getNextToken();
209  } while ( !fn.empty() );
210  if ( s ) {
211  Surface s3( *s );
212  if ( applyFieldMaskToImage )
213  applyFieldMask(s3,0,0,false);
214 
215  delete s;
216  return s3;
217  } else
218  return Surface();
219 
220  } else
221  if ( fn.suffix() == "pcx" ) {
222  SDL_Surface* surface;
223  {
224  tnfilestream fs ( fn, tnstream::reading );
225 
226  RWOPS_Handler rwo ( SDL_RWFromStream( &fs ));
227  surface = IMG_LoadPCX_RW ( rwo.Get() );
228  rwo.Close();
229  }
230 
231  if ( !surface )
232  errorMessage( "error loading file " + fn );
233 
234  Surface s ( surface );
235 
236  if ( s.GetPixelFormat().BitsPerPixel() == 8)
237  s.SetColorKey( SDL_SRCCOLORKEY, 255 );
238  /*
239  else
240  s.SetColorKey( SDL_SRCCOLORKEY, 0xfefefe );
241  s.SetAlpha(SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
242  */
243 
244  fn = st.getNextToken();
245  while ( !fn.empty() ) {
246  tnfilestream fs ( fn, tnstream::reading );
247  RWOPS_Handler rwo( SDL_RWFromStream( &fs ) );
248  SDLmm::Surface s2 ( IMG_LoadPNG_RW ( rwo.Get() ));
249  rwo.Close();
250  int res = s.Blit ( s2 );
251  if ( res < 0 )
252  warningMessage ( "ImageProperty::operation_eq - couldn't blit surface "+fn);
253 
254  fn = st.getNextToken();
255  }
256 
257 
258  if ( applyFieldMaskToImage )
259  if ( s.w() >= fieldsizex && s.h() >= fieldsizey )
260  applyFieldMask(s,0,0,false);
261 
262  return s;
263  }
264  throw ASCexception();
265 }
266 
267 
vector< Surface > loadASCFieldImageArray(const ASCString &file, int num)
ASCString & toLower()
Definition: ascstring.cpp:36
void snowify(Surface &s, bool adaptive)
void blit(const Surface &src, Surface &dst, SPoint dstPos)
Definition: blitter.h:349
void Close()
Definition: basestrm.h:55
static const Uint32 transparent
Definition: surface.h:65
Surface loadASCFieldImage(const ASCString &file, bool applyFieldMaskToImage)
void warningMessage(const ASCString &str)
bool imageEmpty(const Surface &s)
static Surface createSurface(int width, int height, SDLmm::Color color=255)
Definition: surface.cpp:387
This class handles filenames. All operations that work on filenames will be added here...
Definition: basestrm.h:667
Global platform dependant definitions. This file just branches to the platform specific files in thei...
void ColorKey2AlphaChannel()
Definition: surface.cpp:734
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
ASCString copytoLower(const ASCString &String)
Definition: ascstring.cpp:167
#define fieldsizey
Definition: typen.h:441
void applyFieldMask(Surface &s, int x, int y, bool detecColorKey)
Definition: surface.cpp:593
A simple string tokenizer.
void displayLogMessage(int msgVerbosity, const char *message,...)
void applyLegacyFieldMask(Surface &s, int x, int y, bool detectColorKey)
applies a field mask that uses FEFEFE Color as Colorkey to load old images
Definition: surface.cpp:611
ASCString getNextToken()
const char * fileNameDelimitter
SDL_RWops * Get()
Definition: basestrm.h:54
ASCString suffix()
return the suffix of the file or an empty string if the file doesn't have a suffix.
Definition: basestrm.cpp:2631
#define fieldsizex
Definition: typen.h:440
SDLmm::SPoint SPoint
Definition: surface.h:27
void errorMessage(const ASCString &string)
void assignDefaultPalette()
assigns the default ASC palette to the surface (only for 8 Bit surfaces)
Definition: surface.cpp:429
This String Tokenizer is NOT intended to be a general purpose tool. It is exclusively used by the Tex...
SDL_RWops * SDL_RWFromStream(tnstream *stream)
Definition: basestrm.cpp:693
void fatalError(const ASCString &string)
void detectColorKey(bool RLE=false)
tries to automatically detect the color key of the surface
Definition: surface.cpp:493
The standard interface for ASC streams. This is the parent class for all kinds of streams: normal fil...