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