ManaPlus
imagehelper.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2019 The ManaPlus Developers
6  * Copyright (C) 2019-2021 Andrei Karas
7  *
8  * This file is part of The ManaPlus Client.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "resources/imagehelper.h"
25 
26 #include "logger.h"
27 
28 #include "resources/dye/dye.h"
30 
31 #include "utils/sdlcheckutils.h"
32 
33 PRAGMA48(GCC diagnostic push)
34 PRAGMA48(GCC diagnostic ignored "-Wshadow")
35 #include <SDL_image.h>
36 PRAGMA48(GCC diagnostic pop)
37 
38 #include "debug.h"
39 
40 #ifndef SDL_BIG_ENDIAN
41 #error missing SDL_endian.h
42 #endif // SDL_BYTEORDER
43 
46 
47 bool ImageHelper::mEnableAlpha = true;
49 
50 Image *ImageHelper::load(SDL_RWops *const rw)
51 {
52  SDL_Surface *const tmpImage = loadPng(rw);
53  if (tmpImage == nullptr)
54  {
55  logger->log("Error, image load failed: %s", SDL_GetError());
56  return nullptr;
57  }
58 
59  Image *const image = loadSurface(tmpImage);
60 
61  MSDL_FreeSurface(tmpImage);
62  return image;
63 }
64 
65 Image *ImageHelper::load(SDL_RWops *const rw, Dye const &dye)
66 {
67  BLOCK_START("ImageHelper::load")
68  SDL_Surface *const tmpImage = loadPng(rw);
69  if (tmpImage == nullptr)
70  {
71  logger->log("Error, image load failed: %s", SDL_GetError());
72  BLOCK_END("ImageHelper::load")
73  return nullptr;
74  }
75 
76  SDL_PixelFormat rgba;
77  rgba.palette = nullptr;
78  rgba.BitsPerPixel = 32;
79  rgba.BytesPerPixel = 4;
80 
81 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
82  rgba.Rmask = 0x000000FFU;
83  rgba.Gmask = 0x0000FF00U;
84  rgba.Bmask = 0x00FF0000U;
85  rgba.Amask = 0xFF000000U;
86 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
87 
88  rgba.Rmask = 0xFF000000U;
89  rgba.Gmask = 0x00FF0000U;
90  rgba.Bmask = 0x0000FF00U;
91  rgba.Amask = 0x000000FFU;
92 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
93 
94  SDL_Surface *const surf = MSDL_ConvertSurface(
95  tmpImage, &rgba, SDL_SWSURFACE);
96  MSDL_FreeSurface(tmpImage);
97 
98  if (surf == nullptr)
99  return nullptr;
100 
101  uint32_t *const pixels = static_cast<uint32_t *>(surf->pixels);
102  const int type = dye.getType();
103 
104  switch (type)
105  {
106  case 1:
107  {
108  const DyePalette *const pal = dye.getSPalete();
109  if (pal != nullptr)
110  DYEPALETTEP(pal, SColor)(pixels, surf->w * surf->h);
111  break;
112  }
113  case 2:
114  {
115  const DyePalette *const pal = dye.getAPalete();
116  if (pal != nullptr)
117  DYEPALETTEP(pal, AColor)(pixels, surf->w * surf->h);
118  break;
119  }
120  case 0:
121  default:
122  {
123  dye.normalDye(pixels, surf->w * surf->h);
124  break;
125  }
126  }
127 
128  Image *const image = loadSurface(surf);
129  MSDL_FreeSurface(surf);
130  BLOCK_END("ImageHelper::load")
131  return image;
132 }
133 
134 SDL_Surface* ImageHelper::convertTo32Bit(SDL_Surface *const tmpImage)
135 {
136  if (tmpImage == nullptr)
137  return nullptr;
138  SDL_PixelFormat RGBAFormat;
139  RGBAFormat.palette = nullptr;
140 #ifndef USE_SDL2
141  RGBAFormat.colorkey = 0;
142  RGBAFormat.alpha = 0;
143 #endif // USE_SDL2
144 
145  RGBAFormat.BitsPerPixel = 32;
146  RGBAFormat.BytesPerPixel = 4;
147 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
148  RGBAFormat.Rmask = 0xFF000000U;
149  RGBAFormat.Rshift = 0;
150  RGBAFormat.Rloss = 0;
151  RGBAFormat.Gmask = 0x00FF0000U;
152  RGBAFormat.Gshift = 8;
153  RGBAFormat.Gloss = 0;
154  RGBAFormat.Bmask = 0x0000FF00U;
155  RGBAFormat.Bshift = 16;
156  RGBAFormat.Bloss = 0;
157  RGBAFormat.Amask = 0x000000FFU;
158  RGBAFormat.Ashift = 24;
159  RGBAFormat.Aloss = 0;
160 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
161 
162  RGBAFormat.Rmask = 0x000000FFU;
163  RGBAFormat.Rshift = 24;
164  RGBAFormat.Rloss = 0;
165  RGBAFormat.Gmask = 0x0000FF00U;
166  RGBAFormat.Gshift = 16;
167  RGBAFormat.Gloss = 0;
168  RGBAFormat.Bmask = 0x00FF0000U;
169  RGBAFormat.Bshift = 8;
170  RGBAFormat.Bloss = 0;
171  RGBAFormat.Amask = 0xFF000000U;
172  RGBAFormat.Ashift = 0;
173  RGBAFormat.Aloss = 0;
174 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
175 
176  return MSDL_ConvertSurface(tmpImage, &RGBAFormat, SDL_SWSURFACE);
177 }
178 
179 void ImageHelper::dumpSurfaceFormat(const SDL_Surface *const image)
180 {
181  if (image == nullptr)
182  return;
183  if (image->format != nullptr)
184  {
185  const SDL_PixelFormat * const format = image->format;
186  logger->log("Bytes per pixel: %d", format->BytesPerPixel);
187 #ifdef USE_SDL2
188  logger->log("Format: %u", format->format);
189 #else // USE_SDL2
190 
191  logger->log("Alpha: %d", format->alpha);
192  logger->log("Color key: %u", format->colorkey);
193 #endif // USE_SDL2
194 
195  logger->log("Loss: %02x, %02x, %02x, %02x",
196  CAST_U32(format->Rloss),
197  CAST_U32(format->Gloss),
198  CAST_U32(format->Bloss),
199  CAST_U32(format->Aloss));
200  logger->log("Shift: %02x, %02x, %02x, %02x",
201  CAST_U32(format->Rshift),
202  CAST_U32(format->Gshift),
203  CAST_U32(format->Bshift),
204  CAST_U32(format->Ashift));
205  logger->log("Mask: %08x, %08x, %08x, %08x", format->Rmask,
206  format->Gmask, format->Bmask, format->Amask);
207  }
208  logger->log("Flags: %u", image->flags);
209  logger->log("Pitch: %d", CAST_S32(image->pitch));
210 #ifndef USE_SDL2
211  logger->log("Offset: %d", image->offset);
212 #endif // USE_SDL2
213 }
214 
215 SDL_Surface *ImageHelper::loadPng(SDL_RWops *const rw)
216 {
217  if (rw == nullptr)
218  return nullptr;
219 
220  if (IMG_isPNG(rw) != 0)
221  {
222  SDL_Surface *const tmpImage = MIMG_LoadPNG_RW(rw);
223  SDL_RWclose(rw);
224  return tmpImage;
225  }
226 
227  if (IMG_isJPG(rw) != 0)
228  {
229  SDL_Surface *const tmpImage = MIMG_LoadJPG_RW(rw);
230  SDL_RWclose(rw);
231  return tmpImage;
232  }
233 
234  logger->log("Error, image is not png");
235  SDL_RWclose(rw);
236  return nullptr;
237 }
238 
239 SDL_Surface *ImageHelper::create32BitSurface(int width,
240  int height) const
241 {
242 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
243  const uint32_t rmask = 0xff000000U;
244  const uint32_t gmask = 0x00ff0000U;
245  const uint32_t bmask = 0x0000ff00U;
246  const uint32_t amask = 0x000000ffU;
247 #else // SDL_BYTEORDER == SDL_BIG_ENDIAN
248 
249  const uint32_t rmask = 0x000000ffU;
250  const uint32_t gmask = 0x0000ff00U;
251  const uint32_t bmask = 0x00ff0000U;
252  const uint32_t amask = 0xff000000U;
253 #endif // SDL_BYTEORDER == SDL_BIG_ENDIAN
254 
255  return MSDL_CreateRGBSurface(SDL_SWSURFACE,
256  width, height, 32, rmask, gmask, bmask, amask);
257 }
#define CAST_S32
Definition: cast.h:30
#define CAST_U32
Definition: cast.h:31
Definition: dye.h:41
const DyePalette * getSPalete() const
Definition: dye.h:67
const DyePalette * getAPalete() const
Definition: dye.h:73
void normalDye(uint32_t *pixels, const int bufSize) const
Definition: dye.cpp:158
int getType() const
Definition: dye.cpp:149
static void dumpSurfaceFormat(const SDL_Surface *const image)
static RenderType mUseOpenGL
Definition: imagehelper.h:118
static SDL_Surface * convertTo32Bit(SDL_Surface *const tmpImage)
virtual Image * loadSurface(SDL_Surface *const)
Definition: imagehelper.h:73
virtual SDL_Surface * create32BitSurface(int width, int height) const
static SDL_Surface * loadPng(SDL_RWops *const rw)
static bool mEnableAlpha
Definition: imagehelper.h:117
Image * load(SDL_RWops *const rw)
Definition: imagehelper.cpp:50
void log(const char *const log_text,...)
Definition: logger.cpp:269
#define MSDL_ConvertSurface(src, fmt, flags)
Definition: debug.h:57
#define MIMG_LoadJPG_RW(src)
Definition: debug.h:53
#define MIMG_LoadPNG_RW(src)
Definition: debug.h:52
#define MSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a)
Definition: debug.h:55
#define MSDL_FreeSurface(surface)
Definition: debug.h:54
#define DYEPALETTEP(palette, color)
Definition: dyepalette.h:40
ImageHelper * imageHelper
Definition: imagehelper.cpp:44
ImageHelper * surfaceImageHelper
Definition: imagehelper.cpp:45
#define PRAGMA48(str)
Definition: localconsts.h:199
Logger * logger
Definition: logger.cpp:89
#define BLOCK_END(name)
Definition: perfomance.h:80
#define BLOCK_START(name)
Definition: perfomance.h:79
RenderType
Definition: rendertype.h:26
@ RENDER_SOFTWARE
Definition: rendertype.h:27