source: abuse/tags/pd/macabuse/imlib/filter.c @ 475

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