source: abuse/trunk/src/imlib/filter.cpp @ 56

Last change on this file since 56 was 56, checked in by Sam Hocevar, 15 years ago
  • Add licensing terms to most C / C++ files (Ref #5).
File size: 5.3 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include "image.hpp"
13#include "macs.hpp"
14#include "filter.hpp"
15
16extern unsigned char current_background;
17
18filter::filter(palette *from, palette *to)   // creates a conversion filter from one palette to another
19{
20  nc=from->pal_size() > to->pal_size() ? from->pal_size() : to->pal_size();
21  unsigned char *p=fdat=(unsigned char *)jmalloc(nc,"conversion filter");
22  unsigned char *r,*g,*b;
23  r=g=b=(unsigned char *)from->addr();
24  g++;
25  b+=2;
26
27  int dk=to->darkest(1);
28  for (int i=0;i<nc;i++,p++,r+=3,g+=3,b+=3)
29  {
30    *p=to->find_closest(*r,*g,*b);
31
32    // make sure non-blacks don't get remapped to the transparency
33    if ((*r!=0 || *g!=0 || *b!=0) && (to->red(*p)==0 && to->green(*p)==0 && to->blue(*p)==0))
34      *p=dk;
35  }
36
37}
38
39void filter::clear()
40{
41  int i;
42  for (i=0;i<nc;i++)
43    fdat[i]=i;
44}
45
46void filter::max_threshold(int minv, char blank)
47{
48  int i;
49  CONDITION(minv>=0 && minv<nc,"Bad minv");
50  for (i=0;i<minv;i++)
51    fdat[i]=blank;
52}
53
54void filter::min_threshold(int maxv, char blank)
55{
56  int i;
57  CONDITION(maxv>=0 && maxv<nc,"bad maxv value in filter::max_thresh");
58  for (i=nc-1;i>=maxv;i--)
59    fdat[i]=(unsigned) blank;
60}
61
62
63void filter::set(int color_num, char change_to)
64{
65  CONDITION(color_num>=0 && color_num<nc,"Bad colors_num");
66  fdat[color_num]=(unsigned) change_to;
67}
68
69
70filter::filter(int colors)
71{
72  CONDITION(colors>=0 && colors<=256,"bad colors value");
73  nc=colors;
74  make_block(nc);
75  fdat=(unsigned char *)jmalloc(nc,"filter");
76  clear();
77}
78
79void filter::apply(image *im)
80{
81  int x,y;
82  unsigned char *c;
83  CONDITION(im,"null image passed in filter::apply\n");
84  for (y=im->height()-1;y>=0;y--)
85  {
86    c=im->scan_line(y);
87    for (x=im->width()-1;x>=0;x--)
88    {
89      CONDITION((unsigned) c[x]<nc,"not enough filter colors");
90      c[x]=fdat[(unsigned) c[x]];
91    }
92  }
93}
94
95
96palette *compare_pal;
97
98int color_compare(void *c1, void *c2)
99{
100  long v1,v2; 
101  unsigned char r1,g1,b1,r2,g2,b2;
102  compare_pal->get(  *((unsigned char *)c1),r1,g1,b1);
103  compare_pal->get(  *((unsigned char *)c2),r2,g2,b2);
104  v1=(int)r1*(int)r1+(int)g1*(int)g1+(int)b1*(int)b1;
105  v2=(int)r2*(int)r2+(int)g2*(int)g2+(int)b2*(int)b2;
106  if (v1<v2) return -1;
107  else if (v1>v2) return 1;
108  else return 0;     
109}
110
111
112/*color_filter::color_filter(palette *pal, int color_bits)
113{
114  unsigned char map[256],*last_start,*start;
115  int i,last_color=0,color;
116  compare_pal=pal; 
117  for (i=0;i,256;i++)
118    map[i]=i;
119
120  qsort(map,1,1,color_compare);
121  colors=1<<color_bits;
122  last_start=color_table=(unsigned char *)malloc(colors*colors*colors);
123
124 
125 
126  last_color=map[0];
127  last_dist=0;
128 
129 
130  for (i=1;i<colors;i++)
131  {   
132    color=map[i<<(8-color_bits)];
133    dist=       
134
135    memset(c,
136  }
137 
138 
139}*/
140
141
142color_filter::color_filter(palette *pal, int color_bits, void (*stat_fun)(int))
143{
144  color_bits=5;      // hard code 5 for now
145  int r,g,b,rv,gv,bv,
146      c=0,i,max=pal->pal_size(),
147      lshift=8-color_bits;
148  unsigned char *pp;
149 
150  long dist_sqr,best;
151  int colors=1<<color_bits;
152  color_table=(unsigned char *)jmalloc(colors*colors*colors,"color_filter");
153  for (r=0;r<colors;r++)
154  {
155    if (stat_fun) stat_fun(r);
156    rv=r<<lshift;   
157    for (g=0;g<colors;g++)
158    {
159      gv=g<<lshift;     
160      for (b=0;b<colors;b++)
161      {
162        bv=b<<lshift;     
163        best=0x7fffffff;
164        for (i=0,pp=(unsigned char *)pal->addr();i<max;i++)
165        {
166          register long rd=*(pp++)-rv,
167                        gd=*(pp++)-gv,
168                        bd=*(pp++)-bv;
169         
170          dist_sqr=(long)rd*rd+(long)bd*bd+(long)gd*gd;
171          if (dist_sqr<best)
172          { best=dist_sqr;
173            c=i;
174          }
175        }
176        color_table[r*colors*colors+g*colors+b]=c;
177      }
178    }
179  } 
180}
181
182color_filter::color_filter(spec_entry *e, bFILE *fp)
183{
184  fp->seek(e->offset,0);
185  fp->read_uint16();
186  int colors=32;
187  color_table=(unsigned char *)jmalloc(colors*colors*colors,"color_filter : loaded");
188  fp->read(color_table,colors*colors*colors);
189}
190
191int color_filter::size()
192{
193  int colors=32;
194  return 2+colors*colors*colors;
195}
196
197int color_filter::write(bFILE *fp)
198{
199  int colors=32;
200  fp->write_uint16(colors);
201  return fp->write(color_table,colors*colors*colors)==colors*colors*colors;
202}
203
204
205void filter::put_image(image *screen, image *im, short x, short y, char transparent)
206{
207  short cx1,cy1,cx2,cy2,x1=0,y1=0,x2=im->width()-1,y2=im->height()-1;
208  screen->get_clip(cx1,cy1,cx2,cy2);
209 
210  // see if the image gets clipped of the screen
211  if (x>cx2 || y>cy2 || x+(x2-x1)<cx1 || y+(y2-y1)<cy1) return ;
212 
213  if (x<cx1)
214  { x1+=(cx1-x); x=cx1; }
215  if (y<cy1)
216  { y1+=(cy1-y); y=cy1; }
217
218  if (x+x2-x1+1>cx2)
219  { x2=cx2-x+x1; }
220
221  if (y+y2-y1+1>cy2)
222  { y2=cy2-y+y1; }
223  if (x1>x2 || y1>y2) return ;   
224
225 
226
227
228  int xl=x2-x1+1;
229  int yl=y2-y1+1;
230
231  screen->add_dirty(x,y,x+xl-1,y+yl-1);
232
233  uint8_t *pg1=screen->scan_line(y),*source,*dest;
234  uint8_t *pg2=im->scan_line(y1);
235  int i;
236  for (int j=0;j<yl;j++)       
237  {
238    for (i=0,source=&pg2[x1],dest=&pg1[x];i<xl;i++,source++,dest++)     
239      if (!transparent || *source!=current_background)
240        *dest=fdat[*source];
241    pg1=screen->next_line(y+j,pg1); 
242    pg2=im->next_line(y1+j,pg2);
243  }
244
245}
246
247
248
249
250
Note: See TracBrowser for help on using the repository browser.