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

Last change on this file since 534 was 524, checked in by Sam Hocevar, 11 years ago

core: Get rid of mostly useless headers, move endianness handling to
common.h (and rewrite functions so that they do not need the SDL headers)
and move a few functions out of sdlport's video.cpp. These functions
were in the original video.cpp (which reappears) and shouldn't be part
of the SDL port.

File size: 5.1 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 or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include "common.h"
14
15#include "image.h"
16#include "filter.h"
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 *)malloc(nc);
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  fdat=(unsigned char *)malloc(nc);
75  clear();
76}
77
78void filter::apply(image *im)
79{
80  int x,y;
81  unsigned char *c;
82  CONDITION(im,"null image passed in filter::apply\n");
83  im->Lock();
84  for (y=im->Size().y-1; y>=0; y--)
85  {
86    c=im->scan_line(y);
87    for (x=im->Size().x-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  im->Unlock();
94}
95
96
97palette *compare_pal;
98
99int color_compare(void *c1, void *c2)
100{
101  long v1,v2;
102  unsigned char r1,g1,b1,r2,g2,b2;
103  compare_pal->get(  *((unsigned char *)c1),r1,g1,b1);
104  compare_pal->get(  *((unsigned char *)c2),r2,g2,b2);
105  v1=(int)r1*(int)r1+(int)g1*(int)g1+(int)b1*(int)b1;
106  v2=(int)r2*(int)r2+(int)g2*(int)g2+(int)b2*(int)b2;
107  if (v1<v2) return -1;
108  else if (v1>v2) return 1;
109  else return 0;
110}
111
112color_filter::color_filter(palette *pal, int color_bits, void (*stat_fun)(int))
113{
114  color_bits=5;      // hard code 5 for now
115  int r,g,b,rv,gv,bv,
116      c=0,i,max=pal->pal_size(),
117      lshift=8-color_bits;
118  unsigned char *pp;
119
120  long dist_sqr,best;
121  int colors=1<<color_bits;
122  color_table=(unsigned char *)malloc(colors*colors*colors);
123  for (r=0; r<colors; r++)
124  {
125    if (stat_fun) stat_fun(r);
126    rv=r<<lshift;
127    for (g=0; g<colors; g++)
128    {
129      gv=g<<lshift;
130      for (b=0; b<colors; b++)
131      {
132    bv=b<<lshift;
133        best=0x7fffffff;
134        for (i=0,pp=(unsigned char *)pal->addr(); i<max; i++)
135        {
136          register long rd=*(pp++)-rv,
137                        gd=*(pp++)-gv,
138                        bd=*(pp++)-bv;
139
140          dist_sqr=(long)rd*rd+(long)bd*bd+(long)gd*gd;
141          if (dist_sqr<best)
142          { best=dist_sqr;
143            c=i;
144          }
145        }
146        color_table[r*colors*colors+g*colors+b]=c;
147      }
148    }
149  }
150}
151
152color_filter::color_filter(spec_entry *e, bFILE *fp)
153{
154  fp->seek(e->offset,0);
155  fp->read_uint16();
156  int colors=32;
157  color_table=(unsigned char *)malloc(colors*colors*colors);
158  fp->read(color_table,colors*colors*colors);
159}
160
161int color_filter::size()
162{
163  int colors=32;
164  return 2+colors*colors*colors;
165}
166
167int color_filter::write(bFILE *fp)
168{
169  int colors=32;
170  fp->write_uint16(colors);
171  return fp->write(color_table,colors*colors*colors)==colors*colors*colors;
172}
173
174
175void filter::put_image(image *screen, image *im, short x, short y,
176                       char transparent)
177{
178    int cx1, cy1, cx2, cy2, x1 = 0, y1 = 0,
179          x2 = im->Size().x, y2 = im->Size().y;
180    screen->GetClip(cx1, cy1, cx2, cy2);
181
182    // see if the image gets clipped off the screen
183    if(x >= cx2 || y >= cy2 || x + (x2 - x1) <= cx1 || y + (y2 - y1) <= cy1)
184        return;
185
186    if(x < cx1)
187    {
188        x1 += (cx1 - x);
189        x = cx1;
190    }
191    if(y < cy1)
192    {
193        y1 += (cy1 - y);
194         y = cy1;
195    }
196
197    if(x + x2 - x1 >= cx2)
198        x2 = cx2 - x + x1;
199
200    if(y + y2 - y1 >= cy2)
201        y2 = cy2 - y + y1;
202
203    if(x1 >= x2 || y1 >= y2)
204        return;
205
206    int xl = x2 - x1;
207    int yl = y2 - y1;
208
209    screen->AddDirty(x, y, x + xl, y + yl);
210
211    screen->Lock();
212    im->Lock();
213
214    uint8_t *pg1 = screen->scan_line(y), *source, *dest;
215    uint8_t *pg2 = im->scan_line(y1);
216    int i;
217    for(int j = 0; j < yl; j++)
218    {
219        for(i = 0, source = &pg2[x1], dest = &pg1[x];
220            i < xl;
221            i++, source++, dest++)
222        {
223            if (!transparent || *source)
224                *dest=fdat[*source];
225        }
226        pg1 = screen->next_line(y + j, pg1);
227        pg2 = im->next_line(y1 + j, pg2);
228    }
229
230    im->Unlock();
231    screen->Unlock();
232}
233
Note: See TracBrowser for help on using the repository browser.