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