你是不是把问题写反了,将256色转换为16色?16色不存在转为256色的问题,最多就是将BMP文件格式改一下,将16种颜色填到256色调色板的第16-31色(有的系统保留前16色以保持界面显示不变),再把图素逐点改为调色板的相应值即可。不存在改变效果的问题。

解决方案 »

  1.   

    这个问题涉及从真彩色中选择于人的视觉相关的敏感的256种颜色,由于篇幅关系,我无法详细解释数学模型,请研究以下代码(PCX到256):#include <dos.h>
    #include <stdio.h>
    #include <conio.h>
    //#include <alloc.h> unsigned char REbuff[640][3],pal_buff[256][3];
    unsigned char [64],SUM_[64];
    unsigned int max_NUM;
    struct I
    {
    unsigned char R;
    unsigned char G;
    unsigned char B;
    unsigned char gray;
    }bright[64][20],REcolor[1000],color[256];
    struct HEAD
    {
    unsigned int bo;
    unsigned int ver;
    unsigned long next;
    }head;
    struct DIR
    {
    unsigned int tga;
    unsigned int type;
    unsigned long len;
    unsigned long val;
    }dir[20];
    main(argc,argv)
    int argc;
    char * argv[];
    {
    union REGS in ,out;
    unsigned char cur_mode,cur_page;
    FILE * pcx;
    unsigned char rec[6][6][6];
    int p2,p3,w1,w2,w3,hi_test=0,low_test=0;
    unsigned long k1,k2,k3,jj,blue_mean,star,star1,palptr;
    unsigned long sw1,sw2,sw3,success,with,hight;
    unsigned int REmax_NUM,kkk,i,n,k,m,j,mmend,kk,nd,d,test=1,tt;
    unsigned char gray,level;
    unsigned int COL_NUM,d1,d2,d3;
    sw1=128;
    w1=4;
    w2=8;
    w3=1;
    if((pcx=fopen(argv[1],"rb+"))==NULL) {printf("open file error!");exit(0);} fread(&head,8,1,pcx);
    fseek (pcx, head. next, SEEK_SET);
    fread (&nd,2,1,pcx);
    fread (dir,12 * nd,1,pcx);
    for(i=0; i<nd; i++) switch(dir[i].tga )

    case 0x100:with=dir[i]. val; break;
    case 0x101:hight=dir[i].val; break;
    case 0x111:star1=dir[i].val; break;
    case 0x140:palptr=dir[i].val;break;
    default : continue;
    }
    for(i=0; i<64; i++)
    for(j=0;j<20; j++)
    {
    bright[i][j].R=2 * i;
    bright[i][j].G=2 *i;
    bright[i][j].B=2 *i;
    }
    for(i=0;i<64;i++)
    {
    [i]=0;
    }
    max_NUM=1;
    REcolor[0].R=0;
    REcolor[0].G=0;
    REcolor[0].B=0;
    for(i=0; i<6; i++)
    for(j=0; j<6; j++)
    for(k=0; k<6; k++)
    rec[i][j][k]=0;
    fseek (pcx,star1,SEEK_SET);
    for(j=0; j<hight; j++)
    {
    k1=REbuff[m][0]/43;
    k2=REbuff[m][1]/43;
    k3=REbuff[m][2]/43;
    rec[k1][k2][k3]=1;
    }
    REmax_NUM=0;
    for(i=0; i<6; i++)
    for(j=0; j<6; j++)
    for(k=0; k<6; k++)
    {if(rec[i][j][k]==1) REmax_NUM++;}
    sw2=REmax_NUM * 10+40;
    while ((max_NUM<230) | (max_NUM>255))
    {
    max_NUM=1;
    fseek (pcx,star1,SEEK_SET);
    for(j=0; j<hight; j++)
    {
    fread(REbuff,3,with,pcx);
    printf("%5d", j);
    gray=0.30 * REbuff[0][0]+0.59 * REbuff[0][1]+0.11 * REbuff[0][2];
    level=gray/4;
    success=0;
    i=0;
    while(success!=1)
    {
    d1=w1 * (REbuff[0][0]-REcolor[i].R)*(REbuff[0][0]-REcolor[i].R);
    d2=w2 * (REbuff[0][1]-REcolor[i].G)*(REbuff[0][1]-REcolor[i].G);
    d3=w3 * (REbuff[0][2]-REcolor[i].B)*(REbuff[0][2]-REcolor[i].B);
    d=d1+d2+d3;
    if(d<sw2)
    {success=1;}
    else{i++;
    if(i==max_NUM)
    {
    REcolor[i].R=REbuff[0][0];
    REcolor[i].G=REbuff[0][1];
    REcolor[i].B=REbuff[0][2];
    REcolor[i].gray=0.30 * REbuff[0][0] +0.59 * REbuff[0][1]+0.11 * REbuff[0][2];
    max_NUM++;
    success=1;
    }
    }
    }
    for(m=1;m<with;m++)
    {
    gray=0.30 * REbuff[m][0]+0.59 * REbuff[m][1]+0.11 *REbuff[m][2];
    level=gray/4;
    success=0;
    i=0;
    while(success !=1 )
    {
    d1=w1*(REbuff[m][0]-REcolor[i].R)*(REbuff[m][0]-REcolor[i].R);
    d2=w2*(REbuff[m][1]-REcolor[i].G)*(REbuff[m][1]-REcolor[i].G);
    d1=w1*(REbuff[m][2]-REcolor[i].B)*(REbuff[m][2]-REcolor[i].B);
    d=d1+d2+d3;
    if(d<sw2)
    {success=1;}
    else{i++;
    if(i==max_NUM)
    {
    REcolor[i].R=REbuff[m][0];
    REcolor[i].G=REbuff[m][1];
    REcolor[i].B=REbuff[m][2];
    REcolor[i].gray=0.30 * REbuff[m][0] +0.59 * REbuff[m][1]+0.11 * REbuff[m][2];
    max_NUM++;
    success=1;
    }
    }
    }
    }
    }
    if((max_NUM<=255)&&(max_NUM>=230))
    {
    printf("\70k! Press any key to display.....\n");
    }
    if(max_NUM>255)
    {
    if(low_test==1)
    {
    sw1=sw1/2;
    hi_test=1;
    low_test=0;
    }
    else hi_test=1;
    sw2+=sw1;
    }
    if(max_NUM<230)
    {
    if(hi_test==1)
    {
    sw1=sw1/2;
    low_test=1;
    hi_test=0;
    }
    else low_test=1;
    sw2-=sw1;
    }
    getch( );
    for(i=0;i<max_NUM; i++)
    {
    color[i].R=REcolor[i].R;
    color[i].G=REcolor[i].G;
    color[i].B=REcolor[i].B;
    color[i].gray=REcolor[i].gray;
    }
    for(i=0;i<max_NUM; i++)
    {
    level=color[i].gray/4;
    COL_NUM=[level];
    [level]++;
    bright[level][COL_NUM].R=color[i].R;
    bright[level][COL_NUM].G=color[i].G;
    bright[level][COL_NUM].B=color[i].B;
    }
    for(i=0;i<64; i++)
    {
    jj=0;
    for(j=0;j<i;j++)
     jj+=[j];
    SUM_[i]=jj;
    }
    pal_buff[0][0]=0;
    pal_buff[0][1]=0;
    pal_buff[0][2]=0;
    for(i=0; i<256; i++)
    {
    pal_buff[i][0]=255;
    pal_buff[i][1]=255;
    pal_buff[i][2]=255;
    }
    for(i=0; i<64; i++)
    {
    for(j=0;j<[i]; j++)
    {
    pal_buff [SUM_[i]+j+1] [0]=bright[i][j].R;
    pal_buff [SUM_[i]+j+1] [1]=bright[i][j].G;
    pal_buff [SUM_[i]+j+1] [2]=bright[i][j].B;
    }
    }
    fclose(pcx);
    in.h.ah=15;
    int86(0x10,&in,&out);
    cur_mode=out.h.al;
    cur_page=out.h.bl;
    p2=320-with/2;
    p3=240-hight/2;
    show(argv[1],p2,p30);
    in.h.al=0;
    in.h.al=cur_mode;
    int86(0x10,&in,&out);
    }                    void show(char * filename, int x, int y)
    {
    union REGS in , out;
    FILE * pcx;
    unsigned int long cc = 0, dd,star, palptr, min_dd;
    unsigned int success, kkk, kk, level, ii, m, j, kl, k2, k3, d1, d2, d3;
    unsigned int dd1, dd2, dd3, dd4, ddd, jj, n, nd, bitcount, with, hight, d;
    unsigned char hh, buff[640];
    int i, k=-1;
    int w1=1,w2=1,w3=1;
    unsigned char ch, mode, seg_num=0;
    char far * pvdieo = (char far * ) 0xa0000000;
    in. h.ah.=0;
    in. h. al=0x5d;
    int86(0x10, &in ,&out);
    outp(ox3c8, 0);
    for(j=0; j<256; j + + )
    for(i=0; i<3; i + +)
    outp(0x3c9,pal_buff[j][i]>>2);
    x=x%640;
    y=y%480;
    cc=(long)y * (long)640+(long)x;
    while(cc>=65535) {cc=cc-65535.seg_num+ +;}
    if(seg_num==0)if(x<=254)k=-x-1;else k=640-x-1;
    if(seg_num==1)if(x<=510)k=254-x;else k=640-x+254;
    if(seg_num==2)if(x<=126)k=510-x;else k=640-x+510;
    if(seg_num==3)if(x<=382)k=126-x;else k=640-x+126;
    if(seg_num==4)if(x<=638)k=638-x;else k=640-x+382;
    pvdieo+=cc;
    outp(0x3c4, 0x0e);
    in.h.al=seg_num + +;
    in.h.al=(ih.h.al&0x0f)^0x02;
    outp(0x3c5, in.h.al);
    if((pcx=fopen(filename,"rb+"))==NULL)
    {printf("open file error!"); exit(0);}
    fread(&head, 8,1,pcx);
    fseek(pcx, head. next,SEEK_SET);
    fread(&nd,2,1,pcx);
    fread(dir,12*nd,1,pcx);
    for(i=0; i<nd; i + +)
    switch (dir[i].tga)
    {
    case 0x100:with=dir[i].val; break;
    case 0x101:hight=dir[i].val; break;
    case 0x102:bitcount=dir[i].val; break;
    case 0x111:star=dir[i].val; break;
    case 0x140:palptr=dir[i].val; break;
    default : continue;
    }
    fseek(pcx,star,SEEK_SET);
    for(j=0; j<hight; j + +)
    {
    fread(REbuff, 3, with, pcx);
    jj=(0.30*REbuff[0][0]+0.59*REbuff[0][1]+0.11*REbuff[0][2])/4;
    min_dd=10000000;
    buff[0]=SUM_[jj];
    for(hh=0; hh<9; hh + +)
    {
    if(((jj-4+hh)>=0)&&((jj-4+hh)<=63))
    {
    for(i=0; i<[jj-4+hh]; i + +)
    {
    dd=0;
    dd + = w1*( bright [ jj-4+hh] [i].R-REbuff [0][0])*(bright [jj-4+hh] [i].R-REbuff [0][0]);
    dd + = w2*( bright [ jj-4+hh] [i].G-REbuff [0][1])*(bright [jj-4+hh] [i].G-REbuff [0][1]);
    dd + = w3*( bright [ jj-4+hh] [i].B-REbuff [0][2])*(bright [jj-4+hh] [i].B-REbuff [0][2]);
    if(dd<min_dd)
    {
    min_dd=dd;
    buff[0]=SUM_[jj-4+hh]+i+1;
    }
    }
    }
    }
    for(m=1; m<with; m + +)
    {
    kkk=(0.30*REbuff[m][0]+0.59*REbuff[m][1]+0.11*REbuff[m][2])/4;
    buff[m]=SUM_[kkk];
    min_dd=10000000;
    for(hh=0; hh<9; hh + +)
    {
    if(((kkk-4+hh)>=0)&&((kkk-4+hh)<=63))
    {
    for(i=0; i<[kkk-4+hh]; i + +)
    {
    k1=abs (bright [kkk-4+hh][i].R=REbuff[m][0]);
    k2=abs (bright [kkk-4+hh][i].G=REbuff[m][1]);
    k3=abs (bright [kkk-4+hh][i].B=REbuff[m][2]);
    if((k1<25)&&(k2<20)&&(k3<30))
    {
    dd=0;
    dd + = w1*( bright [ kkk-4+hh] [i].R-REbuff [m][0])*(bright [kkk-4+hh] [i].G-REbuff [m][0]);
    dd + = w2*( bright [kkk-4+hh] [i].G-REbuff [m][1])*(bright [kkk-4+hh] [i].G-REbuff [m][1]);
    dd + = w3*( bright [kkk-4+hh] [i].B-REbuff [m][2])*(bright [kkk-4+hh] [i].B-REbuff [m][2]);
    if(dd<min_dd)
    {
    min_dd=dd;
    buff[0]=SUM_[kkk-4+hh]+i+1;
    }
    }
    }
    }
    }
    }
    if((cc+640),65535)
    {
    for(m=0;m<with; m + +)
    *pvdieo + + =buff[m];
    pvdieo + =640-with;
    cc+=640;
    }
    else
    {
    k=(k+256)%640;
    if(k<with)
    {
    for(m=0; m<=k; m + +)
    *pvdieo + + =buff[m];
    {
    else
    {
    for(m=0; m<with; m + +)
    *pvdieo+ +=buff[m];
    pvdieo + =k-with;
    }
    outp(0xc4, 0x0e);
    in.h.al=seg)num + +;
    in.h.al=(in.h.al& 0x0f)^0x02;
    outp(0x3c5, in.h.al);
    pvdieo=(char far * ) 0xa0000000;
    if(k<with)
    {
    for(i=m; i<with; i + +)
    *pvdieo + + =buff[i];
    pvdieo + =640-with;
    cc=640-k;
    }
    else
    {
    pvdieo + = 639-k;
    cc=640-k;
    }
    }
    }
    fclose(pcx);
    getch ( );
    }