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