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

Last change on this file since 129 was 129, checked in by Sam Hocevar, 15 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
File size: 5.2 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 *)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  make_block(nc);
75  fdat=(unsigned char *)malloc(nc);
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  im->lock();
85  for (y=im->height()-1;y>=0;y--)
86  {
87    c=im->scan_line(y);
88    for (x=im->width()-1;x>=0;x--)
89    {
90      CONDITION((unsigned) c[x]<nc,"not enough filter colors");
91      c[x]=fdat[(unsigned) c[x]];
92    }
93  }
94  im->unlock();
95}
96
97
98palette *compare_pal;
99
100int color_compare(void *c1, void *c2)
101{
102  long v1,v2;
103  unsigned char r1,g1,b1,r2,g2,b2;
104  compare_pal->get(  *((unsigned char *)c1),r1,g1,b1);
105  compare_pal->get(  *((unsigned char *)c2),r2,g2,b2);
106  v1=(int)r1*(int)r1+(int)g1*(int)g1+(int)b1*(int)b1;
107  v2=(int)r2*(int)r2+(int)g2*(int)g2+(int)b2*(int)b2;
108  if (v1<v2) return -1;
109  else if (v1>v2) return 1;
110  else return 0;
111}
112
113color_filter::color_filter(palette *pal, int color_bits, void (*stat_fun)(int))
114{
115  color_bits=5;      // hard code 5 for now
116  int r,g,b,rv,gv,bv,
117      c=0,i,max=pal->pal_size(),
118      lshift=8-color_bits;
119  unsigned char *pp;
120
121  long dist_sqr,best;
122  int colors=1<<color_bits;
123  color_table=(unsigned char *)malloc(colors*colors*colors);
124  for (r=0;r<colors;r++)
125  {
126    if (stat_fun) stat_fun(r);
127    rv=r<<lshift;
128    for (g=0;g<colors;g++)
129    {
130      gv=g<<lshift;
131      for (b=0;b<colors;b++)
132      {
133    bv=b<<lshift;
134        best=0x7fffffff;
135        for (i=0,pp=(unsigned char *)pal->addr();i<max;i++)
136        {
137          register long rd=*(pp++)-rv,
138                        gd=*(pp++)-gv,
139                        bd=*(pp++)-bv;
140   
141          dist_sqr=(long)rd*rd+(long)bd*bd+(long)gd*gd;
142          if (dist_sqr<best)
143          { best=dist_sqr;
144            c=i;
145          }
146        }
147        color_table[r*colors*colors+g*colors+b]=c;
148      }
149    }
150  }
151}
152
153color_filter::color_filter(spec_entry *e, bFILE *fp)
154{
155  fp->seek(e->offset,0);
156  fp->read_uint16();
157  int colors=32;
158  color_table=(unsigned char *)malloc(colors*colors*colors);
159  fp->read(color_table,colors*colors*colors);
160}
161
162int color_filter::size()
163{
164  int colors=32;
165  return 2+colors*colors*colors;
166}
167
168int color_filter::write(bFILE *fp)
169{
170  int colors=32;
171  fp->write_uint16(colors);
172  return fp->write(color_table,colors*colors*colors)==colors*colors*colors;
173}
174
175
176void filter::put_image(image *screen, image *im, short x, short y,
177                       char transparent)
178{
179    short cx1, cy1, cx2, cy2, x1 = 0, y1 = 0,
180          x2 = im->width() - 1, y2 = im->height() - 1;
181    screen->get_clip(cx1,cy1,cx2,cy2);
182
183    // see if the image gets clipped off the screen
184    if(x > cx2 || y > cy2 || x + (x2 - x1) < cx1 || y + (y2 - y1) < cy1)
185        return;
186
187    if(x < cx1)
188    {
189        x1 += (cx1 - x);
190        x = cx1;
191    }
192    if(y < cy1)
193    {
194        y1 += (cy1 - y);
195         y = cy1;
196    }
197
198    if(x + x2 - x1 + 1 > cx2)
199        x2 = cx2 - x + x1;
200
201    if(y + y2 - y1 + 1 > cy2)
202        y2 = cy2 - y + y1;
203
204    if(x1 > x2 || y1 > y2)
205        return;
206
207    int xl = x2 - x1 + 1;
208    int yl = y2 - y1 + 1;
209
210    screen->add_dirty(x, y, x + xl - 1, y + yl - 1);
211
212    screen->lock();
213    im->lock();
214
215    uint8_t *pg1 = screen->scan_line(y), *source, *dest;
216    uint8_t *pg2 = im->scan_line(y1);
217    int i;
218    for(int j = 0; j < yl; j++)
219    {
220        for(i = 0, source = &pg2[x1], dest = &pg1[x];
221            i < xl;
222            i++, source++, dest++)   
223        {
224            if(!transparent || *source != current_background)
225                *dest=fdat[*source];
226        }
227        pg1 = screen->next_line(y + j, pg1);
228        pg2 = im->next_line(y1 + j, pg2);
229    }
230
231    im->unlock();
232    screen->unlock();
233}
234
Note: See TracBrowser for help on using the repository browser.