The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
exploder_utils.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2004 - 2016 by Philippe Plantier <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org
4 
5  This program 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  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "exploder_utils.hpp"
16 #include "game_config.hpp"
18 #include <png.h>
19 #include <zlib.h>
20 
22  : x(0)
23  , y(0)
24 {
25  std::vector<std::string> items = utils::split(s);
26  if(items.size() == 2) {
27  x = atoi(items[0].c_str());
28  y = atoi(items[1].c_str());
29  }
30 }
31 
33  : x(0)
34  , y(0)
35  , w(0)
36  , h(0)
37 {
38  std::vector<std::string> items = utils::split(s);
39  if(items.size() == 4) {
40  x = atoi(items[0].c_str());
41  y = atoi(items[1].c_str());
42  w = atoi(items[2].c_str());
43  h = atoi(items[3].c_str());
44  }
45 }
46 
48 {
49  // return ".";
50  return game_config::path + "/images/tools/exploder";
51 }
52 
54 {
55  return game_config::path + "/data/tools/exploder";
56 }
57 
58 //on pixels where mask is not white, overwrite dest with src. Mask and dest are
59 //translated to the position (x,y) on dest.
60 //All surfaces are supposed to be neutral surfaces, mask and src are supposed
61 //to be of identical size.
63 {
64  surface_lock dest_lock(dest);
65  surface_lock src_lock(src);
66  surface_lock mask_lock(mask);
67 
68  Uint32* dest_beg = dest_lock.pixels();
69  Uint32* src_beg = src_lock.pixels();
70  Uint32* mask_beg = mask_lock.pixels();
71 
72  size_t small_shift_before;
73  size_t small_shift_after;
74  size_t dest_shift;
75  size_t src_width = src->w;
76  size_t src_height = src->h;
77 
78  if(x < 0) {
79  small_shift_before = -x;
80  if (src_width < small_shift_before)
81  return;
82  src_width -= small_shift_before;
83  x = 0;
84  } else {
85  small_shift_before = 0;
86  }
87 
88  if(x + src_width <= unsigned(dest->w)) {
89  small_shift_after = 0;
90  } else {
91  small_shift_after = src_width - (dest->w - x);
92  src_width = dest->w - x;
93  }
94 
95  if(y >= 0) {
96  dest_beg += dest->w * y + x;
97  } else {
98  src_beg += (-y) * src->w;
99  mask_beg += (-y) * mask->w;
100  dest_beg += x;
101  if (src_height < static_cast<size_t>(-y))
102  return;
103  src_height += y;
104  y = 0;
105  }
106 
107  if(y + src_height > unsigned(dest->h)) {
108  src_height = dest->h - y;
109  }
110 
111  dest_shift = dest->w - src_width;
112 
113  for(size_t j = 0; j < src_height; ++j) {
114  src_beg += small_shift_before;
115  mask_beg += small_shift_before;
116 
117  for(size_t i = 0; i < src_width; ++i) {
118  //Assuming here alpha mask is 0xff000000
119  if((*mask_beg & 0x00ffffff) != 0x00ffffff) {
120  *dest_beg = *src_beg;
121  }
122  ++dest_beg;
123  ++src_beg;
124  ++mask_beg;
125  }
126 
127  src_beg += small_shift_after;
128  mask_beg += small_shift_after;
129  dest_beg += dest_shift;
130  }
131 }
132 
133 
134 //returns true if the image is empty. the surface surf is considered to be a
135 //neutral surface.
137 {
138  //an image is considered empty if
139  // * all its pixels have 0 alpha, OR
140  // * all of its pixels have the same color (and the same alpha)
141 
142  surface_lock lock(surf);
143 
144  Uint32* beg = lock.pixels();
145  Uint32* end = beg + surf->w*surf->h;
146 
147  Uint32 color = *beg;
148 
149  while(beg != end) {
150  if((*beg & 0xff000000) != 0 && (*beg != color))
151  return false;
152 
153  ++beg;
154  }
155  return true;
156 }
157 
158 
159 namespace {
160  struct rgba {
161  Uint8 r;
162  Uint8 g;
163  Uint8 b;
164  Uint8 a;
165  };
166 }
167 
168 //saves the given SDL structure into a given filename.
169 void save_image(surface surf, const std::string &filename)
170 {
171  //opens the actual file
172  const util::scoped_FILE file(fopen(filename.c_str(),"wb"));
173 
174  //initializes PNG write structures
175  //TODO: review whether providing nullptr error handlers is something
176  //sensible
177  png_struct* png_ptr = png_create_write_struct
178  (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
179  if(!png_ptr)
180  throw exploder_failure("Unable to initialize the png write structure");
181 
182  png_info* info_ptr = png_create_info_struct(png_ptr);
183  if(!info_ptr) {
184  png_destroy_write_struct(&png_ptr, nullptr);
185  throw exploder_failure("Unable to initialize the png info structure");
186  }
187 
188  //instructs the PNG library to use the open file
189  png_init_io(png_ptr, file);
190 
191  //sets compression level to the maximum
192  png_set_compression_level(png_ptr,
193  Z_BEST_COMPRESSION);
194 
195  //configures the header
196  png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h,
197  8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
198  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
199 
200  //puts the actual image data in the row_pointers array
201  png_byte **row_pointers = new png_byte *[surf->h];
202  surface_lock lock(surf);
203 
204  //converts the data to the RGBA format. We cannot pass SDL data
205  //directly to the png lib, even if we know its pixel format, because of
206  //endianness problems.
207  util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]);
208 
209  Uint32 *surf_data = lock.pixels();
210  int pos = 0;
211  for(int y = 0; y < surf->h; ++y) {
212  row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos);
213  for(int x = 0; x < surf->w; ++x) {
214  Uint8 red, green, blue, alpha;
215  SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha);
216  rgba_data[pos].r = red;
217  rgba_data[pos].g = green;
218  rgba_data[pos].b = blue;
219  rgba_data[pos].a = alpha;
220  pos++;
221  surf_data++;
222  }
223  }
224  png_set_rows(png_ptr, info_ptr, row_pointers);
225 
226  //writes the actual image data
227  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
228 
229  //cleans everything
230  png_write_end(png_ptr, info_ptr);
231  png_destroy_write_struct(&png_ptr, &info_ptr);
232  delete [] row_pointers;
233 }
234 
int pos
Definition: formula.cpp:800
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
GLenum src
Definition: glew.h:2392
const std::vector< std::string > items
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
This class has identical behavior to scoped_ptr, except it manages heap-allocated arrays instead of h...
std::string get_exploder_dir()
GLuint GLuint end
Definition: glew.h:1221
GLclampf GLclampf blue
Definition: glew.h:1488
GLclampf green
Definition: glew.h:1488
void masked_overwrite_surface(surface dest, surface src, surface mask, int x, int y)
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1858
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
A class template, scoped_resource, designed to implement the Resource Acquisition Is Initialization (...
GLclampf GLclampf GLclampf alpha
Definition: glew.h:1488
std::string path
void save_image(surface surf, const std::string &filename)
GLenum GLint GLuint mask
Definition: glew.h:1813
Helper class for pinning SDL surfaces into memory.
Definition: utils.hpp:439
surf
Definition: filter.cpp:143
GLuint color
Definition: glew.h:5801
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:5910
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
#define g
Definition: glew.h:12730
Uint32 * pixels()
Definition: utils.hpp:444
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
GLdouble s
Definition: glew.h:1358
std::string get_mask_dir()
GLsizei const GLcharARB ** string
Definition: glew.h:4503
bool image_empty(surface surf)