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