The Battle for Wesnoth  1.15.12+dev
image_modifications.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Iris Morelle <shadowm2006@gmail.com>
3  Part of the Battle for Wesnoth Project https://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 #pragma once
16 
17 #include "color_range.hpp"
19 #include "sdl/surface.hpp"
20 #include "sdl/utils.hpp"
21 
22 #include <functional>
23 #include <map>
24 #include <memory>
25 
26 namespace image {
27 
28 class modification;
29 
30 /**
31  * A modified priority queue used to order image modifications.
32  * The priorities for this queue are to order modifications by priority(),
33  * then by the order they are added to the queue.
34  */
36 {
37  // Invariant for this class:
38  // At the beginning and end of each member function call, there
39  // are no empty vectors in priorities_.
40 public:
42  : priorities_()
43  {
44  }
45 
46  bool empty() const { return priorities_.empty(); }
47  void push(modification * mod);
48  void pop();
49  std::size_t size() const;
50  modification * top() const;
51 
52 private:
53  /** Map from a mod's priority() to the mods having that priority. */
54  typedef std::map<int, std::vector<std::shared_ptr<modification>>, std::greater<int>> map_type;
55  /** Map from a mod's priority() to the mods having that priority. */
56  map_type priorities_;
57 };
58 
59 /** Base abstract class for an image-path modification */
61 {
62 public:
63 
64  /** Exception thrown by the operator() when an error occurs. */
67  {
68  /**
69  * Constructor.
70  *
71  * @pre message_stream.str()[message_stream.str().size() - 1] == '\n'
72  *
73  * @param message_stream Stream with the error message regarding
74  * the failed operation.
75  */
76  imod_exception(const std::stringstream& message_stream);
77 
78  /**
79  * Constructor.
80  *
81  * @pre message[message.size() - 1] == '\n'
82  *
83  * @param message String with the error message regarding
84  * the failed operation.
85  */
86  imod_exception(const std::string& message);
87 
88  ~imod_exception() noexcept {}
89 
90  /** The error message regarding the failed operation. */
91  const std::string message;
92 
93  private:
94 
96  };
97 
98  /** Decodes modifications from a modification string */
99  static modification_queue decode(const std::string&);
100 
101  virtual ~modification() {}
102 
103  /** Applies the image-path modification on the specified surface */
104  virtual surface operator()(const surface& src) const = 0;
105 
106  /** Specifies the priority of the modification */
107  virtual int priority() const { return 0; }
108 };
109 
110 /**
111  * Recolor (RC/TC/PAL) modification.
112  * It is used not only for color-range-based recoloring ("~RC(magenta>teal)")
113  * but also for team-color-based color range selection and recoloring
114  * ("~TC(3,magenta)") and palette switches ("~PAL(000000,005000 > FFFFFF,FF00FF)").
115  */
117 {
118 public:
119  /**
120  * Default constructor.
121  */
123  : rc_map_()
124  {}
125  /**
126  * RC-map based constructor.
127  * @param recolor_map The palette switch map.
128  */
129  rc_modification(const color_range_map& recolor_map)
130  : rc_map_(recolor_map)
131  {}
132  virtual surface operator()(const surface& src) const;
133 
134  // The rc modification has a higher priority
135  virtual int priority() const { return 1; }
136 
137  bool no_op() const { return rc_map_.empty(); }
138 
139  const color_range_map& map() const { return rc_map_;}
140  color_range_map& map() { return rc_map_;}
141 
142 private:
144 };
145 
146 /**
147  * Mirror (FL) modification.
148  */
150 {
151 public:
152  /**
153  * Constructor.
154  * @param horiz Horizontal mirror flag.
155  * @param vert Vertical mirror flag.
156  */
157  fl_modification(bool horiz = false, bool vert = false)
158  : horiz_(horiz)
159  , vert_(vert)
160  {}
161  virtual surface operator()(const surface& src) const;
162 
163  void set_horiz(bool val) { horiz_ = val; }
164  void set_vert(bool val) { vert_ = val; }
165  bool get_horiz() const { return horiz_; }
166  bool get_vert() const { return vert_; }
167  /** Toggle horizontal mirror flag.
168  * @return The new flag state after toggling. */
169  bool toggle_horiz() { return((horiz_ = !horiz_)); }
170  /** Toggle vertical mirror flag.
171  * @return The new flag state after toggling. */
172  bool toggle_vert() { return((vert_ = !vert_)); }
173 
174  bool no_op() const { return ((!horiz_) && (!vert_)); }
175 
176 private:
177  bool horiz_;
178  bool vert_;
179 };
180 
181 /**
182  * Rotate (ROTATE) modification.
183  */
185 {
186 public:
187  /**
188  * Constructor.
189  *
190  * @pre zoom >= offset Otherwise the result will have empty pixels.
191  * @pre offset > 0 Otherwise the procedure will not return.
192  *
193  * @param degrees Amount of rotation (in degrees).
194  * Positive values are clockwise; negative are counter-clockwise.
195  * @param zoom The zoom level to calculate the rotation from.
196  * Greater values result in better results and increased runtime.
197  * This parameter will be ignored if @a degrees is a multiple of 90.
198  * @param offset Determines the step size of the scanning of the zoomed source.
199  * Different offsets can produce better results, try them out.
200  * Greater values result in decreased runtime.
201  * This parameter will be ignored if @a degrees is a multiple of 90.
202  * If @a offset is greater than @a zoom the result will have empty pixels.
203  */
204  rotate_modification(int degrees = 90, int zoom = 16, int offset = 8)
205  : degrees_(degrees), zoom_(zoom), offset_(offset)
206  {}
207  virtual surface operator()(const surface& src) const;
208 
209  bool no_op() const { return degrees_ % 360 == 0; }
210 
211 private:
212  int degrees_;
213  int zoom_;
214  int offset_;
215 };
216 
217 /**
218  * Grayscale (GS) modification.
219  */
221 {
222 public:
223  virtual surface operator()(const surface& src) const;
224 };
225 
226 /**
227  * Black and white (BW) modification.
228  */
230 {
231 public:
232  bw_modification(int threshold): threshold_(threshold) {}
233  virtual surface operator()(const surface& src) const;
234 private:
236 };
237 
238 /**
239  * Give to the image a sepia tint (SEPIA)
240  */
242 {
243  virtual surface operator()(const surface &src) const;
244 };
245 
246 /**
247  * Make an image negative (NEG)
248  */
250 {
251 public:
252  negative_modification(int r, int g, int b): red_(r), green_(g), blue_(b) {}
253  virtual surface operator()(const surface &src) const;
254 private:
255  int red_, green_, blue_;
256 };
257 
258 /**
259  * Plot Alpha (Alpha) modification
260  */
262 {
263 public:
264  virtual surface operator()(const surface& src) const;
265 };
266 
267 /**
268  * Wipe Alpha (Wipe_Alpha) modification
269  */
271 {
272 public:
273  virtual surface operator()(const surface& src) const;
274 };
275 
276 /**
277  * Adjust Alpha (ADJUST_ALPHA) modification
278  */
280 {
281 public:
282  adjust_alpha_modification(const std::string& formula)
283  : formula_(formula)
284  {}
285 
286  virtual surface operator()(const surface& src) const;
287 
288 private:
289  std::string formula_;
290 };
291 
292 /**
293  * Adjust Channels (CHAN) modification
294  */
296 {
297 public:
298  adjust_channels_modification(const std::vector<std::string>& formulas)
299  : formulas_(formulas)
300  {
301  if(formulas_.empty()) {
302  formulas_.push_back("red");
303  }
304  if(formulas_.size() == 1) {
305  formulas_.push_back("green");
306  }
307  if(formulas_.size() == 2) {
308  formulas_.push_back("blue");
309  }
310  if(formulas_.size() == 3) {
311  formulas_.push_back("alpha");
312  }
313  }
314 
315  virtual surface operator()(const surface& src) const;
316 
317 private:
318  std::vector<std::string> formulas_;
319 };
320 
321 /**
322  * Crop (CROP) modification.
323  */
325 {
326 public:
327  crop_modification(const SDL_Rect& slice)
328  : slice_(slice)
329  {}
330  virtual surface operator()(const surface& src) const;
331 
332  const SDL_Rect& get_slice() const
333  {
334  return slice_;
335  }
336 
337 private:
338  SDL_Rect slice_;
339 };
340 
341 /**
342  * Scale (BLIT) modification.
343  */
344 
346 {
347 public:
348  blit_modification(const surface& surf, int x, int y)
349  : surf_(surf), x_(x), y_(y)
350  {}
351  virtual surface operator()(const surface& src) const;
352 
353  const surface& get_surface() const
354  {
355  return surf_;
356  }
357 
358  int get_x() const
359  {
360  return x_;
361  }
362 
363  int get_y() const
364  {
365  return y_;
366  }
367 
368 private:
370  int x_;
371  int y_;
372 };
373 
374 /**
375  * Mask (MASK) modification.
376  */
377 
379 {
380 public:
381  mask_modification(const surface& mask, int x, int y)
382  : mask_(mask), x_(x), y_(y)
383  {}
384  virtual surface operator()(const surface& src) const;
385 
386  const surface& get_mask() const
387  {
388  return mask_;
389  }
390 
391  int get_x() const
392  {
393  return x_;
394  }
395 
396  int get_y() const
397  {
398  return y_;
399  }
400 
401 private:
403  int x_;
404  int y_;
405 };
406 
407 /**
408  * LIGHT (L) modification.
409  */
410 
412 {
413 public:
415  : surf_(surf)
416  {}
417  virtual surface operator()(const surface& src) const;
418 
419  const surface& get_surface() const
420  {
421  return surf_;
422  }
423 
424 private:
426 };
427 
428 /**
429  * Scaling modifications base class.
430  */
432 {
433 public:
434  scale_modification(int width, int height, const std::string& fn, bool use_nn)
435  : w_(width), h_(height), nn_(use_nn), fn_(fn)
436  {}
437  virtual surface operator()(const surface& src) const;
438  virtual std::pair<int,int> calculate_size(const surface& src) const = 0;
439 
440  int get_w() const
441  {
442  return w_;
443  }
444 
445  int get_h() const
446  {
447  return h_;
448  }
449 
450 private:
451  int w_, h_;
452  bool nn_;
453 
454 protected:
455  const std::string fn_;
456 };
457 
458 /**
459  * Scale exact modification. (SCALE, SCALE_SHARP)
460  */
462 {
463 public:
464  scale_exact_modification(int width, int height, const std::string& fn, bool use_nn)
465  : scale_modification(width, height, fn, use_nn)
466  {}
467  virtual std::pair<int,int> calculate_size(const surface& src) const;
468 };
469 
470 /**
471  * Scale into (SCALE_INTO) modification. (SCALE_INTO, SCALE_INTO_SHARP)
472  * Preserves aspect ratio.
473  */
475 {
476 public:
477  scale_into_modification(int width, int height, const std::string& fn, bool use_nn)
478  : scale_modification(width, height, fn, use_nn)
479  {}
480  virtual std::pair<int,int> calculate_size(const surface& src) const;
481 };
482 
483 /**
484  * xBRZ scale (xBRZ) modification
485  */
487 {
488 public:
490  : z_(z)
491  {}
492 
493  virtual surface operator()(const surface& src) const;
494 
495 private:
496  int z_;
497 };
498 
499 /**
500  * Opacity (O) modification
501  */
503 {
504 public:
505  o_modification(float opacity)
506  : opacity_(opacity)
507  {}
508  virtual surface operator()(const surface& src) const;
509 
510  float get_opacity() const
511  {
512  return opacity_;
513  }
514 
515 private:
516  float opacity_;
517 };
518 
519 /**
520  * Color-shift (CS, R, G, B) modification.
521  */
523 {
524 public:
525  cs_modification(int r, int g, int b)
526  : r_(r), g_(g), b_(b)
527  {}
528  virtual surface operator()(const surface& src) const;
529 
530  int get_r() const { return r_; }
531  int get_g() const { return g_; }
532  int get_b() const { return b_; }
533 
534 private:
535  int r_, g_, b_;
536 };
537 
538 /**
539  * Color blending (BLEND) modification
540  */
542 {
543 public:
544  blend_modification(int r, int g, int b, float a)
545  : r_(r), g_(g), b_(b), a_(a)
546  {}
547  virtual surface operator()(const surface& src) const;
548 
549  int get_r() const { return r_; }
550  int get_g() const { return g_; }
551  int get_b() const { return b_; }
552  float get_a() const { return a_; }
553 
554 private:
555  int r_, g_, b_;
556  float a_;
557 };
558 
559 /**
560  * Gaussian-like blur (BL) modification.
561  */
563 {
564 public:
565  bl_modification(int depth)
566  : depth_(depth)
567  {}
568  virtual surface operator()(const surface& src) const;
569 
570  int get_depth() const
571  {
572  return depth_;
573  }
574 
575 private:
576  int depth_;
577 };
578 
579 /**
580  * Fill background with a color (BG).
581  */
583 {
584  background_modification(const color_t& c): color_(c) {}
585  virtual surface operator()(const surface &src) const;
586 
587  const color_t& get_color() const
588  {
589  return color_;
590  }
591 
592 private:
594 };
595 
596 /**
597  * Channel swap (SWAP).
598  */
600 {
601 public:
602  swap_modification(channel r, channel g, channel b, channel a): red_(r), green_(g), blue_(b), alpha_(a) {}
603  virtual surface operator()(const surface& src) const;
604 private:
609 };
610 
611 } /* end namespace image */
const surface & get_surface() const
Grayscale (GS) modification.
Scale (BLIT) modification.
scale_modification(int width, int height, const std::string &fn, bool use_nn)
scale_exact_modification(int width, int height, const std::string &fn, bool use_nn)
blend_modification(int r, int g, int b, float a)
Fill background with a color (BG).
mask_modification(const surface &mask, int x, int y)
Gaussian-like blur (BL) modification.
const surface & get_surface() const
Adjust Channels (CHAN) modification.
Color-shift (CS, R, G, B) modification.
#define IMPLEMENT_LUA_JAILBREAK_EXCEPTION(type)
Helper macro for classes deriving from lua_jailbreak_exception.
variant b_
Definition: function.cpp:729
Adjust Alpha (ADJUST_ALPHA) modification.
Black and white (BW) modification.
#define a
A modified priority queue used to order image modifications.
adjust_channels_modification(const std::vector< std::string > &formulas)
Plot Alpha (Alpha) modification.
rc_modification()
Default constructor.
xBRZ scale (xBRZ) modification
Mask (MASK) modification.
const SDL_Rect & get_slice() const
static void decode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:180
Recolor (RC/TC/PAL) modification.
virtual int priority() const
Specifies the priority of the modification.
Make an image negative (NEG)
void push(modification *mod)
Adds mod to the queue (unless mod is nullptr).
#define b
bool toggle_vert()
Toggle vertical mirror flag.
cs_modification(int r, int g, int b)
virtual int priority() const
Specifies the priority of the modification.
std::size_t size() const
Returns the number of elements in the queue.
negative_modification(int r, int g, int b)
Crop (CROP) modification.
Color blending (BLEND) modification.
Base abstract class for an image-path modification.
std::map< int, std::vector< std::shared_ptr< modification > >, std::greater< int > > map_type
Map from a mod&#39;s priority() to the mods having that priority.
std::unordered_map< color_t, color_t > color_range_map
Definition: color_range.hpp:30
Give to the image a sepia tint (SEPIA)
Rotate (ROTATE) modification.
LIGHT (L) modification.
light_modification(const surface &surf)
double g
Definition: astarsearch.cpp:64
scale_into_modification(int width, int height, const std::string &fn, bool use_nn)
variant a_
Definition: function.cpp:729
Opacity (O) modification.
rc_modification(const color_range_map &recolor_map)
RC-map based constructor.
Wipe Alpha (Wipe_Alpha) modification.
blit_modification(const surface &surf, int x, int y)
bool toggle_horiz()
Toggle horizontal mirror flag.
Functions to load and save images from/to disk.
modification * top() const
Returns the top element in the queue .
map_type priorities_
Map from a mod&#39;s priority() to the mods having that priority.
Scale into (SCALE_INTO) modification.
adjust_alpha_modification(const std::string &formula)
rotate_modification(int degrees=90, int zoom=16, int offset=8)
Constructor.
void pop()
Removes the top element from the queue.
swap_modification(channel r, channel g, channel b, channel a)
const surface & get_mask() const
mock_char c
std::size_t w_
Exception thrown by the operator() when an error occurs.
Mirror (FL) modification.
Base class for exceptions that want to be thrown &#39;through&#39; lua.
fl_modification(bool horiz=false, bool vert=false)
Constructor.
Scaling modifications base class.
crop_modification(const SDL_Rect &slice)
channel
Definition: utils.hpp:145
const std::string message
The error message regarding the failed operation.
const color_range_map & map() const