source: abuse/tags/pd/macabuse/imlib/supmorph.c @ 528

Last change on this file since 528 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: 8.5 KB
Line 
1#include "supmorph.hpp"
2#include "specs.hpp"
3#include "timage.hpp"
4#include "timing.hpp"
5#include "filter.hpp"
6#include "video.hpp"
7#include "jrand.hpp"
8
9#define p_swap(x,y) { x^=y; y^=x; x^=y; }
10#define p_dist(x1,y1,x2,y2) (((int)(x1)-(int)x2)*((int)(x1)-(int)x2)+      \
11                             ((int)(y1)-(int)y2)*((int)(y1)-(int)y2))
12
13super_morph::super_morph(trans_image *hint1, trans_image *hint2,
14                         int aneal_steps, void (*stat_fun)(int))
15{
16  int x,y,w1=hint1->width(),
17          h1=hint1->height(),
18          w2=hint2->width(),
19          h2=hint2->height();
20  if (w1>w2) w=w1; else w=w2;
21  if (h1>h2) h=h1; else h=h2;
22  unsigned char *dp;
23
24  /************************ count up the number of hints ****************************/
25  unsigned short hints1[256],hints2[256];
26  memset(hints1,0,256*2);
27  memset(hints2,0,256*2);
28
29  dp=hint1->t_data();
30  for (y=0;y<h1;y++)
31  {
32    x=0;
33    while (x<w1)
34    {     
35      x+=*dp;      // skip over space
36      dp++;
37      if (x<w1)
38      {
39        int rl=*(dp++);
40        while (rl--) { hints1[*(dp++)]++; x++; }
41      }
42    }
43  }
44
45  // hint2 image2
46  dp=hint2->t_data();
47  for (y=0;y<h2;y++)
48  {
49    x=0;
50    while (x<w2)
51    {     
52      x+=*dp;      // skip over space
53      dp++;
54      if (x<w2)
55      {
56        int rl=*(dp++);
57        while (rl--) { hints2[*(dp++)]++; x++; }
58      }
59    }
60  }
61
62
63  /****************** now sum up hints and alloc memory for movers *************/
64  unsigned short start1[256],start2[256],
65                 totals[256],
66                 start=0,*h1p=hints1,*h2p=hints2;
67  unsigned char hint_color[256],total_hints=0;
68
69  for (y=0;y<256;y++,h1p++,h2p++)
70    if (*h1p)
71    {
72      if (*h2p==0) 
73      {
74        t=0;
75        return ;
76      }
77      start1[y]=start2[y]=start;       // specify start of hint range
78      if (*h1p>*h2p)
79        totals[y]=*h1p;
80      else totals[y]=*h2p;
81      start+=totals[y];
82      hint_color[total_hints++]=y;     
83    }
84
85  t=start;
86  movers=(unsigned char *)jmalloc(t*4,"morph movers");
87 
88 
89  /**************** Now scan the images again setup hints *********************/
90  dp=hint1->t_data();
91  for (y=0;y<h1;y++)
92  {
93    x=0;
94    while (x<w1)
95    {     
96      x+=*dp;      // skip over space
97      dp++;
98      if (x<w1)
99      {
100        int rl=*(dp++);
101        while (rl--)
102        {
103          int maddr=(start1[*(dp++)]++)*4;
104          movers[(maddr++)]=x;
105          movers[maddr]=y;
106          x++;
107        }
108      }
109    }
110  } 
111
112  dp=hint2->t_data();
113  for (y=0;y<h2;y++)
114  {
115    x=0;
116    while (x<w2)
117    {     
118      x+=*dp;      // skip over space
119      dp++;
120      if (x<w2)
121      {
122        int rl=*(dp++);
123        while (rl--)
124        {
125          int maddr=(start2[*(dp++)]++)*4+2;
126          movers[(maddr++)]=x;
127          movers[maddr]=y;
128          x++;
129        }
130      }
131    }
132  } 
133
134  /********* if hint sizes don't match duplicate the smaller until sizes are equal **********/
135  for (start=0,x=0;x<total_hints;x++)
136  {
137    y=hint_color[x];
138    int dups;
139    for (dp=movers+start1[y]*4,dups=totals[y]-hints1[y];dups;dups--)
140    {
141      *dp=*(dp-4); dp++;      // copy previous x,y position
142      *dp=*(dp-4); dp++;
143      dp+=2;   
144    }
145    start1[y]-=2*totals[y]-hints1[y];        // set the start back to the begining of hint range
146  }
147
148  for (start=0,x=0;x<total_hints;x++)
149  {
150    y=hint_color[x];
151    int dups;
152    for (dp=movers+start2[y]*4+2,dups=totals[y]-hints2[y];dups;dups--)
153    {
154      *dp=*(dp-4); dp++;      // copy previous x,y position
155      *dp=*(dp-4); dp++;
156      dp+=2;   
157    }
158    start2[y]-=hints2[y];        // set the start back to the begining of hint range
159  }
160
161
162  /******* Now apply simulated annealing to solve for a smaller total distance ********/
163  int rand_on=0;
164  for (y=0;y<aneal_steps;y++)
165  {
166    if (stat_fun)
167      stat_fun(y);
168    dp=movers;   
169    for (x=0;x<total_hints;x++)
170    {
171      int hc=hint_color[x];
172      int a,z=totals[hc];
173      unsigned char *range_start=dp;
174      for (a=0;a<z;a++,dp+=4)
175      {
176        unsigned char *swap=range_start+(rtable[((rand_on++)&(RAND_TABLE_SIZE-1))]%z)*4;
177        int d_old=p_dist(dp[0],dp[1],dp[2],dp[3])+p_dist(swap[0],swap[1],swap[2],swap[3]);
178        int d_new=p_dist(dp[0],dp[1],swap[2],swap[3])+p_dist(swap[0],swap[1],dp[2],dp[3]);
179        if (d_new<d_old)
180        {
181          unsigned char s;
182          s=swap[2]; swap[2]=dp[2]; dp[2]=s;
183          s=swap[3]; swap[3]=dp[3]; dp[3]=s;
184        }
185      }     
186    }   
187  }
188}
189
190smorph_player::smorph_player(super_morph *m, palette *pal, image *i1, image *i2, int frames, int dir)
191{
192  int i,x1,y1,x2,y2;
193  unsigned char *d=m->movers,*paddr=(unsigned char *)pal->addr(),*pa;
194  stepper *p;
195  p=steps=(stepper *)jmalloc(sizeof(stepper)*m->t,"smorph steps");
196  f_left=frames;
197  frames--;
198  t=m->t;
199  w=m->w; h=m->h;
200
201  for (i=0;i<t;i++,p++)
202  {   
203    x1=*(d++);
204    y1=*(d++);
205    x2=*(d++);
206    y2=*(d++);
207   
208    unsigned char r1,g1,b1,r2,g2,b2;
209    pa=paddr+(int)(*(i1->scan_line(y1)+x1))*3;
210    r1=*(pa++);
211    g1=*(pa++);
212    b1=*(pa++);
213   
214    pa=paddr+(int)(*(i2->scan_line(y2)+x2))*3;
215    r2=*(pa++);
216    g2=*(pa++);
217    b2=*(pa++);
218
219    p->r=r1<<16;
220    p->g=g1<<16;
221    p->b=b1<<16;
222
223    p->dr=(long)(((int)r2-(int)r1)<<16)/frames;
224    p->dg=(long)(((int)g2-(int)g1)<<16)/frames;
225    p->db=(long)(((int)b2-(int)b1)<<16)/frames;
226
227    if (dir<0)
228    {
229      x1=w-x1-1;
230      x2=w-x2-1;
231    }
232    p->dx=((x2-x1)<<16)/frames;
233    p->dy=((y2-y1)<<16)/frames;
234    p->x=x1<<16;
235    p->y=y1<<16;
236  }
237
238  hole=(unsigned char *)jmalloc(w*h,"hole image");
239}
240
241
242
243
244
245int smorph_player::show(image *screen, int x, int y, color_filter *fil, palette *pal,
246                        int blur_threshold)
247
248  if (f_left)
249  {
250    int i,px,py,ix,iy;
251    short x1,y1,x2,y2;
252    screen->get_clip(x1,y1,x2,y2);
253    screen->add_dirty(x,y,x+w-1,y+h-1);
254    stepper *ss;
255    memset(hole,0,w*h);
256    unsigned char *paddr=(unsigned char *)pal->addr();
257    for (ss=steps,i=0;i<t;i++,ss++)
258    {
259      ix=(ss->x>>(16));
260      iy=(ss->y>>(16));
261      px=ix+x;
262      py=iy+y;
263      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)                 
264      {
265        hole[ix+iy*w]=*(screen->scan_line(py)+px)=fil->lookup_color(ss->r>>(19),
266                                                                    ss->g>>(19),
267                                                                    ss->b>>(19));
268      }
269      ss->x+=ss->dx;
270      ss->y+=ss->dy;
271      ss->r+=ss->dr;
272      ss->g+=ss->dg;
273      ss->b+=ss->db;         
274    }
275    f_left--;
276    if (!f_left)    // skip hole fills and smoothing on last frame
277      return 1;
278
279    unsigned char *ll=hole+1,*tl=hole+w+1,*nl=hole+w*2+1;
280    for (iy=1;iy<h-1;iy++)    // now scan the for holes to fill
281    {
282      for (ix=1;ix<w-1;ix++,ll++,tl++,nl++)
283      {
284        if (x+ix>=x1 && x+ix<=x2 && y+iy>=y1 && y+iy<=y2)
285        {
286          int t=0;
287          unsigned char *pa;
288          int r=0,g=0,b=0;
289/*        if (*(tl-1)) t++;
290          if (*(tl+1)) t++;
291          if (*ll) t++;
292          if (*nl) t++;*/
293
294          if (*(tl-1)) { t++; pa=paddr+(*(tl-1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
295          if (*(tl+1)) { t++; pa=paddr+(*(tl+1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
296          if (*(ll)) { t++; pa=paddr+(*ll)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
297          if (*(nl)) { t++; pa=paddr+(*nl)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }         
298
299          if (*tl)
300          {
301            if (t)
302            {
303              pa=paddr+(*tl)*3;
304              r/=t; g/=t; b/=t;
305              int dist=((int)(*pa)-r)*((int)(*pa)-r); pa++;
306              dist+=((int)(*pa)-g)*((int)(*pa)-g); pa++;
307              dist+=((int)(*pa)-b)*((int)(*pa)-b);
308              if (dist>blur_threshold)
309                *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color(r>>3,g>>3,b>>3);
310            } else *(tl)=*(screen->scan_line(y+iy)+x+ix)=0; // kill single pixels
311          }
312          else if (t>=3)
313            *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color((r/t)>>3,(g/t)>>3,(b/t)>>3);
314        }
315      }
316      ll+=2;
317      tl+=2;
318      nl+=2;     
319    }
320    return 1;
321  } else return 0;
322}
323
324
325
326
327/*void free_up_memory() { dprintf("you're screwed\n"); }
328
329main(int argc, char **argv)
330{
331  image_init();
332  jrand_init();
333  FILE *fp=fopen("art/mrphmask.spe","rb");
334  spec_directory sd(fp);
335  image *h1=new image(sd.find("20 h"),fp),
336        *h2=new image(sd.find("1h"),fp),
337        *i1=new image(sd.find("20"),fp),
338        *i2=new image(sd.find("1"),fp);
339  palette *pal=new palette(sd.find(SPEC_PALETTE),fp);
340  color_filter *fil=new color_filter(sd.find(SPEC_COLOR_TABLE),fp); 
341
342  int steps=atoi(argv[1]);
343  if (steps<2) steps=50;
344  trans_image *hh1=new trans_image(h1,"hint1"),*hh2=new trans_image(h2,"hint2");
345
346  time_marker time1;
347  super_morph sm(hh1,hh2,steps);
348  int frames=atoi(argv[2]);
349  if (frames<2) frames=16;
350  smorph_player sp(&sm,pal,i1,i2,frames,-1);
351
352  time_marker time2;
353  dprintf("time = %lf\n",time2.diff_time(&time1));
354
355  set_mode(19,argc,argv);
356  pal->load();
357  i1->put_image(screen,30,30);
358  update_dirty(screen);
359  sleep(2);
360  while (sp.show(screen,30,30,fil,pal))
361  { update_dirty(screen);
362    screen->bar(30,30,30+sp.w,30+sp.h,0);
363  }
364  sleep(2);
365  close_graphics();
366}*/
367
368
Note: See TracBrowser for help on using the repository browser.