1 /*
2 * Copyright 2010-2014 OpenXcom Developers.
3 *
4 * This file is part of OpenXcom.
5 *
6 * OpenXcom 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 3 of the License, or
9 * (at your option) any later version.
10 *
11 * OpenXcom is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with OpenXcom. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "Palette.h"
20 #include <fstream>
21 #include "Exception.h"
22
23 namespace OpenXcom
24 {
25
26 /**
27 * Initializes a brand new palette.
28 */
Palette()29 Palette::Palette() : _colors(0), _count(0)
30 {
31 }
32
33 /**
34 * Deletes any colors contained within.
35 */
~Palette()36 Palette::~Palette()
37 {
38 delete[] _colors;
39 }
40
41 /**
42 * Loads an X-Com palette from a file. X-Com palettes are just a set
43 * of RGB colors in a row, on a 0-63 scale, which have to be adjusted
44 * for modern computers (0-255 scale).
45 * @param filename Filename of the palette.
46 * @param ncolors Number of colors in the palette.
47 * @param offset Position of the palette in the file (in bytes).
48 * @sa http://www.ufopaedia.org/index.php?title=PALETTES.DAT
49 */
loadDat(const std::string & filename,int ncolors,int offset)50 void Palette::loadDat(const std::string &filename, int ncolors, int offset)
51 {
52 if(_colors != 0)
53 throw Exception("loadDat can be run only once");
54 _count = ncolors;
55 _colors = new SDL_Color[_count];
56 memset(_colors, 0, sizeof(SDL_Color) * _count);
57
58 // Load file and put colors in pallete
59 std::ifstream palFile (filename.c_str(), std::ios::in | std::ios::binary);
60 if (!palFile)
61 {
62 throw Exception(filename + " not found");
63 }
64
65 // Move pointer to proper pallete
66 palFile.seekg(offset, std::ios::beg);
67
68 Uint8 value[3];
69
70 for (int i = 0; i < _count && palFile.read((char*)value, 3); ++i)
71 {
72 // Correct X-Com colors to RGB colors
73 _colors[i].r = value[0] * 4;
74 _colors[i].g = value[1] * 4;
75 _colors[i].b = value[2] * 4;
76 _colors[i].unused = 255;
77 }
78 _colors[0].unused = 0;
79
80 palFile.close();
81 }
82
83 /**
84 * Provides access to colors contained in the palette.
85 * @param offset Offset to a specific color.
86 * @return Pointer to the requested SDL_Color.
87 */
getColors(int offset) const88 SDL_Color *Palette::getColors(int offset) const
89 {
90 return _colors + offset;
91 }
92
93 /**
94 * Converts an SDL_Color struct into an hexadecimal RGBA color value.
95 * Mostly used for operations with SDL_gfx that require colors in this format.
96 * @param pal Requested palette.
97 * @param color Requested color in the palette.
98 * @return Hexadecimal RGBA value.
99 */
getRGBA(SDL_Color * pal,Uint8 color)100 Uint32 Palette::getRGBA(SDL_Color* pal, Uint8 color)
101 {
102 return ((Uint32) pal[color].r << 24) | ((Uint32) pal[color].g << 16) | ((Uint32) pal[color].b << 8) | (Uint32) 0xFF;
103 }
104
savePal(const std::string & file) const105 void Palette::savePal(const std::string &file) const
106 {
107 std::ofstream out(file.c_str(), std::ios::out | std::ios::binary);
108 short count = _count;
109
110 // RIFF header
111 out << "RIFF";
112 int length = 4 + 4 + 4 + 4 + 2 + 2 + count * 4;
113 out.write((char*) &length, sizeof(length));
114 out << "PAL ";
115
116 // Data chunk
117 out << "data";
118 int data = count * 4 + 4;
119 out.write((char*) &data, sizeof(data));
120 short version = 0x0300;
121 out.write((char*) &version, sizeof(version));
122 out.write((char*) &count, sizeof(count));
123
124 // Colors
125 SDL_Color *color = getColors();
126 for (short i = 0; i < count; ++i)
127 {
128 char c = 0;
129 out.write((char*) &color->r, 1);
130 out.write((char*) &color->g, 1);
131 out.write((char*) &color->b, 1);
132 out.write(&c, 1);
133 color++;
134 }
135 out.close();
136 }
137
138 }
139