123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- #include "supmorph.hpp"
- #include "specs.hpp"
- #include "timage.hpp"
- #include "timing.hpp"
- #include "filter.hpp"
- #include "video.hpp"
- #include "jrand.hpp"
- #define p_swap(x,y) { x^=y; y^=x; x^=y; }
- #define p_dist(x1,y1,x2,y2) (((int)(x1)-(int)x2)*((int)(x1)-(int)x2)+ \
- ((int)(y1)-(int)y2)*((int)(y1)-(int)y2))
- super_morph::super_morph(trans_image *hint1, trans_image *hint2,
- int aneal_steps, void (*stat_fun)(int))
- {
- int x,y,w1=hint1->width(),
- h1=hint1->height(),
- w2=hint2->width(),
- h2=hint2->height();
- if (w1>w2) w=w1; else w=w2;
- if (h1>h2) h=h1; else h=h2;
- unsigned char *dp;
- /************************ count up the number of hints ****************************/
- unsigned short hints1[256],hints2[256];
- memset(hints1,0,256*2);
- memset(hints2,0,256*2);
- dp=hint1->t_data();
- for (y=0;y<h1;y++)
- {
- x=0;
- while (x<w1)
- {
- x+=*dp; // skip over space
- dp++;
- if (x<w1)
- {
- int rl=*(dp++);
- while (rl--) { hints1[*(dp++)]++; x++; }
- }
- }
- }
- // hint2 image2
- dp=hint2->t_data();
- for (y=0;y<h2;y++)
- {
- x=0;
- while (x<w2)
- {
- x+=*dp; // skip over space
- dp++;
- if (x<w2)
- {
- int rl=*(dp++);
- while (rl--) { hints2[*(dp++)]++; x++; }
- }
- }
- }
- /****************** now sum up hints and alloc memory for movers *************/
- unsigned short start1[256],start2[256],
- totals[256],
- start=0,*h1p=hints1,*h2p=hints2;
- unsigned char hint_color[256],total_hints=0;
- for (y=0;y<256;y++,h1p++,h2p++)
- if (*h1p)
- {
- if (*h2p==0)
- {
- t=0;
- return ;
- }
- start1[y]=start2[y]=start; // specify start of hint range
- if (*h1p>*h2p)
- totals[y]=*h1p;
- else totals[y]=*h2p;
- start+=totals[y];
- hint_color[total_hints++]=y;
- }
- t=start;
- movers=(unsigned char *)jmalloc(t*4,"morph movers");
-
-
- /**************** Now scan the images again setup hints *********************/
- dp=hint1->t_data();
- for (y=0;y<h1;y++)
- {
- x=0;
- while (x<w1)
- {
- x+=*dp; // skip over space
- dp++;
- if (x<w1)
- {
- int rl=*(dp++);
- while (rl--)
- {
- int maddr=(start1[*(dp++)]++)*4;
- movers[(maddr++)]=x;
- movers[maddr]=y;
- x++;
- }
- }
- }
- }
- dp=hint2->t_data();
- for (y=0;y<h2;y++)
- {
- x=0;
- while (x<w2)
- {
- x+=*dp; // skip over space
- dp++;
- if (x<w2)
- {
- int rl=*(dp++);
- while (rl--)
- {
- int maddr=(start2[*(dp++)]++)*4+2;
- movers[(maddr++)]=x;
- movers[maddr]=y;
- x++;
- }
- }
- }
- }
- /********* if hint sizes don't match duplicate the smaller until sizes are equal **********/
- for (start=0,x=0;x<total_hints;x++)
- {
- y=hint_color[x];
- int dups;
- for (dp=movers+start1[y]*4,dups=totals[y]-hints1[y];dups;dups--)
- {
- *dp=*(dp-4); dp++; // copy previous x,y position
- *dp=*(dp-4); dp++;
- dp+=2;
- }
- start1[y]-=2*totals[y]-hints1[y]; // set the start back to the begining of hint range
- }
- for (start=0,x=0;x<total_hints;x++)
- {
- y=hint_color[x];
- int dups;
- for (dp=movers+start2[y]*4+2,dups=totals[y]-hints2[y];dups;dups--)
- {
- *dp=*(dp-4); dp++; // copy previous x,y position
- *dp=*(dp-4); dp++;
- dp+=2;
- }
- start2[y]-=hints2[y]; // set the start back to the begining of hint range
- }
- /******* Now apply simulated annealing to solve for a smaller total distance ********/
- int rand_on=0;
- for (y=0;y<aneal_steps;y++)
- {
- if (stat_fun)
- stat_fun(y);
- dp=movers;
- for (x=0;x<total_hints;x++)
- {
- int hc=hint_color[x];
- int a,z=totals[hc];
- unsigned char *range_start=dp;
- for (a=0;a<z;a++,dp+=4)
- {
- unsigned char *swap=range_start+(rtable[((rand_on++)&(RAND_TABLE_SIZE-1))]%z)*4;
- int d_old=p_dist(dp[0],dp[1],dp[2],dp[3])+p_dist(swap[0],swap[1],swap[2],swap[3]);
- int d_new=p_dist(dp[0],dp[1],swap[2],swap[3])+p_dist(swap[0],swap[1],dp[2],dp[3]);
- if (d_new<d_old)
- {
- unsigned char s;
- s=swap[2]; swap[2]=dp[2]; dp[2]=s;
- s=swap[3]; swap[3]=dp[3]; dp[3]=s;
- }
- }
- }
- }
- }
- smorph_player::smorph_player(super_morph *m, palette *pal, image *i1, image *i2, int frames, int dir)
- {
- int i,x1,y1,x2,y2;
- unsigned char *d=m->movers,*paddr=(unsigned char *)pal->addr(),*pa;
- stepper *p;
- p=steps=(stepper *)jmalloc(sizeof(stepper)*m->t,"smorph steps");
- f_left=frames;
- frames--;
- t=m->t;
- w=m->w; h=m->h;
- for (i=0;i<t;i++,p++)
- {
- x1=*(d++);
- y1=*(d++);
- x2=*(d++);
- y2=*(d++);
-
- unsigned char r1,g1,b1,r2,g2,b2;
- pa=paddr+(int)(*(i1->scan_line(y1)+x1))*3;
- r1=*(pa++);
- g1=*(pa++);
- b1=*(pa++);
-
- pa=paddr+(int)(*(i2->scan_line(y2)+x2))*3;
- r2=*(pa++);
- g2=*(pa++);
- b2=*(pa++);
- p->r=r1<<16;
- p->g=g1<<16;
- p->b=b1<<16;
- p->dr=(long)(((int)r2-(int)r1)<<16)/frames;
- p->dg=(long)(((int)g2-(int)g1)<<16)/frames;
- p->db=(long)(((int)b2-(int)b1)<<16)/frames;
- if (dir<0)
- {
- x1=w-x1-1;
- x2=w-x2-1;
- }
- p->dx=((x2-x1)<<16)/frames;
- p->dy=((y2-y1)<<16)/frames;
- p->x=x1<<16;
- p->y=y1<<16;
- }
- hole=(unsigned char *)jmalloc(w*h,"hole image");
- }
- int smorph_player::show(image *screen, int x, int y, color_filter *fil, palette *pal,
- int blur_threshold)
- {
- if (f_left)
- {
- int i,px,py,ix,iy;
- short x1,y1,x2,y2;
- screen->get_clip(x1,y1,x2,y2);
- screen->add_dirty(x,y,x+w-1,y+h-1);
- stepper *ss;
- memset(hole,0,w*h);
- unsigned char *paddr=(unsigned char *)pal->addr();
- for (ss=steps,i=0;i<t;i++,ss++)
- {
- ix=(ss->x>>(16));
- iy=(ss->y>>(16));
- px=ix+x;
- py=iy+y;
- if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
- {
- hole[ix+iy*w]=*(screen->scan_line(py)+px)=fil->lookup_color(ss->r>>(19),
- ss->g>>(19),
- ss->b>>(19));
- }
- ss->x+=ss->dx;
- ss->y+=ss->dy;
- ss->r+=ss->dr;
- ss->g+=ss->dg;
- ss->b+=ss->db;
- }
- f_left--;
- if (!f_left) // skip hole fills and smoothing on last frame
- return 1;
- unsigned char *ll=hole+1,*tl=hole+w+1,*nl=hole+w*2+1;
- for (iy=1;iy<h-1;iy++) // now scan the for holes to fill
- {
- for (ix=1;ix<w-1;ix++,ll++,tl++,nl++)
- {
- if (x+ix>=x1 && x+ix<=x2 && y+iy>=y1 && y+iy<=y2)
- {
- int t=0;
- unsigned char *pa;
- int r=0,g=0,b=0;
- /* if (*(tl-1)) t++;
- if (*(tl+1)) t++;
- if (*ll) t++;
- if (*nl) t++;*/
- if (*(tl-1)) { t++; pa=paddr+(*(tl-1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
- if (*(tl+1)) { t++; pa=paddr+(*(tl+1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
- if (*(ll)) { t++; pa=paddr+(*ll)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
- if (*(nl)) { t++; pa=paddr+(*nl)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
- if (*tl)
- {
- if (t)
- {
- pa=paddr+(*tl)*3;
- r/=t; g/=t; b/=t;
- int dist=((int)(*pa)-r)*((int)(*pa)-r); pa++;
- dist+=((int)(*pa)-g)*((int)(*pa)-g); pa++;
- dist+=((int)(*pa)-b)*((int)(*pa)-b);
- if (dist>blur_threshold)
- *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color(r>>3,g>>3,b>>3);
- } else *(tl)=*(screen->scan_line(y+iy)+x+ix)=0; // kill single pixels
- }
- else if (t>=3)
- *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color((r/t)>>3,(g/t)>>3,(b/t)>>3);
- }
- }
- ll+=2;
- tl+=2;
- nl+=2;
- }
- return 1;
- } else return 0;
- }
- /*void free_up_memory() { printf("you're screwed\n"); }
- main(int argc, char **argv)
- {
- image_init();
- jrand_init();
- FILE *fp=fopen("art/mrphmask.spe","rb");
- spec_directory sd(fp);
- image *h1=new image(sd.find("20 h"),fp),
- *h2=new image(sd.find("1h"),fp),
- *i1=new image(sd.find("20"),fp),
- *i2=new image(sd.find("1"),fp);
- palette *pal=new palette(sd.find(SPEC_PALETTE),fp);
- color_filter *fil=new color_filter(sd.find(SPEC_COLOR_TABLE),fp);
- int steps=atoi(argv[1]);
- if (steps<2) steps=50;
- trans_image *hh1=new trans_image(h1,"hint1"),*hh2=new trans_image(h2,"hint2");
- time_marker time1;
- super_morph sm(hh1,hh2,steps);
- int frames=atoi(argv[2]);
- if (frames<2) frames=16;
- smorph_player sp(&sm,pal,i1,i2,frames,-1);
- time_marker time2;
- printf("time = %lf\n",time2.diff_time(&time1));
- set_mode(19,argc,argv);
- pal->load();
- i1->put_image(screen,30,30);
- update_dirty(screen);
- sleep(2);
- while (sp.show(screen,30,30,fil,pal))
- { update_dirty(screen);
- screen->bar(30,30,30+sp.w,30+sp.h,0);
- }
- sleep(2);
- close_graphics();
- }*/
|