The Battle for Wesnoth  1.17.12+dev
utils.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2022
3  by David White <dave@whitevine.net>
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"
19 #include "color.hpp"
20 #include "sdl/surface.hpp"
21 #include "utils/math.hpp"
22 #include "game_version.hpp"
23 
24 #include <SDL2/SDL.h>
25 
26 #include <cstdlib>
27 #include <map>
28 #include <string>
29 
30 namespace sdl
31 {
32 
33 /** Returns the runtime SDL version. */
35 
36 /**
37  * Returns true if the runtime SDL version is at or greater than the
38  * specified version, false otherwise.
39  */
40 bool runtime_at_least(uint8_t major, uint8_t minor = 0, uint8_t patch = 0);
41 
42 /**
43  * Fill a rectangle on a given surface. Alias for SDL_FillRect.
44  *
45  * @param dst The surface to operate on.
46  * @param dst_rect The rectangle to fill.
47  * @param color Color of the rectangle.
48  */
49 inline void fill_surface_rect(surface& dst, SDL_Rect* dst_rect, const uint32_t color)
50 {
51  SDL_FillRect(dst, dst_rect, color);
52 }
53 
54 } // namespace sdl
55 
56 
57 inline void sdl_blit(const surface& src, const SDL_Rect* src_rect, surface& dst, SDL_Rect* dst_rect){
58  // Note: this is incorrect when both src and dst combine transparent pixels.
59  // The correct equation is, per-pixel:
60  // outA = srcA + dstA * (1 - srcA)
61  // outRGB = (srcRGB * srcA + dstRGB * dstA * (1 - srcA)) / outA
62  // When outA is 0, outRGB can of course be anything.
63  // TODO: implement proper transparent blending using the above formula
64  SDL_BlitSurface(src, src_rect, dst, dst_rect);
65 }
66 
67 /** Scale a surface using xBRZ algorithm
68  * @param surf The source surface
69  * @param z The scaling factor. Should be an integer 2-5 (1 is tolerated).
70  * @return The scaled surface
71  */
72 surface scale_surface_xbrz(const surface & surf, std::size_t z);
73 
74 /** Scale a surface using the nearest neighbor algorithm (provided by xBRZ lib)
75  * @param surf The sources surface
76  * @param w The width of the resulting surface.
77  * @param h The height of the resulting surface.
78  * @return The rescaled surface.
79  */
80 surface scale_surface_nn(const surface & surf, int w, int h);
81 
82 /** Scale a surface using alpha-weighted modified bilinear filtering
83  * Note: causes artifacts with alpha gradients, for example in some portraits
84  * @param surf The source surface.
85  * @param w The width of the resulting surface.
86  * @param h The height of the resulting surface.
87  * @return A surface containing the scaled version of the source.
88  * @retval 0 Returned upon error.
89  * @retval surf Returned if w == surf->w and h == surf->h.
90  */
91 surface scale_surface(const surface &surf, int w, int h);
92 
93 /** Scale a surface using simple bilinear filtering (discarding rgb from source
94  * pixels with 0 alpha)
95  * @param surf The source surface.
96  * @param w The width of the resulting surface.
97  * @param h The height of the resulting surface.
98  * @return A surface containing the scaled version of the source.
99  * @retval 0 Returned upon error.
100  * @retval surf Returned if w == surf->w and h == surf->h.
101  */
102 surface scale_surface_legacy(const surface &surf, int w, int h);
103 
104 /** Scale a surface using modified nearest neighbour algorithm. Use only if
105  * preserving sharp edges is a priority (e.g. minimap).
106  * @param surf The source surface.
107  * @param w The width of the resulting surface.
108  * @param h The height of the resulting surface.
109  * @return A surface containing the scaled version of the source.
110  * @retval 0 Returned upon error.
111  * @retval surf Returned if w == surf->w and h == surf->h.
112  */
113 surface scale_surface_sharp(const surface& surf, int w, int h);
114 
115 surface adjust_surface_color(const surface &surf, int r, int g, int b);
116 surface greyscale_image(const surface &surf);
117 surface monochrome_image(const surface &surf, const int threshold);
118 surface sepia_image(const surface &surf);
119 surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB);
120 surface alpha_to_greyscale(const surface & surf);
121 surface wipe_alpha(const surface & surf);
122 /** create an heavy shadow of the image, by blurring, increasing alpha and darkening */
123 surface shadow_image(const surface &surf, int scale = 1);
124 
125 enum channel { RED, GREEN, BLUE, ALPHA };
127 
128 /**
129  * Recolors a surface using a map with source and converted palette values.
130  * This is most often used for team-coloring.
131  *
132  * @param surf The source surface.
133  * @param map_rgb Map of color values, with the keys corresponding to the
134  * source palette, and the values to the recolored palette.
135  * @return A recolored surface, or a null surface if there are
136  * problems with the source.
137  */
138 surface recolor_image(surface surf, const color_range_map& map_rgb);
139 
140 surface brighten_image(const surface &surf, int32_t amount);
141 
142 /** Get a portion of the screen.
143  * Send nullptr if the portion is outside of the screen.
144  * @param surf The source surface.
145  * @param rect The portion of the source surface to copy.
146  * @return A surface containing the portion of the source.
147  * No RLE or Alpha bits are set.
148  * @retval 0 if error or the portion is outside of the surface.
149  */
150 surface get_surface_portion(const surface &surf, SDL_Rect &rect);
151 
152 void adjust_surface_alpha(surface& surf, uint8_t alpha_mod);
153 surface adjust_surface_alpha_add(const surface &surf, int amount);
154 
155 /** Applies a mask on a surface. */
156 surface mask_surface(const surface &surf, const surface &mask, bool* empty_result = nullptr, const std::string& filename = std::string());
157 
158 /** Check if a surface fit into a mask */
159 bool in_mask_surface(const surface &surf, const surface &mask);
160 
161 /**
162  * Light surf using lightmap
163  * @param surf The source surface.
164  * @param lightmap add/subtract this color to surf
165  * but RGB values are converted to (X-128)*2
166  * to cover the full (-256,256) spectrum.
167  * Should already be neutral
168 */
169 surface light_surface(const surface &surf, const surface &lightmap);
170 
171 /**
172  * Cross-fades a surface.
173  *
174  * @param surf The source surface.
175  * @param depth The depth of the blurring.
176  * @return A new, blurred, neutral surface.
177  */
178 surface blur_surface(const surface &surf, int depth = 1);
179 
180 /**
181  * Cross-fades a surface in place.
182  *
183  * @param surf The surface to blur, must have 32 bits per pixel.
184  * @param rect The part of the surface to blur.
185  * @param depth The depth of the blurring.
186  */
187 void blur_surface(surface& surf, SDL_Rect rect, int depth = 1);
188 
189 /**
190  * Cross-fades a surface with alpha channel.
191  *
192  * @param surf The source surface.
193  * @param depth The depth of the blurring.
194  * @return A new, blurred, neutral surface.
195  */
196 surface blur_alpha_surface(const surface &surf, int depth = 1);
197 
198 /** Cuts a rectangle from a surface. */
199 surface cut_surface(const surface &surf, const SDL_Rect& r);
200 
201 /**
202  * Blends a surface with a color.
203  *
204  * Every pixel in the surface will be blended with the @p color given. The
205  * final color of a pixel is amount * @p color + (1 - amount) * original.
206  *
207  * @param surf The surface to blend.
208  * @param amount The amount of the new color is determined by
209  * @p color. Must be a number in the range
210  * [0, 1].
211  * @param color The color to blend width, note its alpha
212  * channel is ignored.
213  *
214  * @return The blended surface.
215  */
217  const surface &surf
218  , const double amount
219  , const color_t color);
220 
221 /**
222  * Rotates a surface by any degrees.
223  *
224  * @pre @p zoom >= @p offset Otherwise @return will have empty pixels.
225  * @pre @p offset > 0 Otherwise the procedure will not return.
226  *
227  * @param surf The surface to rotate.
228  * @param angle The angle of rotation.
229  * @param zoom Which zoom level to use for calculating the result.
230  * @param offset Pixel offset when scanning the zoomed source.
231  *
232  * @return The rotated surface.
233  */
234 surface rotate_any_surface(const surface& surf, float angle,
235  int zoom, int offset);
236 
237 /**
238  * Rotates a surface 180 degrees.
239  *
240  * @param surf The surface to rotate.
241  *
242  * @return The rotated surface.
243  */
244 surface rotate_180_surface(const surface &surf);
245 
246 /**
247  * Rotates a surface 90 degrees.
248  *
249  * @param surf The surface to rotate.
250  * @param clockwise Whether the rotation should be clockwise (true)
251  * or counter-clockwise (false).
252  *
253  * @return The rotated surface.
254  */
255 surface rotate_90_surface(const surface &surf, bool clockwise);
256 
257 surface flip_surface(const surface &surf);
258 surface flop_surface(const surface &surf);
259 
260 SDL_Rect get_non_transparent_portion(const surface &surf);
261 
262 /**
263  * Helper methods for setting/getting a single pixel in an image.
264  * Lifted from http://sdl.beuc.net/sdl.wiki/Pixel_Access
265  *
266  * @param surf The image to get or receive the pixel from.
267  * @param surf_lock The locked surface to make sure the pointers are valid.
268  * @param x The position in the row of the pixel.
269  * @param y The row of the pixel.
270  * @param pixel The pixel value.
271  */
272 void put_pixel(const surface& surf, surface_lock& surf_lock, int x, int y, uint32_t pixel);
273 uint32_t get_pixel(const surface& surf, const const_surface_lock& surf_lock, int x, int y);
274 
Definition: utils.hpp:125
surface rotate_any_surface(const surface &surf, float angle, int zoom, int offset)
Rotates a surface by any degrees.
Definition: utils.cpp:1591
void sdl_blit(const surface &src, const SDL_Rect *src_rect, surface &dst, SDL_Rect *dst_rect)
Definition: utils.hpp:57
surface cut_surface(const surface &surf, const SDL_Rect &r)
Cuts a rectangle from a surface.
Definition: utils.cpp:1486
surface scale_surface_nn(const surface &surf, int w, int h)
Scale a surface using the nearest neighbor algorithm (provided by xBRZ lib)
Definition: utils.cpp:92
Interfaces for manipulating version numbers of engine, add-ons, etc.
surface greyscale_image(const surface &surf)
Definition: utils.cpp:529
bool runtime_at_least(uint8_t major, uint8_t minor=0, uint8_t patch=0)
Returns true if the runtime SDL version is at or greater than the specified version, false otherwise.
Definition: utils.cpp:41
surface alpha_to_greyscale(const surface &surf)
Definition: utils.cpp:699
surface monochrome_image(const surface &surf, const int threshold)
Definition: utils.cpp:574
#define a
void fill_surface_rect(surface &dst, SDL_Rect *dst_rect, const uint32_t color)
Fill a rectangle on a given surface.
Definition: utils.hpp:49
surface flip_surface(const surface &surf)
Definition: utils.cpp:1779
surface rotate_180_surface(const surface &surf)
Rotates a surface 180 degrees.
Definition: utils.cpp:1702
#define h
bool in_mask_surface(const surface &surf, const surface &mask)
Check if a surface fit into a mask.
Definition: utils.cpp:1092
surface scale_surface(const surface &surf, int w, int h)
Scale a surface using alpha-weighted modified bilinear filtering Note: causes artifacts with alpha gr...
Definition: utils.cpp:129
#define b
version_info get_version()
Returns the runtime SDL version.
Definition: utils.cpp:34
void scale(size_t factor, const uint32_t *src, uint32_t *trg, int srcWidth, int srcHeight, const ScalerCfg &cfg=ScalerCfg(), int yFirst=0, int yLast=std::numeric_limits< int >::max())
Definition: xbrz.cpp:1190
Definition: utils.hpp:125
General math utility functions.
The basic class for representing 8-bit RGB or RGBA colour values.
Definition: color.hpp:58
void put_pixel(const surface &surf, surface_lock &surf_lock, int x, int y, uint32_t pixel)
Helper methods for setting/getting a single pixel in an image.
Definition: utils.cpp:1648
surface adjust_surface_color(const surface &surf, int r, int g, int b)
Definition: utils.cpp:484
surface mask_surface(const surface &surf, const surface &mask, bool *empty_result=nullptr, const std::string &filename=std::string())
Applies a mask on a surface.
Definition: utils.cpp:1022
surface recolor_image(surface surf, const color_range_map &map_rgb)
Recolors a surface using a map with source and converted palette values.
Definition: utils.cpp:894
surface brighten_image(const surface &surf, int32_t amount)
Definition: utils.cpp:933
surface scale_surface_legacy(const surface &surf, int w, int h)
Scale a surface using simple bilinear filtering (discarding rgb from source pixels with 0 alpha) ...
Definition: utils.cpp:258
surface adjust_surface_alpha_add(const surface &surf, int amount)
Definition: utils.cpp:984
void adjust_surface_alpha(surface &surf, uint8_t alpha_mod)
Definition: utils.cpp:975
std::unordered_map< color_t, color_t > color_range_map
Definition: color_range.hpp:31
Definition: utils.hpp:125
surface get_surface_portion(const surface &surf, SDL_Rect &rect)
Get a portion of the screen.
Definition: utils.cpp:1837
double g
Definition: astarsearch.cpp:65
Helper class for pinning SDL surfaces into memory.
Definition: surface.hpp:122
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:46
surface wipe_alpha(const surface &surf)
Definition: utils.cpp:727
int w
Definition: utils.hpp:125
uint32_t get_pixel(const surface &surf, const const_surface_lock &surf_lock, int x, int y)
Definition: utils.cpp:1679
Represents version numbers.
surface scale_surface_sharp(const surface &surf, int w, int h)
Scale a surface using modified nearest neighbour algorithm.
Definition: utils.cpp:395
surface scale_surface_xbrz(const surface &surf, std::size_t z)
Scale a surface using xBRZ algorithm.
Definition: utils.cpp:55
surface flop_surface(const surface &surf)
Definition: utils.cpp:1808
surface blur_surface(const surface &surf, int depth=1)
Cross-fades a surface.
Definition: utils.cpp:1204
surface light_surface(const surface &surf, const surface &lightmap)
Light surf using lightmap.
Definition: utils.cpp:1138
surface shadow_image(const surface &surf, int scale=1)
create an heavy shadow of the image, by blurring, increasing alpha and darkening
Definition: utils.cpp:755
surface swap_channels_image(const surface &surf, channel r, channel g, channel b, channel a)
Definition: utils.cpp:792
surface blend_surface(const surface &surf, const double amount, const color_t color)
Blends a surface with a color.
Definition: utils.cpp:1544
surface rotate_90_surface(const surface &surf, bool clockwise)
Rotates a surface 90 degrees.
Definition: utils.cpp:1744
SDL_Rect get_non_transparent_portion(const surface &surf)
Definition: utils.cpp:1888
surface blur_alpha_surface(const surface &surf, int depth=1)
Cross-fades a surface with alpha channel.
Definition: utils.cpp:1339
surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB)
Definition: utils.cpp:656
surface sepia_image(const surface &surf)
Definition: utils.cpp:614
channel
Definition: utils.hpp:125