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