1 /* Libvisual-plugins - Standard plugins for libvisual
2 *
3 * Copyright (C) 2000, 2001 Richard Ashburn <richard.asbury@btinternet.com>
4 *
5 * Authors: Richard Ashburn <richard.asbury@btinternet.com>
6 * Jean-Christophe Hoelt <jeko@ios-software.com>
7 * Dennis Smit <ds@nerds-incorporated.org>
8 *
9 * $Id: palette.cpp,v 1.6 2005/12/20 18:49:13 synap Exp $
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 #include "palette.h"
27
28 #include <cstdlib>
29 #include <cstring>
30 using namespace std;
31
32 ///////////////////////////////////////////////////////////////////////////////
33
34
35 // Palette stored in compressed format (just checkpoints)
36 class CompressedPalette
37 {
38 public:
39 ColorRGB m_col[16];
40 int m_ind[16];
41 int m_nb;
42
CompressedPalette()43 CompressedPalette() : m_nb(0) {}
push_color(int i,ColorRGB col)44 void push_color(int i, ColorRGB col) { m_col[m_nb] = col; m_ind[m_nb++] = i; }
45
46 void expand(Palette pal) const;
47 };
48
49 ///////////////////////////////////////////////////////////////////////////////
50
PaletteCycler(const int palettes[][NB_PALETTES],int nbPalettes)51 PaletteCycler::PaletteCycler(const int palettes[][NB_PALETTES], int nbPalettes)
52 : m_palettes(palettes, nbPalettes)
53 {
54 visual_mem_set (m_srcpal, 0, sizeof (Palette));
55 visual_mem_set (m_destpal, 0, sizeof (Palette));
56 visual_mem_set (m_curpal, 0, sizeof (Palette));
57
58 startPaletteTransition();
59 affectPaletteTransition(1);
60 m_transferring = false;
61 m_srcnum = m_destnum;
62 }
63
startPaletteTransition()64 void PaletteCycler::startPaletteTransition()
65 {
66 if (m_palettes.size() > 0)
67 {
68 // Copy the current palette to the "source palette"
69 visual_mem_copy(m_srcpal, m_curpal, sizeof(m_srcpal));
70
71 // Create a new palette as the "destination palette"
72 m_srcnum = m_destnum;
73 m_destnum = rand() % (int) m_palettes.size();
74 m_palettes.expandPalette(m_destnum, m_destpal);
75
76 // Begin the transition
77 m_transferring = true;
78 m_progress = 0;
79 }
80 }
81
update(TimedLevel * pLevels)82 void PaletteCycler::update(TimedLevel *pLevels)
83 {
84 // Randomly change the destination palette
85 if (pLevels->timeStamp - pLevels->lastbeat > 10000000) {
86 if (rand() % 100 == 0) startPaletteTransition();
87 }
88 else {
89 if (rand() % 400 == 0) startPaletteTransition();
90 }
91
92 // Continue any current palette transtion
93 if (m_transferring) {
94 if (pLevels->timeStamp - pLevels->lastbeat > 10000000) m_progress += 0.01;
95 else m_progress += 0.005;
96 if (m_progress >= 1) {
97 m_transferring = false;
98 m_progress = 1;
99 m_srcnum = m_destnum;
100 }
101 // Use an inverse sigmoid transition to emphasise the midway palette
102 double x;
103 if (m_progress < 0.5) x = 2 * m_progress * (1 - m_progress);
104 else x = 2 * m_progress * (m_progress - 1) + 1;
105 affectPaletteTransition(x);
106 }
107 }
108
updateVisPalette(VisPalette * pal)109 void PaletteCycler::updateVisPalette (VisPalette *pal)
110 {
111 for (int i = 0; i < 256; i++) {
112 pal->colors[i].r = m_curpal[i].rgbRed;
113 pal->colors[i].g = m_curpal[i].rgbGreen;
114 pal->colors[i].b = m_curpal[i].rgbBlue;
115 }
116 }
117
affectPaletteTransition(double p)118 void PaletteCycler::affectPaletteTransition(double p)
119 {
120 for (int i = 0; i < 256; ++i)
121 {
122 ColorRGB c1 = m_srcpal[i];
123 ColorRGB c2 = m_destpal[i];
124 m_curpal[i].rgbRed = (unsigned char) ((1 - p) * c1.rgbRed + p * c2.rgbRed);
125 m_curpal[i].rgbGreen = (unsigned char) ((1 - p) * c1.rgbGreen + p * c2.rgbGreen);
126 m_curpal[i].rgbBlue = (unsigned char) ((1 - p) * c1.rgbBlue + p * c2.rgbBlue);
127 }
128 }
129
130
131
132 ///////////////////////////////////////////////////////////////////////////////
133
expand(Palette dest) const134 void CompressedPalette::expand(Palette dest) const
135 {
136 ColorRGB col;
137 int entry = 0;
138 col.rgbBlue = col.rgbGreen = col.rgbRed = 0;
139
140 int i = 0;
141 for (; i < m_nb; ++i)
142 {
143 int j = entry;
144 for (; j < m_ind[i]; ++j)
145 {
146 double t = (double) (j - entry) / (m_ind[i] - entry);
147 dest[j].rgbRed = (unsigned char) ((1 - t) * col.rgbRed + t * m_col[i].rgbRed);
148 dest[j].rgbGreen = (unsigned char) ((1 - t) * col.rgbGreen + t * m_col[i].rgbGreen);
149 dest[j].rgbBlue = (unsigned char) ((1 - t) * col.rgbBlue + t * m_col[i].rgbBlue);
150 }
151 entry = j;
152 col = m_col[i];
153 }
154 for (; entry < 256; ++entry) dest[entry] = col;
155 }
156
157 ///////////////////////////////////////////////////////////////////////////////
158
PaletteCollection(const int palettes[][NB_PALETTES],int nbPalettes)159 PaletteCollection::PaletteCollection(const int palettes[][NB_PALETTES], int nbPalettes)
160 {
161 m_cpal = new CompressedPalette[nbPalettes];
162 m_nbPalettes = nbPalettes;
163
164 // Set up the palettes from the array
165 for (int i = 0; i < nbPalettes; ++i)
166 {
167 CompressedPalette newpal;
168 const int* pal = palettes[i];
169 for (int j = 1; j < pal[0] * 2; j += 2)
170 {
171 ColorRGB rgb;
172 rgb.rgbRed = (pal[j + 1] & 0xff0000) >> 16;
173 rgb.rgbGreen = (pal[j + 1] & 0xff00) >> 8;
174 rgb.rgbBlue = pal[j + 1] & 0xff;
175 newpal.push_color(pal[j], rgb);
176 }
177 m_cpal[i] = newpal;
178 }
179 }
180
~PaletteCollection()181 PaletteCollection::~PaletteCollection()
182 {
183 delete[] m_cpal;
184 }
185
expandPalette(int i,Palette dest) const186 void PaletteCollection::expandPalette(int i, Palette dest) const
187 {
188 m_cpal[i].expand(dest);
189 }
190
191 ///////////////////////////////////////////////////////////////////////////////
192
blitSurface8To32(unsigned char * byteSurf,int * colorSurf,int palette[256],int size)193 void blitSurface8To32(unsigned char *byteSurf, int *colorSurf, int palette[256], int size)
194 {
195 int i = 0;
196 while(size--) {
197 colorSurf[i++] = palette[byteSurf[size]];
198 }
199 }
200
paletteToRGBA(int dest[256],const Palette src)201 void paletteToRGBA(int dest[256], const Palette src)
202 {
203 for (int i=0; i<256; ++i)
204 dest[i] = ((int)src[i].rgbRed << 16) | ((int)src[i].rgbGreen << 8) | (int)src[i].rgbBlue;
205 }
206