326 lines
6.8 KiB
C
326 lines
6.8 KiB
C
#include <stdio.h>
|
|
#include <bios.h>
|
|
#include <malloc.h>
|
|
#include <memory.h>
|
|
|
|
int colsreserved=1;
|
|
|
|
int setback255=0;
|
|
int filetype; /* 1=LBM */
|
|
int backcol=255;
|
|
|
|
unsigned char far *vram=(char far *)0xa0000000;
|
|
union REGS reg;
|
|
unsigned char far pic[64000];
|
|
unsigned char far pic1[64000];
|
|
unsigned char far pic2[64000];
|
|
unsigned char far bigpal[8192*3];
|
|
unsigned char far bigpalhsv[8192*3];
|
|
unsigned int bigcnt[8192];
|
|
unsigned int bigcntbak[8192];
|
|
int bigpalpnt,bigpalnum;
|
|
unsigned char palmap[256];
|
|
unsigned char far pal1[768];
|
|
unsigned char far pal2[768];
|
|
unsigned char far palhsv[768];
|
|
unsigned char far tmphsv[768];
|
|
unsigned char far pal[768];
|
|
unsigned char far defpal[16*3]={
|
|
00,00,00,
|
|
00,00,40,
|
|
00,40,00,
|
|
00,40,40,
|
|
40,00,00,
|
|
40,00,40,
|
|
40,20,00,
|
|
40,40,40,
|
|
20,20,20,
|
|
20,20,60,
|
|
20,60,20,
|
|
20,60,60,
|
|
60,20,20,
|
|
60,20,60,
|
|
60,60,20,
|
|
60,60,60,
|
|
};
|
|
|
|
int eschit(void)
|
|
{
|
|
return(kbhit());
|
|
}
|
|
|
|
#include "loadlbm.c"
|
|
|
|
main(int argc,char *argv[])
|
|
{
|
|
int a,b,c,d,x,y;
|
|
printf("\nColorMixer V1.0 (C) 1991 Sami Tammilehto \n\n");
|
|
if(argc==1)
|
|
{
|
|
printf("usage: col [?###] <src1> <src2>\n"
|
|
"when picture is in screen, press space to\n"
|
|
"toggle pics/palette, ESC to exit.\n"
|
|
"!### means reserve ### first colors for other\n"
|
|
"purposes (leave empty/to default pal)\n");
|
|
return(0);
|
|
}
|
|
if(*argv[1]=='?')
|
|
{
|
|
colsreserved=atoi(argv[1]+1);
|
|
argv[1]=argv[2];
|
|
argv[2]=argv[3];
|
|
}
|
|
bigpalpnt=0;
|
|
printf("Processing, please wait...\n");
|
|
printf("File: %s",argv[1]);
|
|
memset(pic,0,64000);
|
|
memset(pal,0,768);
|
|
loadlbm(argv[1]); printf("100%%\n");
|
|
memcpy(pic1,pic,64000);
|
|
memcpy(pal1,pal,768);
|
|
analyze(pic1,pal1);
|
|
printf("File: %s",argv[2]);
|
|
memset(pic,0,64000);
|
|
memset(pal,0,768);
|
|
loadlbm(argv[2]); printf("100%%\n");
|
|
memcpy(pic2,pic,64000);
|
|
memcpy(pal2,pal,768);
|
|
analyze(pic2,pal2);
|
|
bigpalnum=bigpalpnt;
|
|
printf("Colors in big palette: %i\n",bigpalnum);
|
|
printf("Combining and optimizing palettes...\n");
|
|
memset(pal,0,768);
|
|
memcpy(pal,defpal,16*3);
|
|
createpal();
|
|
printf("Remapping first picture... \n");
|
|
remap(pic1,pal1,pal);
|
|
printf("Remapping second picture... \n");
|
|
remap(pic2,pal2,pal);
|
|
reg.x.ax=0x13;
|
|
int86(0x10,®,®);
|
|
{
|
|
outp(0x3c8,0);
|
|
for(a=0;a<768;a++) outp(0x3c9,pal[a]);
|
|
}
|
|
for(;;)
|
|
{
|
|
memset(vram,0,64000);
|
|
for(a=0;a<16;a++) for(b=0;b<16;b++)
|
|
{
|
|
x=a*12; y=b*10;
|
|
for(c=0;c<11;c++) for(d=0;d<9;d++)
|
|
{
|
|
*(vram+x+c+(y+d)*320)=b+a*16;
|
|
}
|
|
}
|
|
a=getch();
|
|
if(a==13 || a==27) break;
|
|
memcpy(vram,pic1,64000);
|
|
a=getch();
|
|
if(a==13 || a==27) break;
|
|
memcpy(vram,pic2,64000);
|
|
a=getch();
|
|
if(a==13 || a==27) break;
|
|
}
|
|
reg.x.ax=0x3;
|
|
int86(0x10,®,®);
|
|
}
|
|
|
|
unsigned colcnt[256];
|
|
|
|
int analyze(unsigned char *pic,unsigned char *pal)
|
|
{
|
|
int a,b,c,x,y;
|
|
printf("Generating big palette and calculating relative color importances...\n");
|
|
memset(colcnt,0,256*2);
|
|
for(y=0;y<200;y++) for(x=0;x<320;x++)
|
|
{
|
|
colcnt[pic[x+y*320]]++;
|
|
}
|
|
for(a=0;a<256;a++)
|
|
{
|
|
if(colcnt[a]!=0)
|
|
{
|
|
bigpal[bigpalpnt*3+0]=pal[a*3+0];
|
|
bigpal[bigpalpnt*3+1]=pal[a*3+1];
|
|
bigpal[bigpalpnt*3+2]=pal[a*3+2];
|
|
bigcnt[bigpalpnt++]=colcnt[a];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int createpal(void)
|
|
{
|
|
int testval,testcnt;
|
|
int colors=256-colsreserved,firstcol=colsreserved;
|
|
int xr,xb,xg,xh,xs,xv;
|
|
int a,b,c,d,e,f,g,h;
|
|
int x,y;
|
|
int s;
|
|
|
|
rgb2hsv(bigpalhsv,bigpal,bigpalnum);
|
|
|
|
for(testcnt=0;testcnt<5;testcnt++)
|
|
{
|
|
switch(testcnt)
|
|
{
|
|
case 0 : testval=0; break;
|
|
case 1 : testval=1; break;
|
|
case 2 : testval=3; break;
|
|
case 3 : testval=5; break;
|
|
case 4 : testval=8; break;
|
|
}
|
|
memset(pal+firstcol*3,0,colors*3);
|
|
memcpy(bigcntbak,bigcnt,bigpalnum*2);
|
|
for(a=0;a<colors;)
|
|
{
|
|
printf("Processing pass %i/5: %i%% complete \r",testcnt+1,100*a/256);
|
|
{
|
|
unsigned int c;
|
|
c=0; /* max */
|
|
d=0; /* maxcolowner */
|
|
for(b=0;b<bigpalnum;b++)
|
|
{
|
|
if(bigcnt[b]>c) { c=bigcnt[b]; d=b; }
|
|
}
|
|
if(c==0) { testcnt=999; break; }
|
|
s=d; bigcnt[d]=0;
|
|
}
|
|
|
|
{
|
|
xr=bigpal[s*3+0];
|
|
xg=bigpal[s*3+1];
|
|
xb=bigpal[s*3+2];
|
|
xh=bigpalhsv[s*3+0];
|
|
xs=bigpalhsv[s*3+1];
|
|
xv=bigpalhsv[s*3+2];
|
|
c=999; /* difference */
|
|
for(b=firstcol;b<a+firstcol;b++)
|
|
{
|
|
f=b*3;
|
|
g=((xr-(unsigned int)pal[f+0]));
|
|
e=(g<0?-g:g);
|
|
g=((xg-(unsigned int)pal[f+1]));
|
|
e+=(g<0?-g:g);
|
|
g=((xb-(unsigned int)pal[f+2]));
|
|
e+=(g<0?-g:g);
|
|
/*g=((xh-(unsigned int)palhsv[f+0]));
|
|
e=(g<0?-g:g)*2;
|
|
g=((xs-(unsigned int)palhsv[f+1]));
|
|
e+=(g<0?-g:g)*2;
|
|
g=((xv-(unsigned int)palhsv[f+2]));
|
|
e+=(g<0?-g:g);*/
|
|
if(e<c) { c=e; }
|
|
}
|
|
}
|
|
if(c>testval)
|
|
{
|
|
d=a+firstcol;
|
|
pal[d*3]=bigpal[s*3];
|
|
pal[d*3+1]=bigpal[s*3+1];
|
|
pal[d*3+2]=bigpal[s*3+2];
|
|
rgb2hsv(palhsv+d*3,pal+d*3,1);
|
|
a++;
|
|
}
|
|
}
|
|
memcpy(bigcnt,bigcntbak,bigpalnum*2);
|
|
}
|
|
rgb2hsv(palhsv,pal,256);
|
|
}
|
|
|
|
int remap(unsigned char *pic,unsigned char *spal,unsigned char *pal)
|
|
{
|
|
int xr,xb,xg,xh,xs,xv;
|
|
int a,b,c,d,e,f,g,h;
|
|
memset(palmap,0,256);
|
|
rgb2hsv(tmphsv,spal,256);
|
|
for(a=0;a<256;a++)
|
|
{
|
|
printf("Processing: %i%% complete \r",100*a/256/2);
|
|
xr=spal[a*3+0];
|
|
xg=spal[a*3+1];
|
|
xb=spal[a*3+2];
|
|
xh=tmphsv[a*3+0];
|
|
xs=tmphsv[a*3+1];
|
|
xv=tmphsv[a*3+2];
|
|
h=0; c=999; /* difference */
|
|
for(b=colsreserved;b<256;b++)
|
|
{
|
|
f=b*3;
|
|
/*g=(xh-(unsigned int)palhsv[f+0]);
|
|
e=(g<0?-g:g)*2;
|
|
g=(xs-(unsigned int)palhsv[f+1]);
|
|
e+=(g<0?-g:g);
|
|
g=(xv-(unsigned int)palhsv[f+2]);
|
|
e+=(g<0?-g:g)*2;*/
|
|
g=((xr-(unsigned int)pal[f+0]));
|
|
e=(g<0?-g:g);
|
|
g=((xg-(unsigned int)pal[f+1]));
|
|
e+=(g<0?-g:g);
|
|
g=((xb-(unsigned int)pal[f+2]));
|
|
e+=(g<0?-g:g);
|
|
if(e<c) { c=e; h=b; }
|
|
}
|
|
palmap[a]=h;
|
|
}
|
|
for(a=0;a<200;a++)
|
|
{
|
|
printf("Processing: %i%% complete \r",100*a/200/2+50);
|
|
for(b=0;b<320;b++)
|
|
{
|
|
pic[a*320+b]=palmap[pic[a*320+b]];
|
|
}
|
|
}
|
|
}
|
|
|
|
int minval(int v1,int v2,int v3)
|
|
{
|
|
if(v1<v2 && v1<v3) return(v1);
|
|
if(v2<v1 && v2<v3) return(v2);
|
|
if(v3<v1 && v3<v2) return(v3);
|
|
return(v1);
|
|
}
|
|
|
|
int maxval(int v1,int v2,int v3)
|
|
{
|
|
if(v1>v2 && v1>v3) return(v1);
|
|
if(v2>v1 && v2>v3) return(v2);
|
|
if(v3>v1 && v3>v2) return(v3);
|
|
return(v1);
|
|
}
|
|
|
|
int rgb2hsv(unsigned char *dst,unsigned char *src,int num)
|
|
{
|
|
int cr,cg,cb;
|
|
int tmp,i;
|
|
int xr,xg,xb,zh,zs,zv;
|
|
for(i=0;i<num;i++)
|
|
{
|
|
xr=*(src++);
|
|
xg=*(src++);
|
|
xb=*(src++);
|
|
/* value */
|
|
zv=maxval(xr,xg,xb);
|
|
/* saturation */
|
|
tmp=minval(xr,xg,xb);
|
|
if(zv==0) zs=0; else zs=63*(zv-tmp)/zv;
|
|
/* hue */
|
|
if(zs==0) zh=127;
|
|
else
|
|
{
|
|
cr=100*(zv-xr)/(zv-tmp);
|
|
cg=100*(zv-xg)/(zv-tmp);
|
|
cb=100*(zv-xb)/(zv-tmp);
|
|
if(xr==zv) zh=cb-cg;
|
|
if(xg==zv) zh=200+cr-cb;
|
|
if(xb==zv) zh=400+cg-cr;
|
|
if(zh<0) zh+=500;
|
|
zh/=8;
|
|
}
|
|
*(dst++)=zh;
|
|
*(dst++)=zs;
|
|
*(dst++)=zv;
|
|
}
|
|
}
|
|
|