source: abuse/trunk/src/imlib/morph.cpp @ 112

Last change on this file since 112 was 112, checked in by Sam Hocevar, 11 years ago
  • Fix spelling errors all over the place.
File size: 25.5 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/* FIXME: this file is unused */
11
12#include "config.h"
13
14#include "morph.hpp"
15
16long trans(long x1, long x2, long frame)
17{
18  return (((x2-x1)<<5)*frame+(x1<<8))>>8; 
19}
20
21
22void jmorph::show_step_frame(image *screen, int x, int y, int frame_on,
23                       color_filter *fli, palette *pal)
24{
25  short x1,y1,x2,y2;
26  unsigned char r1,g1,b1,r2,g2,b2;
27  screen->get_clip(x1,y1,x2,y2);
28 
29  int i;
30  long xx,yy;
31 
32  if (small)
33  {
34    morph_point8 *m8=(morph_point8 *)p;
35    for (i=0;i<total;i++,m8++)
36    {
37      xx=x+trans(m8->x1,m8->x2,frame_on);
38      yy=y+trans(m8->y1,m8->y2,frame_on);
39     
40      if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
41      {
42        pal->get(m8->start_color,r1,g1,b1);
43        pal->get(m8->end_color,r2,g2,b2);
44 
45        long r=trans(r1,r2,frame_on)>>3,
46             g=trans(g1,g2,frame_on)>>3,
47             b=trans(b1,b2,frame_on)>>3;
48       
49        *(screen->scan_line(yy)+xx)=fli->lookup_color(r,g,b);
50      }           
51    }
52  }   
53}
54
55
56void patched_morph::show_frame(image *screen, int x, int y,
57                               int frame_on, color_filter *fli, palette *pal)
58{
59  jmorph::show_step_frame(screen,x,y,frame_on,fli,pal);
60  int tot=pats[frame_on].patches,xx,yy;
61  unsigned char *p=pats[frame_on].patch_data;
62  short cx1,cy1,cx2,cy2;
63  screen->get_clip(cx1,cy1,cx2,cy2);   
64  while (tot--)
65  {
66    xx=*(p++)+x;
67    if (xx<cx1 || xx>cx2)
68      p+=2;
69    else
70    {
71      yy=*(p++)+y;
72      if (yy<cy1 || yy>cy2)
73        p++;
74      else
75        *(screen->scan_line(yy)+xx)=*(p++);
76    }
77  }     
78}
79
80void patched_morph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
81{
82  jmorph::show_8(screen,x,y,frame_on,fli,pal);
83  int tot=pats[frame_on].patches,xx,yy;
84  unsigned char *p=pats[frame_on].patch_data;
85  short cx1,cy1,cx2,cy2;
86  screen->get_clip(cx1,cy1,cx2,cy2);   
87  while (tot--)
88  {
89    xx=*(p++)+x;
90    if (xx<cx1 || xx>cx2)
91      p+=2;
92    else
93    {
94      yy=*(p++)+y;
95      if (yy<cy1 || yy>cy2)
96        p++;
97      else
98        *(screen->scan_line(yy)+xx)=*(p++);
99    }
100  }     
101}
102
103
104
105
106patched_morph::patched_morph(image *i1, image *hint1, image *i2, image *hint2, int aneal_steps,
107                color_filter *fli, palette *pal, int frames) : jmorph(i1,hint1,i2,hint2,aneal_steps)
108{
109  int i,j,w,h,x,y,tot,r,g,b,mark_color,dist;
110  unsigned char *cur_patch,*sl,ored,og,ob;
111 
112  frames=9;
113 
114  patches=frames; 
115  pats=(morph_patch *)jmalloc(sizeof(morph_patch)*patches,"morph::patch array");
116  w=max(bound_x2(0),bound_x2(1));
117  h=max(bound_y2(0),bound_y2(1));   
118  image *im=new image(w,h);
119
120
121  for (i=0;i<patches;i++)
122  {
123    pats[i].patch_data=NULL;
124    pats[i].patches=0;   
125    if (i!=0 && i!=patches-1)
126    {     
127      im->clear();
128      jmorph::show_step_frame(im,0,0,i,fli,pal);
129      for (j=0;j<4;j++)
130      {     
131        for (y=0;y<h;y++)
132          for (sl=im->scan_line(y),x=0;x<w;x++,sl++)
133          {     
134            mark_color=-1;
135           
136            tot=r=g=b=0;                 
137            if (x!=0 && *(sl-1))
138            { tot++;
139              r+=pal->red(*(sl-1));
140              g+=pal->green(*(sl-1));
141              b+=pal->blue(*(sl-1));               
142            }     
143            if (x!=w-1 && *(sl+1))
144            { tot++;
145              r+=pal->red(*(sl+1));
146              g+=pal->green(*(sl+1));
147              b+=pal->blue(*(sl+1));   
148            }     
149            if (y!=0 && im->pixel(x,y-1))
150            { tot++;
151              r+=pal->red(im->pixel(x,y-1));
152              g+=pal->green(im->pixel(x,y-1));
153              b+=pal->blue(im->pixel(x,y-1));
154            }
155            if (y!=h-1 && im->pixel(x,y+1))
156            { tot++;
157              r+=pal->red(im->pixel(x,y+1));
158              g+=pal->green(im->pixel(x,y+1));
159              b+=pal->blue(im->pixel(x,y+1));
160            }
161
162            if (*sl && tot==0)  // kill any separate pixels         
163              mark_color=0;
164            else if (*sl)
165            {
166              pal->get(*sl,ored,og,ob);       // see if we need to blur this on in
167              r/=tot;
168              g/=tot;
169              b/=tot;
170             
171              dist=((int)ored-r)*((int)ored-r)+((int)og-g)*((int)og-g)+((int)ob-b)*((int)ob-b);
172              if (i>0 && i<patches-1 && dist>3000)
173              {
174//              printf("adding blur at %d %d to frame %d, dist=%d\n",x,y,i,dist);
175                mark_color=fli->lookup_color(r>>3,g>>3,b>>3);       
176              }
177            }
178            else if (*sl==0 && tot>=3)     
179              mark_color=fli->lookup_color((r/tot)>>3,(g/tot)>>3,(b/tot)>>3);       
180            if (mark_color>=0)
181            {         
182              pats[i].patches++;
183              pats[i].patch_data=(unsigned char *)realloc(pats[i].patch_data,3*pats[i].patches);
184              cur_patch=pats[i].patch_data+  (pats[i].patches-1)*3;         
185              *(cur_patch++)=x;
186              *(cur_patch++)=y;
187              *sl=mark_color;         
188              *(cur_patch++)=*sl;             
189            }     
190          }
191      }     
192    }
193  } 
194  delete im;
195 
196}
197
198
199void jmorph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
200{
201  int pixelx,pixely,i;
202  short cx1,cy1,cx2,cy2;
203  unsigned char r,g,b;
204  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
205  screen->get_clip(cx1,cy1,cx2,cy2);
206
207  if (small)
208  {
209    morph_point8 *p_on=(morph_point8 *)p;
210    for (i=0;i<total;i++,p_on++)
211    {
212      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
213      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
214      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
215      {
216        scolor=addr+((int)p_on->start_color)*3;
217        ecolor=addr+((int)p_on->end_color)*3;
218        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
219        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
220        b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
221        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
222      }
223    }
224  }
225  else
226  {
227    morph_point16 *p_on=(morph_point16 *)p;
228    for (i=0;i<total;i++,p_on++)
229    {
230      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
231      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
232      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
233      {
234        scolor=addr+((int)p_on->start_color)*3;
235        ecolor=addr+((int)p_on->end_color)*3;
236        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
237        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
238        b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
239        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
240      }
241    }
242  }
243
244
245
246void jmorph::add_filler(int frames)
247{
248  int w=max(bound_x2(0),bound_x2(1)),h=max(bound_y2(0),bound_y2(1)),
249      i,pixelx,pixely,k,l,frame_on; 
250  morph_point8 **middle_map,*other;
251  unsigned char *end_map;
252  CONDITION(small,"add filler not defined for 16bit morphs\n");
253 
254  if (frames<3) return ;
255 
256
257  middle_map=(morph_point8 **)jmalloc(w*h*sizeof(morph_point8 *),
258                                      "morph::middle_map");  // create an image of pointers
259  end_map=(unsigned char *)jmalloc(w*h,
260                                  "morph::end_map");      // maps all the ending pixels
261
262  for (frame_on=2;frame_on<frames-1;frame_on++)
263  {   
264    memset(middle_map,0,w*h*sizeof(morph_point8 *));            // initialize them middle pointers NULL
265    memset(end_map,0,w*h);                                      // clear all end pixels
266 
267    morph_point8 *p_on=(morph_point8 *)p;    // p is the array of morph points
268    for (i=0;i<total;i++,p_on++)           
269    {   
270      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long) frame_on  /(long) frames  +p_on->x1;
271      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long) frame_on  /(long) frames  +p_on->y1;
272
273      middle_map[pixelx+pixely*w]=p_on;      // map this poisiton back to the morph point
274      end_map[p_on->x2+p_on->y2*w]=p_on->end_color;        // note an ending map here
275    }
276
277 
278    int skipped=0;
279   
280    for (pixely=0;pixely<h;pixely++)
281    {
282      for (pixelx=0;pixelx<w;pixelx++)
283      {
284        if (middle_map[pixelx+pixely*w]==NULL)  // we are checking for 'duds'  (misplaced black pixels)
285        {       
286          int tot;     
287          if (pixelx>0) if (middle_map[pixelx-1+pixely*w]) tot=1; else tot=0;     
288          if (pixelx<w-1) if (middle_map[pixelx+1+pixely*w]) tot++;     
289          if (pixely>0) if (middle_map[pixelx+(pixely-1)*w]) tot++;     
290          if (pixely<h-1) if (middle_map[pixelx+(pixely+1)*w]) tot++;   
291
292          if (tot>=3)                   // it is surronded by 3 non black squares, this is a dud       
293          {
294            int distance,shortest_distance,shortest_end_x,shortest_end_y;         
295            morph_point8 *shortest=NULL;
296           
297            for (k=0;k<w;k++)
298              for (l=0;l<h;l++)
299              {             
300                other=middle_map[k+(l)*w];
301                if (other)
302                {
303                  int end_x=frames*(pixelx-other->x1)/frame_on+other->x1,
304                      end_y=frames*(pixely-other->y1)/frame_on+other->y1;                 
305                  if (end_x>=0 && end_y>=0 && end_x<w && end_y<h && end_map[end_x+end_y*w])
306                  {
307                    distance=(other->x1-end_x)*(other->x1-end_x)+
308                             (other->y1-end_y)*(other->y1-end_y);
309                    if (!shortest || shortest_distance>distance)
310                    {
311                      shortest_distance=distance;
312                      shortest=other;
313                      shortest_end_x=end_x;
314                      shortest_end_y=end_y;                   
315                    }
316                  }
317                }
318              }     
319            if (shortest)
320            {
321              total++;
322              p=(void *)realloc(p,sizeof(morph_point8)*total);           
323              morph_point8 *mod=((morph_point8 *)p)+total-1;
324              mod->x1=shortest->x1;
325              mod->y1=shortest->y1;
326              mod->start_color=shortest->start_color;             
327
328              mod->x2=shortest_end_x;
329              mod->y2=shortest_end_y;             
330              mod->end_color=end_map[shortest_end_x+shortest_end_y*w];           
331            }           
332            else
333            {         
334              skipped++;
335              printf("skiped so far : %d (frame %d)\n",skipped,frame_on);
336            }
337           
338
339          }     
340        }
341      }
342    } 
343  }
344 
345  jfree(middle_map);
346  jfree(end_map);
347 
348}
349
350
351
352jmorph::jmorph(spec_entry *e, bFILE *fp)
353{
354  int i;
355  fp->seek(e->offset,0);
356  fp->read(&total,4); 
357  total=long_to_local(total);
358  if (e->type==SPEC_MORPH_POINTS_8 || e->type==SPEC_PATCHED_MORPH)
359  {
360    p=(void *)jmalloc(sizeof(morph_point8)*total,"morph8::point array");
361    fp->read(p,sizeof(morph_point8)*total);
362    small=1;
363  }
364  else
365  {
366    p=(void *)jmalloc(sizeof(morph_point16)*total,"morph16::point array");
367
368    for (i=0;i<total;i++)
369    {
370      ((morph_point16 *)p+i)->x1=fp->read_uint16();
371      ((morph_point16 *)p+i)->y1=fp->read_uint16();
372      ((morph_point16 *)p+i)->x2=fp->read_uint16();
373      ((morph_point16 *)p+i)->y2=fp->read_uint16();
374      fp->read( &((morph_point16 *)p+i)->start_color,1);
375      fp->read( &((morph_point16 *)p+i)->end_color,1);
376    }
377
378    small=0;
379  }
380  w[0]=fp->read_uint16();
381  h[0]=fp->read_uint16(); 
382  w[1]=fp->read_uint16();
383  h[1]=fp->read_uint16();
384}
385
386void jmorph::show_frame(image *screen, int x, int y,
387                      int frames, int frame_on, color_filter *fli, palette *pal)
388{
389  int pixelx,pixely,i;
390  short cx1,cy1,cx2,cy2;
391  unsigned char r,g,b;
392  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
393  screen->get_clip(cx1,cy1,cx2,cy2);
394
395  if (small)
396  {
397    morph_point8 *p_on=(morph_point8 *)p;
398    for (i=0;i<total;i++,p_on++)
399    {
400      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
401      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
402      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
403      {
404        scolor=addr+((int)p_on->start_color)*3;
405        ecolor=addr+((int)p_on->end_color)*3;
406        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
407        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
408        b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
409        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
410      }
411    }
412  }
413  else
414  {
415    morph_point16 *p_on=(morph_point16 *)p;
416    for (i=0;i<total;i++,p_on++)
417    {
418      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
419      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
420      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
421      {
422        scolor=addr+((int)p_on->start_color)*3;
423        ecolor=addr+((int)p_on->end_color)*3;
424        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
425        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
426        b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
427        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
428      }
429    }
430  }
431
432
433void jmorph::show_24frame(unsigned char *screen, int width, int height,
434                  int x, int y, int frames, int frame_on, palette *pal)
435{
436    int pixelx,pixely,i;
437  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr(),*pix;
438 
439  if (small)
440  {
441    morph_point8 *p_on=(morph_point8 *)p;
442    for (i=0;i<total;i++,p_on++)
443    {
444      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
445      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
446
447      if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
448      {
449        scolor=addr+((int)p_on->start_color)*3;
450        ecolor=addr+((int)p_on->end_color)*3;
451        pix=screen+pixelx*3+pixely*3*width;               
452        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;     
453        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;     
454        *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
455      }
456    }
457  }
458  else
459  {
460    morph_point16 *p_on=(morph_point16 *)p;
461    for (i=0;i<total;i++,p_on++)
462    {
463      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
464      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
465
466      if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
467      {
468        scolor=addr+((int)p_on->start_color)*3;
469        ecolor=addr+((int)p_on->end_color)*3;
470        pix=screen+pixelx*3+pixely*3*width;               
471        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;     
472        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;     
473        *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
474      }
475    }
476  }
477}
478
479
480jmorph::jmorph(image *i1, image *hint1, image *i2, image *hint2,
481                          int aneal_steps)
482{
483  w[0]=i1->width();
484  h[0]=i1->height(); 
485  w[1]=i2->width();
486  h[1]=i2->height(); 
487
488  struct { int start,end; } crange[256];
489  int hint_hist1[256],hint_hist2[256],x,y,total_hints=0,randp,cur_pix,
490      last=0,first=0,i,j,k,findx1,findy1,findx2,findy2,total1,total2,points;
491  unsigned char *sl,color;
492  void *plist;
493
494
495  CONDITION(i1->width()==hint1->width() && i1->height()==hint1->height() &&
496            i2->width()==hint2->width() && i2->height()==hint2->height(),
497            "Image sizes do not correspond with hint sizes");
498  if (i1->width()>255 || i2->width()>255 || i1->height()>255 || i2->height()>255)
499    small=0;
500  else small=1;
501
502  memset(hint_hist1,0,sizeof(hint_hist1));
503  memset(hint_hist2,0,sizeof(hint_hist2));
504  total=0;
505
506  // first found out how many hints we have to follow
507  for (y=0;y<hint1->height();y++)
508  { sl=hint1->scan_line(y);
509    for (x=hint1->width();x;x--,sl++)
510      if (*sl) hint_hist1[*sl]++;
511  }
512  for (y=0;y<hint2->height();y++)
513  { sl=hint2->scan_line(y);
514    for (x=hint2->width();x;x--,sl++)
515      if (*sl) hint_hist2[*sl]++;
516  }
517
518  // check the user and see if the mask match up
519  for (x=0;x<256;x++)
520  {
521    if ((hint_hist1[x]!=0 && hint_hist2[x]==0) ||
522        (hint_hist1[x]==0 && hint_hist2[x]!=0))
523    { printf("Color %d used for hinting is prent in one hint mask, but not the other\n",x);
524      exit(1);
525    } else if (hint_hist1[x])
526    {
527      if (!first) first=x;
528      total_hints++;
529      if (hint_hist1[x]>hint_hist2[x])
530        y=hint_hist1[x];
531      else
532        y=hint_hist2[x];
533      total+=y;
534      crange[x].start=last;
535      crange[x].end=last+y-1;
536      last+=y;
537    }
538  }
539  if (small)
540    plist=(void *)jmalloc(sizeof(morph_point8)*total,"morph8::point array");
541  else
542    plist=(void *)jmalloc(sizeof(morph_point16)*total,"morph16::point array");
543  CHECK(plist);
544  for (i=0,color=0;i<total_hints;i++)
545  {
546    color++; while (!hint_hist1[color]) color++;
547    findx1=findx2=-1; findy1=findy2=0;
548    total1=hint_hist1[color];
549    total2=hint_hist2[color];
550    if (total1>total2) points=total1; else points=total2;
551    for (j=0;j<points;j++)
552    {
553      if (total1)  // are there any more pixels left in this image?
554      { total1--;
555        do {
556          findx1++;
557          if (findx1>=hint1->width()) { findx1=0; findy1++; }
558        } while (hint1->pixel(findx1,findy1)!=color);
559      }
560      else
561      {
562        randp=rand()%j+crange[color].start;
563        if (small)
564        { findx1=((morph_point8 *)plist)[randp].x1;
565          findy1=((morph_point8 *)plist)[randp].y1;
566        } else
567        { findx1=((morph_point16 *)plist)[randp].x1;
568          findy1=((morph_point16 *)plist)[randp].y1;
569        }
570      }
571      if (total2)  // are there any more pixels left in this image?
572      {
573        total2--;
574        do {
575          findx2++;
576          if (findx2>=hint2->width()) { findx2=0; findy2++; }
577        } while (hint2->pixel(findx2,findy2)!=color);
578      }
579      else
580      {
581        randp=rand()%j+crange[color].start;
582        if (small)
583        { findx2=((morph_point8 *)plist)[randp].x2;
584          findy2=((morph_point8 *)plist)[randp].y2;
585        } else
586        { findx2=((morph_point16 *)plist)[randp].x2;
587          findy2=((morph_point16 *)plist)[randp].y2;
588        }
589      }
590      cur_pix=j+crange[color].start;
591      CHECK(cur_pix<total);
592
593      if (small)
594      {
595        ((morph_point8 *)plist)[cur_pix].x1=findx1; 
596        ((morph_point8 *)plist)[cur_pix].x2=findx2; 
597        ((morph_point8 *)plist)[cur_pix].y1=findy1; 
598        ((morph_point8 *)plist)[cur_pix].y2=findy2; 
599        ((morph_point8 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
600        ((morph_point8 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
601      }
602      else
603      {
604        ((morph_point16 *)plist)[cur_pix].x1=findx1; 
605        ((morph_point16 *)plist)[cur_pix].x2=findx2; 
606        ((morph_point16 *)plist)[cur_pix].y1=findy1; 
607        ((morph_point16 *)plist)[cur_pix].y2=findy2; 
608        ((morph_point16 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
609        ((morph_point16 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
610      }
611    }
612  }
613  int swap_point,distance,new_distance,hint_color,first_point,range,start;
614
615  int sx2,sy2,sec;
616  for (i=0;i<aneal_steps;i++)
617  {
618    for (j=0,first_point=0;j<total_hints;j++)
619    {
620      if (small)
621        hint_color=hint1->pixel(((morph_point8 *)plist)[first_point].x1,((morph_point8 *)plist)[first_point].y1);
622      else
623        hint_color=hint1->pixel(((morph_point16 *)plist)[first_point].x1,((morph_point16 *)plist)[first_point].y1);
624      start=crange[hint_color].start;
625      range=crange[hint_color].end-start+1;
626      for(k=crange[hint_color].start;k<=crange[hint_color].end;k++)
627      {
628        swap_point=rand()%range+start;
629        if (small)
630        {
631          morph_point8 *pk,*ps;
632          pk=(morph_point8 *)plist+k;
633          ps=(morph_point8 *)plist+swap_point;
634
635          distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
636                   (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
637          new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
638                       (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
639          if (new_distance<distance)
640          {
641            sx2=pk->x2;         sy2=pk->y2;
642            sec=pk->end_color;
643            pk->x2=ps->x2;      pk->y2=ps->y2;
644            pk->end_color=ps->end_color;
645            ps->x2=sx2;         ps->y2=sy2;
646            ps->end_color=sec;
647          }
648        } else
649        {
650          morph_point16 *pk,*ps;
651          pk=(morph_point16 *)plist+k;
652          ps=(morph_point16 *)plist+swap_point;
653
654          distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
655                   (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
656          new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
657                       (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
658          if (new_distance<distance)
659          {
660            sx2=pk->x2;         sy2=pk->y2;
661            sec=pk->end_color;
662            pk->x2=ps->x2;      pk->y2=ps->y2;
663            pk->end_color=ps->end_color;
664            ps->x2=sx2;         ps->y2=sy2;
665            ps->end_color=sec;
666          }
667        }
668      }
669      first_point=crange[hint_color].end+1;
670    }
671  }
672  p=plist;
673}
674
675int morph_width;
676
677int morph8_compare(const void *p1, const void *p2)
678{
679  int pos1=((morph_point8 *)p1)->x1+((morph_point8 *)p1)->y1*morph_width; 
680  int pos2=((morph_point8 *)p2)->x1+((morph_point8 *)p2)->y1*morph_width; 
681  if (pos1<pos2) return -1;
682  else if (pos1==pos2) return 0;
683  else return 1;
684 
685}
686
687
688int jmorph::write(bFILE *fp)
689{
690  int i;
691
692 
693  fp->write_uint32(total); 
694  if (small)
695  {
696
697    // if the points are put in order then they can be compressed easier
698    morph_width=max(bound_x2(0),bound_x2(1));      // global used by qsort compare routine
699    qsort(p,total,sizeof(morph_point8),morph8_compare); 
700   
701    fp->write(p,sizeof(morph_point8)*total);
702  } 
703  else
704  {
705    for (i=0;i<total;i++)
706    { fp->write_uint16(((morph_point16 *)p+i)->x1);
707      fp->write_uint16(((morph_point16 *)p+i)->y1);
708      fp->write_uint16(((morph_point16 *)p+i)->x2);
709      fp->write_uint16(((morph_point16 *)p+i)->y2);
710      fp->write( &((morph_point16 *)p+i)->start_color,1);
711      fp->write( &((morph_point16 *)p+i)->end_color,1);
712    }
713  }
714  fp->write_uint16(w[0]);
715  fp->write_uint16(h[0]);
716  fp->write_uint16(w[1]);
717  fp->write_uint16(h[1]);
718  return 1;
719}
720
721
722
723
724step_morph::step_morph(patched_morph *mor, palette *pal, int frame_direction, int face_direction)
725{
726  int i;
727  pm=mor;
728 
729  total=mor->total_points();     
730  points=(step_struct *)jmalloc(sizeof(step_struct)*total,"step_morph::points"); 
731 
732  dir=frame_direction;
733  face_dir=face_direction;
734 
735  if (dir>0)
736    frame_on=0;
737  else
738    frame_on=mor->patches-1;
739 
740  if (mor->small_morph())
741  {   
742      int x1,y1,x2,y2;
743
744   
745      if (frame_direction>0)
746      {     
747        morph_point8 *m8=mor->small_points();     
748       
749        for (i=0;i<total;i++,m8++)
750        {       
751          x1=(int)m8->x1;
752          x2=(int)m8->x2;
753
754          y1=(int)m8->y1;
755          y2=(int)m8->y2;
756
757          points[i].x=x1<<8;
758          points[i].y=y1<<8;       
759          points[i].dx=(x2-x1)<<5;
760          points[i].dy=(y2-y1)<<5;             
761         
762          unsigned char r1,g1,b1,r2,g2,b2;
763          pal->get(m8->start_color,r1,g1,b1);
764          pal->get(m8->end_color,r2,g2,b2);
765          points[i].r=r1<<8;
766          points[i].g=g1<<8;
767          points[i].b=b1<<8;
768
769          points[i].dr=(long)((int)r2-(int)r1)<<5;
770          points[i].dg=(long)((int)g2-(int)g1)<<5;
771          points[i].db=(long)((int)b2-(int)b1)<<5;                     
772        }
773      }   
774      else
775      {     
776        morph_point8 *m8=mor->small_points();     
777        for (i=0;i<total;i++,m8++)
778        {       
779          x1=(int)m8->x1;
780          x2=(int)m8->x2;
781
782          y1=(int)m8->y1;
783          y2=(int)m8->y2;
784
785          points[i].x=x2<<8;
786          points[i].y=y2<<8;       
787          points[i].dx=(x1-x2)<<5;
788          points[i].dy=(y1-y2)<<5;             
789
790          unsigned char r1,g1,b1,r2,g2,b2;
791          pal->get(m8->start_color,r2,g2,b2);
792          pal->get(m8->end_color,r1,g1,b1);
793          points[i].r=r1<<8;
794          points[i].g=g1<<8;
795          points[i].b=b1<<8;
796
797          points[i].dr=(long)((int)r2-(int)r1)<<5;
798          points[i].dg=(long)((int)g2-(int)g1)<<5;
799          points[i].db=(long)((int)b2-(int)b1)<<5;                     
800        }
801      }   
802  } 
803
804
805}
806
807void step_morph::show_frame(image *screen, int x, int y,  color_filter *fli)
808{
809  short x1,y1,x2,y2;
810  screen->get_clip(x1,y1,x2,y2);
811
812  int i,px,py,ww=max(pm->bound_x2(0),pm->bound_x2(1))-1;
813  step_struct *ss;
814
815  morph_patch *pat=pm->pats+frame_on; 
816  int j,tp=pat->patches;
817  unsigned char *sl=pat->patch_data;   
818
819  if (face_dir>0)
820  {   
821    for (i=0,ss=points;i<total;i++,ss++)
822    {
823      px=x+(ss->x>>(16-8));
824      py=y+(ss->y>>(16-8));
825      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
826        *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
827
828      ss->x+=ss->dx;
829      ss->y+=ss->dy;
830      ss->r+=ss->dr;
831      ss->g+=ss->dg;
832      ss->b+=ss->db;       
833    } 
834
835    for (j=0;j<tp;j++,sl++)
836    {
837      px=x+*(sl++);
838      py=y+*(sl++);
839      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
840        *(screen->scan_line(py)+px)=*sl;
841    }             
842  } else
843  {
844    for (i=0,ss=points;i<total;i++,ss++)
845    {
846      px=x+ww-(ss->x>>(16-8));
847      py=y+(ss->y>>(16-8));
848      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
849        *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
850
851      ss->x+=ss->dx;
852      ss->y+=ss->dy;
853      ss->r+=ss->dr;
854      ss->g+=ss->dg;
855      ss->b+=ss->db;       
856    } 
857
858    for (j=0;j<tp;j++,sl++)
859    {
860      px=x+(ww-(int)(*(sl++)));
861      py=y+*(sl++);
862      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
863        *(screen->scan_line(py)+px)=*sl;
864    }         
865  }
866 
867  frame_on+=dir;
868 
869}
870
871void step_morph::reverse_direction()
872{
873  step_struct *s=points;
874  int i;
875  for (i=0;i<total;i++,s++)
876  {
877    s->dx=-s->dx;
878    s->dy=-s->dy;
879    s->dr=-s->dr;
880    s->dg=-s->dg;
881    s->db=-s->db;   
882  }
883  dir=-dir;
884 
885}
886
887
888patched_morph::patched_morph(spec_entry *e, bFILE *fp) : jmorph(e,fp)
889{
890  int i;
891 
892  patches=fp->read_uint16();
893  pats=(morph_patch *)jmalloc(sizeof(morph_patch)*patches,"patched_morph::points");
894 
895  for (i=0;i<patches;i++)
896  {
897    pats[i].patches=fp->read_uint16();
898    if (pats[i].patches)
899    {     
900      pats[i].patch_data=(unsigned char *)jmalloc(3*pats[i].patches,"patched_morph::patch_data");
901      fp->read(pats[i].patch_data,3*pats[i].patches);     
902    }
903    else
904      pats[i].patch_data=NULL;
905  }   
906}
907
908
Note: See TracBrowser for help on using the repository browser.