source: abuse/trunk/src/imlib/palette.cpp @ 682

Last change on this file since 682 was 653, checked in by Sam Hocevar, 9 years ago

imlib: remove unused code and tag unused method arguments.

File size: 8.7 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <math.h>
16
17#include "common.h"
18
19#include "palette.h"
20#include "image.h"
21#include "video.h"
22#include "filter.h"
23
24palette *lastl=NULL;
25
26palette::palette(bFILE *fp)
27{
28  ncolors=fp->read_uint16();
29  pal=(color *)malloc(sizeof(color)*ncolors);
30  usd=(unsigned char *)malloc(ncolors/8+1);
31  set_all_unused();
32  fp->read(pal,sizeof(color)*ncolors);
33  bg=0;
34}
35
36palette::palette(spec_entry *e, bFILE *fp)
37{
38  fp->seek(e->offset,0);
39  ncolors=fp->read_uint16();
40  pal=(color *)malloc(sizeof(color)*ncolors);
41  usd=(unsigned char *)malloc(ncolors/8+1);
42  set_all_unused();
43  fp->read(pal,sizeof(color)*ncolors);
44  bg=0;
45}
46
47int palette::size()
48{
49  return ncolors*sizeof(color)+2;
50}
51
52int palette::write(bFILE *fp)
53{
54  fp->write_uint16(ncolors);
55  return fp->write(pal,sizeof(color)*ncolors)==ncolors;
56}
57
58int palette::find_closest(uint8_t r, uint8_t g, uint8_t b)
59{
60   unsigned char *cl=(unsigned char *)addr();
61   int c=0,d=0x100000,i,nd;
62   for (i=0; i<256; i++)
63   {
64     nd=((int)r-(int)(*cl))*((int)r-(int)(*cl)); cl++;
65     nd+=((int)g-(int)(*cl))*((int)g-(int)(*cl)); cl++;
66     nd+=((int)b-(int)(*cl))*((int)b-(int)(*cl)); cl++;
67     if (nd<d)
68     { c=i; d=nd; }
69   }
70   return c;
71}
72
73int palette::find_color(uint8_t r, uint8_t g, uint8_t b)
74{
75  int i,ub,mask,find;
76  for (i=0,ub=0,mask=128,find=-1; i<ncolors && find<0; i++)
77  {
78    if (usd[ub]&mask)
79      if (r==pal[i].red && b==pal[i].blue && g==pal[i].green)
80    find=i;
81    mask>>=1;
82    if (mask==0)
83    { mask=128; ub++; }
84  }
85  return find;
86}
87
88uint32_t palette::getquad(int x)
89{ union { char entry[4]; uint32_t ret; };
90  entry[3]=0;
91  entry[2]=pal[x].red;
92  entry[1]=pal[x].green;
93  entry[0]=pal[x].blue;
94  return ret;
95}
96
97
98void palette::black_white()
99{
100  int i;
101  unsigned char r,g,b,gr;
102
103  for (i=0; i<256; i++)
104  {
105    get(i,r,g,b);
106    gr=(unsigned char)((double) r*0.30+(double) g*0.59+(double)b*0.11);
107    set(i,gr,gr,gr);
108  }
109}
110
111void palette::make_black_white()
112{
113  int i,c;
114  set(0,0,0,0);
115  for (i=1; i<ncolors; i++)
116  { c=(int)((double)i/(double)ncolors*(double)255);
117    set(i,c,c,c);
118  }
119}
120
121void palette::set_rgbs()
122{
123  int i,v;
124  CHECK(ncolors==256);
125  for (i=0; i<64; i++)
126  {
127    if (i==0) v=0;
128    else
129    {
130      v=(int) ((double)i+(double)(sqrt(63.0-i)));
131      v<<=2;
132    }
133
134    set(i,         i,     0,     0);            // reds 0-63
135    set(i+64,      0,     i,     0);
136    set(i+128,     0,     0,     i);       // blues 128-191
137    set(i+128+64,  v,     v,     v);        // whites .. rest
138  }
139  set_all_used();
140}
141
142void palette::set_all_used()
143{
144  int i;
145  for (i=0; i<ncolors; i++) set_used(i);
146}
147
148void palette::set_all_unused()
149{
150  int i;
151  for (i=0; i<ncolors; i++) set_unused(i);
152}
153
154
155palette *palette::copy()
156{
157  palette *p;
158  int i;
159  p=new palette(ncolors);
160  for (i=0; i<ncolors; i++)
161  {
162    if (used(i))
163      p->set_used(i);
164    else p->set_unused(i);
165    p->set(i,red(i),green(i),blue(i));
166  }
167  return p;
168}
169
170void palette::set_used(int color_num)
171{
172  int x,b;
173  CHECK(color_num>=0 && color_num<ncolors);
174  x=color_num/8;
175  b=color_num%8;
176  usd[x]|=(128>>b);
177}
178
179void palette::set_unused(int color_num)
180{
181  int x,b;
182  CHECK(color_num>=0 && color_num<ncolors);
183  x=color_num/8;
184  b=color_num%8;
185  usd[x]&=(0xff^(128>>b));
186}
187
188int palette::used(int color_num)
189{
190  int x,b;
191  CHECK(color_num>=0 && color_num<ncolors);
192  x=color_num/8;
193  b=color_num%8;
194  return (usd[x]&(128>>b));
195}
196
197void palette::defaults()
198{
199  int i;
200  set(0,0,0,0);
201  set_used(0);
202  for (i=1; i<ncolors; i++)
203    set_unused(i);
204  if (ncolors==256)
205    for (i=0; i<ncolors; i++)
206      set(i,RED3(i),GREEN3(i),BLUE2(i));
207  else if (ncolors==16)
208    for (i=0; i<ncolors; i++)
209      set(i,255-(i&3),255-((i&4)>>2),255-((i&8)>>3));
210  else
211    for (i=0; i<ncolors; i++)
212      set(i,255-(i%3),255-((i+1)%3),255-((i+2)%3));
213}
214
215void palette::shift(int amount)
216{
217  int i;
218  unsigned char m;
219  if (amount<0)
220  {
221
222    m=-amount;
223    for (i=0; i<ncolors*3; i++)
224      ((unsigned char *) pal)[i]>>=m;
225  }
226  else if (amount>0)
227  {
228    m=amount;
229    for (i=0; i<ncolors*3; i++)
230      ((unsigned char *) pal)[i]<<=m;
231  }
232}
233
234
235
236void palette::set(int x, unsigned char red, char unsigned green, char unsigned blue)
237{ CONDITION(x>=0 && x<ncolors,"Pallete::set passed bad x");
238  CONDITION((int)red<=ncolors && (int)green<=ncolors && (int)blue<=ncolors,
239        "pallette::set color values bigger than palette");
240  pal[x].red=red; pal[x].green=green; pal[x].blue=blue;
241}
242
243void palette::get(int x, unsigned char &red, unsigned char &green, unsigned char &blue)
244{ CONDITION(x>=0 && x<ncolors,"Pallete::get passed bad x");
245  red=pal[x].red; green=pal[x].green; blue=pal[x].blue;
246}
247palette::~palette()
248{ if (pal) free(pal);
249  if (usd) free(usd);
250}
251
252palette::palette(int number_colors)
253{
254  CONDITION(number_colors>0,"palette::constructor - need at least one color!");
255  ncolors=number_colors;
256  bg=0;
257  pal=(color *)malloc(ncolors*3);
258  usd=(unsigned char *)malloc(ncolors/8+1);
259  defaults();
260}
261
262
263
264quant_node::~quant_node()
265{
266/*  if (!is_leaf())
267  { for (i=0; i<8; i++)
268      if (children[i])
269      {    delete children[i];
270    children[i]=NULL;
271      }
272  } */
273}
274
275
276/*void quant_node::prune()
277{
278  int t,r,g,b;
279  CONDITION(!is_leaf(),"Cannot prune a leaf!");
280  total(t,r,g,b);
281  red=r/t;
282  green=g/t;
283  blue=b/t;
284  be_childish();
285} */
286
287void quant_node::total(int &tnodes, int &tr, int &tg, int &tb)
288{
289  int i;
290  if (is_leaf())
291  { tnodes+=tot;
292    tr+=red*tot;
293    tg+=green*tot;
294    tb+=blue*tot;
295  }
296  else
297  { for (i=0; i<8; i++)
298      if (children[i])
299    children[i]->total(tnodes,tr,tg,tb);
300  }
301}
302
303quant_node::quant_node(int level, quant_node *dad,
304    unsigned char r, unsigned char g, unsigned char b)
305{
306  int i;
307  CONDITION(level<=8,"Tree cannot have more than eight levels");
308  if (level==8)
309    be_childish();
310  else
311    for (i=0; i<8; i++) children[i]=NULL;
312  padre=dad;
313  red=r; green=g; blue=b;
314  tot=0;
315}
316
317quant_palette::quant_palette(int max_colors)
318{ root=NULL; nc=0; mx=max_colors; }
319
320void quant_palette::re_delete(quant_node *who, int lev)  // removes all children from memory
321{ int x;                                  // and recurses down
322  if (who)
323  {
324    if (!who->is_leaf())
325    { for (x=0; x<8; x++)
326    if (who->children[x])
327    {
328      CONDITION(lev<8,"Levl > 7");
329      re_delete(who->children[x],lev+1);
330      level[lev].unlink(who->children[x]);
331      delete who->children[x];
332    }
333    }
334  }
335}
336
337void quant_palette::prune()
338{
339  int pruned,lev,x,r,g,b,t;
340  quant_node *p=NULL,*f=NULL;
341  for (pruned=0,lev=8; lev>1 && !pruned; lev--)
342  {
343    p=(quant_node *)level[lev-1].first();
344    if (p)
345    { do
346      {
347    f=p->father();
348    for (x=0; x<8 && !pruned; x++)
349      if (f->children[x])
350        if (f->children[x]->Next()!=p->Next())        // if this son is not me!
351        pruned=1;                   //  I have a brother! stop
352       p=(quant_node *)p->Next();
353      } while (p != level[lev-1].first() && !pruned);
354    }
355  }
356  CONDITION(lev>0,"could not prune!");
357  t=0; r=0; g=0; b=0;
358  f->total(t,r,g,b);
359  if (t<=1)
360  {
361    t=0; r=0; g=0; b=0;
362    f->total(t,r,g,b);
363  }
364  CONDITION(t>1,"Should be more colors\n");
365  printf("%d Pruned at level %d, r=%d, g=%d, b=%d, total nodes off = %d\n",nc,
366    lev,r/t,g/t,b/t,t);
367  f->set(r/t,g/t,b/t);
368  nc-=t;
369  nc++;
370  re_delete(f,lev);
371  f->be_childish();
372}
373
374quant_palette::~quant_palette()
375{
376  if (root)
377  {
378    re_delete(root,1);
379    delete root;
380  }
381}
382
383uint8_t palette::brightest(int all)
384{ uint8_t r,g,b,bri;
385  unsigned i;
386  long brv;
387  brv=0; bri=0;
388
389  for (i=0; i<(unsigned int)ncolors; i++)
390  { if (all || used(i))
391    {
392      get(i,r,g,b);
393      if ((long)r*(long)g*(long)b>brv)
394      { brv=(long)r*(long)g*(long)b;
395    bri=i;
396      }
397    }
398  }
399
400  return bri;
401}
402
403uint8_t palette::darkest(int all, int noblack)
404{ uint8_t r,g,b,bri;
405  unsigned i;
406  long brv,x;
407  brv=(long)258*(long)258*(long)258; bri=0;
408
409  for (i=0; i<(unsigned int)ncolors; i++)
410  { if (all || used(i))
411    {
412      get(i,r,g,b);
413      x=(long)r*(long)g*(long)b;
414      if (x<brv && (x || !noblack))
415      { brv=(long)r*(long)g*(long)b;
416    bri=i;
417      }
418    }
419  }
420  return bri;
421}
422
423
424
425palette *last_loaded()
426{ return lastl; }
427
428void palette::fade_to(int total_fades, int fade_on, int dest_r, int dest_g, int dest_b)
429{
430  uint8_t *sl=(uint8_t *)addr();
431  uint8_t x;
432  int i;
433  for (i=0; i<ncolors; i++)
434  {
435    x=(( dest_r-(int)*sl)*fade_on/total_fades+*sl);
436    *(sl++)=x;
437    x=(( dest_g-(int)*sl)*fade_on/total_fades+*sl);
438    *(sl++)=x;
439    x=(( dest_b-(int)*sl)*fade_on/total_fades+*sl);
440    *(sl++)=x;
441  }
442}
Note: See TracBrowser for help on using the repository browser.