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