如何将16位图像转换为256色图像,基本不改变图像效果

xuhao1 2000-08-30 07:07:00
如何将16位图像转换为256色图像,基本不改变图像效果
...全文
420 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
SAsura 2001-01-27
  • 打赏
  • 举报
回复
如果对图像分辨率没有要求的话可以将横竖分辨率增大一倍,然后采用抖动的方法,我想这可能是失真最小的办法。
michaelh 2001-01-26
  • 打赏
  • 举报
回复
这个问题涉及从真彩色中选择于人的视觉相关的敏感的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 mark[64],SUM_mark[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++)
{
mark[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=mark[level];
mark[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+=mark[j];
SUM_mark[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<mark[i]; j++)
{
pal_buff [SUM_mark[i]+j+1] [0]=bright[i][j].R;
pal_buff [SUM_mark[i]+j+1] [1]=bright[i][j].G;
pal_buff [SUM_mark[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_mark[jj];
for(hh=0; hh<9; hh + +)
{
if(((jj-4+hh)>=0)&&((jj-4+hh)<=63))
{
for(i=0; i<mark[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_mark[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_mark[kkk];
min_dd=10000000;
for(hh=0; hh<9; hh + +)
{
if(((kkk-4+hh)>=0)&&((kkk-4+hh)<=63))
{
for(i=0; i<mark[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_mark[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 ( );
}





xuhao1 2000-08-31
  • 打赏
  • 举报
回复
对不起,写的不大清楚,是16位颜色不是16色
tchaikov 2000-08-30
  • 打赏
  • 举报
回复
你是不是把问题写反了,将256色转换为16色?

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

taxi 2000-08-30
  • 打赏
  • 举报
回复
bitmap.pixelformat:=pf8bit

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧