The Battle for Wesnoth  1.19.0+dev
image_modifications.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2024
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(std::unique_ptr<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::unique_ptr<modification>>, std::greater<int>> map_type;
56  /** Map from a mod's priority() to the mods having that priority. */
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. */
66  struct imod_exception final
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_;}
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  * Crop transparent padding (CROP_TRANSPARENCY) modification.
229  */
231 {
232 public:
233  virtual surface operator()(const surface& src) const;
234 };
235 
236 /**
237  * Black and white (BW) modification.
238  */
240 {
241 public:
242  bw_modification(int threshold): threshold_(threshold) {}
243  virtual surface operator()(const surface& src) const;
244 private:
246 };
247 
248 /**
249  * Give to the image a sepia tint (SEPIA)
250  */
252 {
253  virtual surface operator()(const surface &src) const;
254 };
255 
256 /**
257  * Make an image negative (NEG)
258  */
260 {
261 public:
262  negative_modification(int r, int g, int b): red_(r), green_(g), blue_(b) {}
263  virtual surface operator()(const surface &src) const;
264 private:
266 };
267 
268 /**
269  * Plot Alpha (Alpha) modification
270  */
272 {
273 public:
274  virtual surface operator()(const surface& src) const;
275 };
276 
277 /**
278  * Wipe Alpha (Wipe_Alpha) modification
279  */
281 {
282 public:
283  virtual surface operator()(const surface& src) const;
284 };
285 
286 /**
287  * Adjust Alpha (ADJUST_ALPHA) modification
288  */
290 {
291 public:
292  adjust_alpha_modification(const std::string& formula)
293  : formula_(formula)
294  {}
295 
296  virtual surface operator()(const surface& src) const;
297 
298 private:
299  std::string formula_;
300 };
301 
302 /**
303  * Adjust Channels (CHAN) modification
304  */
306 {
307 public:
308  adjust_channels_modification(const std::vector<std::string>& formulas)
309  : formulas_(formulas)
310  {
311  if(formulas_.empty()) {
312  formulas_.push_back("red");
313  }
314  if(formulas_.size() == 1) {
315  formulas_.push_back("green");
316  }
317  if(formulas_.size() == 2) {
318  formulas_.push_back("blue");
319  }
320  if(formulas_.size() == 3) {
321  formulas_.push_back("alpha");
322  }
323  }
324 
325  virtual surface operator()(const surface& src) const;
326 
327 private:
328  std::vector<std::string> formulas_;
329 };
330 
331 /**
332  * Crop (CROP) modification.
333  */
335 {
336 public:
337  crop_modification(const SDL_Rect& slice)
338  : slice_(slice)
339  {}
340  virtual surface operator()(const surface& src) const;
341 
342  const SDL_Rect& get_slice() const
343  {
344  return slice_;
345  }
346 
347 private:
348  SDL_Rect slice_;
349 };
350 
351 /**
352  * Scale (BLIT) modification.
353  */
354 
356 {
357 public:
358  blit_modification(const surface& surf, int x, int y)
359  : surf_(surf), x_(x), y_(y)
360  {}
361  virtual surface operator()(const surface& src) const;
362 
363  const surface& get_surface() const
364  {
365  return surf_;
366  }
367 
368  int get_x() const
369  {
370  return x_;
371  }
372 
373  int get_y() const
374  {
375  return y_;
376  }
377 
378 private:
380  int x_;
381  int y_;
382 };
383 
384 /**
385  * Mask (MASK) modification.
386  */
387 
389 {
390 public:
391  mask_modification(const surface& mask, int x, int y)
392  : mask_(mask), x_(x), y_(y)
393  {}
394  virtual surface operator()(const surface& src) const;
395 
396  const surface& get_mask() const
397  {
398  return mask_;
399  }
400 
401  int get_x() const
402  {
403  return x_;
404  }
405 
406  int get_y() const
407  {
408  return y_;
409  }
410 
411 private:
413  int x_;
414  int y_;
415 };
416 
417 /**
418  * LIGHT (L) modification.
419  */
420 
422 {
423 public:
425  : surf_(surf)
426  {}
427  virtual surface operator()(const surface& src) const;
428 
429  const surface& get_surface() const
430  {
431  return surf_;
432  }
433 
434 private:
436 };
437 
438 /**
439  * Scaling (SCALE[_INTO], SCALE[_INTO]_SHARP) modifications.
440  */
442 {
443 public:
444  // Bit-unique scaling flags
445  enum SCALE_FLAGS : uint8_t {
446  SCALE_LINEAR = 0b00000,
447  SCALE_SHARP = 0b00001,
448  FIT_TO_SIZE = 0b00010,
450  X_BY_FACTOR = 0b01000,
451  Y_BY_FACTOR = 0b10000,
452  };
453 
454  scale_modification(point target_size, uint8_t flags)
455  : target_size_(target_size)
456  , flags_(flags)
457  {}
458 
459  virtual surface operator()(const surface& src) const;
460 
461  int get_w() const { return target_size_.x; }
462  int get_h() const { return target_size_.y; }
463 
464 private:
466 
468 };
469 
470 /**
471  * xBRZ scale (xBRZ) modification
472  */
474 {
475 public:
477  : z_(z)
478  {}
479 
480  virtual surface operator()(const surface& src) const;
481 
482 private:
483  int z_;
484 };
485 
486 /**
487  * Opacity (O) modification
488  */
490 {
491 public:
492  o_modification(float opacity)
493  : opacity_(opacity)
494  {}
495  virtual surface operator()(const surface& src) const;
496 
497  float get_opacity() const
498  {
499  return opacity_;
500  }
501 
502 private:
503  float opacity_;
504 };
505 
506 /**
507  * Color-shift (CS, R, G, B) modification.
508  */
510 {
511 public:
512  cs_modification(int r, int g, int b)
513  : r_(r), g_(g), b_(b)
514  {}
515  virtual surface operator()(const surface& src) const;
516 
517  int get_r() const { return r_; }
518  int get_g() const { return g_; }
519  int get_b() const { return b_; }
520 
521 private:
522  int r_, g_, b_;
523 };
524 
525 /**
526  * Color blending (BLEND) modification
527  */
529 {
530 public:
531  blend_modification(int r, int g, int b, float a)
532  : r_(r), g_(g), b_(b), a_(a)
533  {}
534  virtual surface operator()(const surface& src) const;
535 
536  int get_r() const { return r_; }
537  int get_g() const { return g_; }
538  int get_b() const { return b_; }
539  float get_a() const { return a_; }
540 
541 private:
542  int r_, g_, b_;
543  float a_;
544 };
545 
546 /**
547  * Gaussian-like blur (BL) modification.
548  */
550 {
551 public:
552  bl_modification(int depth)
553  : depth_(depth)
554  {}
555  virtual surface operator()(const surface& src) const;
556 
557  int get_depth() const
558  {
559  return depth_;
560  }
561 
562 private:
563  int depth_;
564 };
565 
566 /**
567  * Fill background with a color (BG).
568  */
570 {
572  virtual surface operator()(const surface &src) const;
573 
574  const color_t& get_color() const
575  {
576  return color_;
577  }
578 
579 private:
581 };
582 
583 /**
584  * Channel swap (SWAP).
585  */
587 {
588 public:
590  virtual surface operator()(const surface& src) const;
591 private:
596 };
597 
598 } /* end namespace image */
double g
Definition: astarsearch.cpp:63
Adjust Alpha (ADJUST_ALPHA) modification.
adjust_alpha_modification(const std::string &formula)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Adjust Channels (CHAN) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
adjust_channels_modification(const std::vector< std::string > &formulas)
Gaussian-like blur (BL) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Color blending (BLEND) modification.
blend_modification(int r, int g, int b, float a)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Scale (BLIT) modification.
const surface & get_surface() const
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
blit_modification(const surface &surf, int x, int y)
Black and white (BW) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Crop (CROP) modification.
const SDL_Rect & get_slice() const
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
crop_modification(const SDL_Rect &slice)
Crop transparent padding (CROP_TRANSPARENCY) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Color-shift (CS, R, G, B) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
cs_modification(int r, int g, int b)
Mirror (FL) modification.
bool toggle_horiz()
Toggle horizontal mirror flag.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
bool toggle_vert()
Toggle vertical mirror flag.
fl_modification(bool horiz=false, bool vert=false)
Constructor.
Grayscale (GS) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
LIGHT (L) modification.
light_modification(const surface &surf)
const surface & get_surface() const
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Mask (MASK) modification.
const surface & get_mask() const
mask_modification(const surface &mask, int x, int y)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
A modified priority queue used to order image modifications.
modification * top() const
Returns the top element in the queue .
std::map< int, std::vector< std::unique_ptr< modification > >, std::greater< int > > map_type
Map from a mod's priority() to the mods having that priority.
void pop()
Removes the top element from the queue.
void push(std::unique_ptr< modification > mod)
Adds mod to the queue (unless mod is nullptr).
map_type priorities_
Map from a mod's priority() to the mods having that priority.
std::size_t size() const
Returns the number of elements in the queue.
Base abstract class for an image-path modification.
static modification_queue decode(const std::string &)
Decodes modifications from a modification string.
virtual int priority() const
Specifies the priority of the modification.
virtual surface operator()(const surface &src) const =0
Applies the image-path modification on the specified surface.
Make an image negative (NEG)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
negative_modification(int r, int g, int b)
Opacity (O) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Plot Alpha (Alpha) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Recolor (RC/TC/PAL) modification.
const color_range_map & map() const
rc_modification()
Default constructor.
virtual int priority() const
Specifies the priority of the modification.
rc_modification(const color_range_map &recolor_map)
RC-map based constructor.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Rotate (ROTATE) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
rotate_modification(int degrees=90, int zoom=16, int offset=8)
Constructor.
Scaling (SCALE[_INTO], SCALE[_INTO]_SHARP) modifications.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
scale_modification(point target_size, uint8_t flags)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
swap_modification(channel r, channel g, channel b, channel a)
Wipe Alpha (Wipe_Alpha) modification.
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
xBRZ scale (xBRZ) modification
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Base class for exceptions that want to be thrown 'through' lua.
std::unordered_map< color_t, color_t > color_range_map
Definition: color_range.hpp:30
#define IMPLEMENT_LUA_JAILBREAK_EXCEPTION(type)
Helper macro for classes deriving from lua_jailbreak_exception.
Functions to load and save images from/to disk.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:59
Fill background with a color (BG).
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Exception thrown by the operator() when an error occurs.
imod_exception(const std::stringstream &message_stream)
Constructor.
const std::string message
The error message regarding the failed operation.
Give to the image a sepia tint (SEPIA)
virtual surface operator()(const surface &src) const
Applies the image-path modification on the specified surface.
Holds a 2D point.
Definition: point.hpp:25
mock_char c
channel
Definition: utils.hpp:122
#define a
#define b