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