1// SuperTux
2// Copyright (C) 2016 Ingo Ruhnke <grumbel@gmail.com>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17#include "video/sdl_surface.hpp"
18
19#include <sstream>
20#include <stdexcept>
21
22#include <SDL_image.h>
23#include <savepng.h>
24
25#include "physfs/physfs_sdl.hpp"
26#include "util/log.hpp"
27
28SDLSurfacePtr
29SDLSurface::create_rgba(int width, int height)
30{
31#if SDL_BYTEORDER == SDL_BIG_ENDIAN
32 Uint32 rmask = 0xff000000;
33 Uint32 gmask = 0x00ff0000;
34 Uint32 bmask = 0x0000ff00;
35 Uint32 amask = 0x000000ff;
36#else
37 Uint32 rmask = 0x000000ff;
38 Uint32 gmask = 0x0000ff00;
39 Uint32 bmask = 0x00ff0000;
40 Uint32 amask = 0xff000000;
41#endif
42 SDLSurfacePtr surface(SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask));
43 if (!surface) {
44 std::ostringstream out;
45 out << "failed to create SDL_Surface: " << SDL_GetError();
46 throw std::runtime_error(out.str());
47 }
48
49 return surface;
50}
51
52SDLSurfacePtr
53SDLSurface::create_rgb(int width, int height)
54{
55#if SDL_BYTEORDER == SDL_BIG_ENDIAN
56 Uint32 rmask = 0xff000000;
57 Uint32 gmask = 0x00ff0000;
58 Uint32 bmask = 0x0000ff00;
59 Uint32 amask = 0x00000000;
60#else
61 Uint32 rmask = 0x000000ff;
62 Uint32 gmask = 0x0000ff00;
63 Uint32 bmask = 0x00ff0000;
64 Uint32 amask = 0x00000000;
65#endif
66 SDLSurfacePtr surface(SDL_CreateRGBSurface(0, width, height, 24, rmask, gmask, bmask, amask));
67 if (!surface) {
68 std::ostringstream out;
69 out << "failed to create SDL_Surface: " << SDL_GetError();
70 throw std::runtime_error(out.str());
71 }
72
73 return surface;
74}
75
76SDLSurfacePtr
77SDLSurface::from_file(const std::string& filename)
78{
79 log_debug << "loading image: " << filename << std::endl;
80 SDLSurfacePtr surface(IMG_Load_RW(get_physfs_SDLRWops(filename), 1));
81 if (!surface)
82 {
83 std::ostringstream msg;
84 msg << "Couldn't load image '" << filename << "' :" << SDL_GetError();
85 throw std::runtime_error(msg.str());
86 }
87 else
88 {
89 return surface;
90 }
91}
92
93int
94SDLSurface::save_png(const SDL_Surface& surface, const std::string& filename)
95{
96 // This does not lead to a double free when 'tmp == screen', as
97 // SDL_PNGFormatAlpha() will increase the refcount of surface.
98 SDLSurfacePtr tmp(SDL_PNGFormatAlpha(const_cast<SDL_Surface*>(&surface)));
99 int ret = SDL_SavePNG_RW(tmp.get(), get_writable_physfs_SDLRWops(filename), 1);
100 if (ret < 0)
101 {
102 log_warning << "Saving " << filename << " failed: " << SDL_GetError() << std::endl;
103 return false;
104 }
105 else
106 {
107 return true;
108 }
109}
110
111/* EOF */
112