GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/imagehelper.cpp Lines: 40 95 42.1 %
Date: 2021-03-17 Branches: 5 29 17.2 %

Line Branch Exec Source
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"
29
#include "resources/dye/dyepalette.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
44
ImageHelper *imageHelper = nullptr;
45
ImageHelper *surfaceImageHelper = nullptr;
46
47
bool ImageHelper::mEnableAlpha = true;
48
RenderType ImageHelper::mUseOpenGL = RENDER_SOFTWARE;
49
50
1611
Image *ImageHelper::load(SDL_RWops *const rw)
51
{
52
1611
    SDL_Surface *const tmpImage = loadPng(rw);
53
1611
    if (tmpImage == nullptr)
54
    {
55
        logger->log("Error, image load failed: %s", SDL_GetError());
56
        return nullptr;
57
    }
58
59
1611
    Image *const image = loadSurface(tmpImage);
60
61
1611
    MSDL_FreeSurface(tmpImage);
62
1611
    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
77
void ImageHelper::dumpSurfaceFormat(const SDL_Surface *const image)
180
{
181
77
    if (image == nullptr)
182
        return;
183
77
    if (image->format != nullptr)
184
    {
185
77
        const SDL_PixelFormat * const format = image->format;
186
77
        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
77
        logger->log("Alpha: %d", format->alpha);
192
77
        logger->log("Color key: %u", format->colorkey);
193
#endif  // USE_SDL2
194
195
308
        logger->log("Loss: %02x, %02x, %02x, %02x",
196
77
            CAST_U32(format->Rloss),
197
77
            CAST_U32(format->Gloss),
198
77
            CAST_U32(format->Bloss),
199
154
            CAST_U32(format->Aloss));
200
308
        logger->log("Shift: %02x, %02x, %02x, %02x",
201
77
            CAST_U32(format->Rshift),
202
77
            CAST_U32(format->Gshift),
203
77
            CAST_U32(format->Bshift),
204
154
            CAST_U32(format->Ashift));
205
77
        logger->log("Mask: %08x, %08x, %08x, %08x", format->Rmask,
206
154
            format->Gmask, format->Bmask, format->Amask);
207
    }
208
77
    logger->log("Flags: %u", image->flags);
209
77
    logger->log("Pitch: %d", CAST_S32(image->pitch));
210
#ifndef USE_SDL2
211
77
    logger->log("Offset: %d", image->offset);
212
#endif  // USE_SDL2
213
}
214
215
1616
SDL_Surface *ImageHelper::loadPng(SDL_RWops *const rw)
216
{
217
1616
    if (rw == nullptr)
218
        return nullptr;
219
220
1616
    if (IMG_isPNG(rw) != 0)
221
    {
222
1616
        SDL_Surface *const tmpImage = MIMG_LoadPNG_RW(rw);
223
1616
        SDL_RWclose(rw);
224
1616
        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
130
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
130
    const uint32_t rmask = 0x000000ffU;
250
130
    const uint32_t gmask = 0x0000ff00U;
251
130
    const uint32_t bmask = 0x00ff0000U;
252
130
    const uint32_t amask = 0xff000000U;
253
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
254
255
130
    return MSDL_CreateRGBSurface(SDL_SWSURFACE,
256
        width, height, 32, rmask, gmask, bmask, amask);
257
}