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

Last change on this file since 115 was 115, checked in by Sam Hocevar, 11 years ago
  • Add lock() and unlock() methods to jimage objects. They're no-ops, but the Win32/DirectX version uses them all over the place because it uses DirectDraw? surfaces. One day we may wish to merge Abuse Win32's video output, or to use the SDL blending functions. You never know.
File size: 5.6 KB
RevLine 
[56]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
[2]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{
[115]100  long v1,v2;
[2]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;
[115]108  else return 0;
[2]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;
[115]116  compare_pal=pal;
[2]117  for (i=0;i,256;i++)
118    map[i]=i;
119
[115]120  qsort(map,1,1,color_compare);
[2]121  colors=1<<color_bits;
122  last_start=color_table=(unsigned char *)malloc(colors*colors*colors);
123
[115]124
125
[2]126  last_color=map[0];
127  last_dist=0;
[115]128
129
[2]130  for (i=1;i<colors;i++)
[115]131  {
[2]132    color=map[i<<(8-color_bits)];
[115]133    dist=
[2]134
135    memset(c,
136  }
[115]137
138
[2]139}*/
140
141
142color_filter::color_filter(palette *pal, int color_bits, void (*stat_fun)(int))
[115]143{
[2]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;
[115]149
[2]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);
[115]156    rv=r<<lshift;
[2]157    for (g=0;g<colors;g++)
158    {
[115]159      gv=g<<lshift;
[2]160      for (b=0;b<colors;b++)
161      {
[115]162        bv=b<<lshift;
[2]163        best=0x7fffffff;
164        for (i=0,pp=(unsigned char *)pal->addr();i<max;i++)
[115]165        {
[2]166          register long rd=*(pp++)-rv,
167                        gd=*(pp++)-gv,
168                        bd=*(pp++)-bv;
[115]169       
[2]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    }
[115]179  }
[2]180}
181
182color_filter::color_filter(spec_entry *e, bFILE *fp)
183{
184  fp->seek(e->offset,0);
[17]185  fp->read_uint16();
[2]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;
[17]200  fp->write_uint16(colors);
[2]201  return fp->write(color_table,colors*colors*colors)==colors*colors*colors;
202}
203
204
[115]205void filter::put_image(image *screen, image *im, short x, short y,
206                       char transparent)
[2]207{
[115]208    short cx1, cy1, cx2, cy2, x1 = 0, y1 = 0,
209          x2 = im->width() - 1, y2 = im->height() - 1;
210    screen->get_clip(cx1,cy1,cx2,cy2);
[2]211
[115]212    // see if the image gets clipped off the screen
213    if(x > cx2 || y > cy2 || x + (x2 - x1) < cx1 || y + (y2 - y1) < cy1)
214        return;
[2]215
[115]216    if(x < cx1)
217    {
218        x1 += (cx1 - x);
219        x = cx1;
220    }
221    if(y < cy1)
222    {
223        y1 += (cy1 - y);
224         y = cy1;
225    }
[2]226
[115]227    if(x + x2 - x1 + 1 > cx2)
228        x2 = cx2 - x + x1;
[2]229
[115]230    if(y + y2 - y1 + 1 > cy2)
231        y2 = cy2 - y + y1;
[2]232
[115]233    if(x1 > x2 || y1 > y2)
234        return;
[2]235
[115]236    int xl = x2 - x1 + 1;
237    int yl = y2 - y1 + 1;
[2]238
[115]239    screen->add_dirty(x, y, x + xl - 1, y + yl - 1);
[2]240
[115]241    screen->lock();
242    im->lock();
[2]243
[115]244    uint8_t *pg1 = screen->scan_line(y), *source, *dest;
245    uint8_t *pg2 = im->scan_line(y1);
246    int i;
247    for(int j = 0; j < yl; j++)
248    {
249        for(i = 0, source = &pg2[x1], dest = &pg1[x];
250            i < xl;
251            i++, source++, dest++)     
252        {
253            if(!transparent || *source != current_background)
254                *dest=fdat[*source];
255        }
256        pg1 = screen->next_line(y + j, pg1);
257        pg2 = im->next_line(y1 + j, pg2);
258    }
[2]259
[115]260    im->unlock();
261    screen->unlock();
262}
[2]263
Note: See TracBrowser for help on using the repository browser.