有一个16X16的bmp图片,用工具 convert.exe转换后,数据是:
{
  0,80,80,80,80,80,80,80,80,80,80,80,78,80,80,0
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
}发现用16*2个值就能保存该图片。
但我不知道区中的编码是怎莫来的。
请教!!!。
算法怎莫学的???分不够可加。

解决方案 »

  1.   

    没用过,-_-#
    这个数据是保存下来是什么格式啊?保存下来txt可以打开吗?
    然后把txt另存为*.bmp能回复到图片么?学习
      

  2.   

    反正我看楼主的数据是没看出什么门道来,啥乱78糟的阿-_-!下面的连接是bmp的格式的详细说明http://www.wotsit.org/filestore/bmpfrmat.zip大伙没事的话也帮忙看看
      

  3.   

    一般都是RLE压缩方式;具体的压缩编码如下:
    0a xx xx xx
    a 个单独的颜色点1a bb xx xx xx
    abb 个单独的颜色点Da bb 
    abb 个透明色Ca 
    a 个透明色8a xx
    a 个颜色是XX的点9a xx bb
    abb 个颜色为xx的点Aa xx bb cc
    abbcc 个颜色为xx的点其他情况,没有压缩基本上超过3个点一样就用8a xx 了这个是我自己写的压缩bmp的算法,传奇3的图象资源的处理代码,很烂;处理的是565格式;var
      STM: TMemorystream;
      i,fwidth,fheight: Integer;
      offset: dword;
      ilen: dword;
      DTM: TMemoryStream;
      Buffer: array of WORD;
      DnyArray: Array of WORD;
      abyte: array[0..8] of Byte;
      
        function CompressToWil: Integer;
        var
          Count           : Integer;
          i, J, Idx, bakIdx: integer;
        begin
          I := 0;
          Idx := 0;                           //  Count := 0;//  bakIdx := 0;
      
          Setlength(DnyArray, High(Buffer) * 2);
          while i <= High(Buffer) do
          begin
            if buffer[i] = 63519 then
            begin
              DnyArray[Idx] := $C0;
              Inc(Idx, 1);
              Count := 0;
              for j := i to High(Buffer) do
              begin
                if buffer[j] = 63519 then
                begin
                  Inc(Count);
                end
                else
                  break;
              end;
              DnyArray[Idx] := count;
              i := j;
              Inc(Idx, 1);
            end
            else
            begin
              DnyArray[Idx] := $C1;
              Inc(Idx, 1);
              bakIdx := Idx;
              Count := 0;
              for j := i to High(Buffer) do
              begin
                if buffer[j] <> 63519 then
                begin
                  Inc(Count);
                  Inc(Idx);
                  DnyArray[Idx] := buffer[j];
                end
                else
                  break;
              end;
              DnyArray[bakIdx] := Count;
              i := j;
              Inc(Idx);
            end;
          end;
          setLength(DnyArray, Idx);
          result := Idx;
        end;
      
      procedure makeByte(streamSize:DWORD);
      var
        HexStr            : string;
        iC                 : Integer;
        a, b, c, d        : string;
      begin
      
        HexStr := Format('%8x', [streamSize]);
        for iC := 1 to Length(HexStr) do
          if HexStr[iC] = #32 then
            HexStr[iC] := '0';
      
        a := HexStr[1] + HexStr[2];           //12
        b := HexStr[3] + HexStr[4];           //34
        c := HexStr[5] + HexStr[6];           //56
        d := HexStr[7] + HexStr[8];           //78
      
        abyte[0] := FImageHandle.X[0];
        abyte[1] := FImageHandle.X[1];
        abyte[2] := FImageHandle.X[2];
        abyte[3] := FImageHandle.X[3];
        abyte[4] := FImageHandle.X[4];
        abyte[5] := StrToInt('$' + d);
        abyte[6] := StrToInt('$' + c);
        abyte[7] := StrToInt('$' + b);
        abyte[8] := StrToInt('$' + a);
      
      end;
      
    begin
      if (FbitMap.Empty) then Exit;  //如果为空数据则退出过程
      if not FImageChange then Exit;
      FRLTStream.Clear;
      
      STM := TMemoryStream.Create;          //压缩前
      DTM := TMemoryStream.Create;          //压缩后
      try
        FlipImg(FBitmap); //反转
        FbitMap.SaveToStream(STM);
        FlipImg(FBitmap); //还原
        fwidth := Fbitmap.Width;
        fheight := FBitmap.Height;
        offset := 66;
        stm.Seek(offset, 0);
        setLength(Buffer, fwidth);          //设置 本次的缓冲区尺寸
      
        FImageHandle.Px := FOffsetX;
        FImageHandle.Py := FOffsetY;
      
        ilen:=0;
        DTM.seek(0,0);
        DTM.Write(FImageHandle,12);
        DTM.Write(iLen,1);
        DTM.write(FImageSize,4);
        DTM.Write(iLen,1);
        DTM.Seek(17,0);
      
        for i := 0 to fheight - 1 do
        begin
          stm.Read(Buffer[0], fwidth * 2);  //取出 数据到 图像缓冲区
          iLen := CompressToWil;
          DTM.Write(iLen, 2);
          DTM.write(DnyArray[0], iLen*2);
        end;
        iLen :=((DTM.Size-17) div 2);
        dtm.seek(offset + 8,0);
        makeByte(iLen);
        dtm.Write(abyte[0],9);
        dtm.seek(0,0);
      
        FRLTStream.CopyFrom(dtm,dtm.size);
        FRLTStream.Seek(0,0);
        FImageChange :=false;
      finally
        stm.Free;
        dtm.Free;
      end;
    end;这个是解压算法
        //计算数据偏移地址
        offset := offset + headlen;
        for i := 0 to FImageHandle.height - 1 do
        begin
          f.Seek(offset, 0);                //定位当前位置
          f.Read(tmpWord, 2);               //读出本行数据长度 00C1,00C0
          fw := Tmpword;                    //得到宽度
          setlength(imgbuff, fw + 1);       //设置 本次的缓冲区尺寸
          f.Read(imgbuff[0], fw * 2);       //取出 数据到 图像缓冲区
          j := 0;
          while j < fw do                   //定位到开始
          begin
            case imgbuff[j] of              //
              $C0:                          //192
                begin
                  j := J + 1;
                  tmpWord := 63519;         //0;
                  for n := 0 to imgbuff[j] - 1 do
                    imageStream.Write(tmpword, sizeOf(word));
                  j := J + 1;
                end;
              $C1, $C2:                     //193, 194:
                begin
                  j := j + 2;
                  imageStream.Write(imgBuff[j], imgbuff[j - 1] * sizeof(word));
                  j := j + imgbuff[j - 1];
                end;
            end;
          end;
          offset := offset + fw * 2 + 2;
        end;
      

  4.   

    to S.F.
      bmp的压缩编码我也看了一下,没看出跟楼主给出的东东有啥联系……
    他那里面咋全是80?
      

  5.   

    一般图片的压缩分为有损压缩和无损压缩
    这样转化成exe后不知道打开图片质量会不会变差
    至于压缩后怎么来的这样格式
    楼主要看看bmp的形成机理和内在构成
    ---------------------------------------
    http://purec.binghua.com/Article/SoftAndHardResourse/FileFormat/200410/280.html
      

  6.   

    把BMP文件转换为EXE文件的通用方法[转]--很可惜,是C语言
    ----------------------------------------------------------
    目前出现很多别具特色的图像显示程序, 其中一种特
    殊的处理功能就是把图像文件如BMP、GIF等文件直接转换
    为.EXE可执行文件, 实际上如果了解了图像显示的一般原
    理, 即可以轻松的完成这种文件转换功能。下面以显示16
    色BMP 图像为例, 编制一个BMP2EXE转换程序。
    一、基本原理:完成此操作的基本过程, 就是在图形
    文件的头部加上一段具有图像显示能力的程序段, 当运行
    合并后的程序时,打开此文件本身,并移动文件指针到图像
    数据段,依次读出内容显示即可。所以一个完整的BMP2COM
    程序内部, 应该同时具有显示图像功能及合并文件的功能,
    其中的合并文件功能负责把其中的显示图像程序段与图像
    文件进行合并处理, 而显示图像功能只有在合并后的 EXE
    文件运行时才能得到执行。
    二、文件指针的调整问题: 当进行图像显示时, 必须
    把文件指针移到正确位置,即跳过显示程序段部分,但由于
    程序调试时显示程序段长度是不定的, 无法确定具体的数
    值,此时可以采取一种动态记录显示程序段的方法,即合并
    显程序与图像文件时, 把显示程序长度记录在合并后程序
    的未尾, 运行转换后的可执行文件时, 首先从文件尾部读
    出显示程序长度, 即可移到正确位置。另外程序的显示模 
    式号,及屏幕起始坐标等均采用此方法进行保存和读取。
    三、程序使用方法:此程序运行时需要携带两个或二
    个以上参数, 段如程序名为BMP2EXE.EXE,则命令格式:
    BMP2EXE Source Target Mode Row Col
    其中Source为原图像文件内容, Target为转换后的目
    标文件名, 后缀必须为EXE, MODE为所使用的显示模式,可
    为系统支持的任意16色以上图像模式, 用16进制表示,ROW
    及COL 为图像在屏幕上的起始坐标值, 以象素为单位, 可
    为256 以内的10进制数值, 主要用于调整图像在屏幕上的
    具体位置, 其中显示模式及坐标均可省略, 省略时使用系
    统的12H 图像模式, 并从屏幕的始端开始显示图像。转换
    之后所产生的EXE 文件即可以单独运行, 运行之后即可以
    把当前屏幕置为相应的显示模式, 并在指定的位置显示图
    像。本文仅演示了16色BMP 图像的显示过程, 可扩充其
    中的图像显示过程, 使之可处理真彩色图像或其它格式的
    图像文件。

    //BMP图像转换为可执行文件
    //适用于16色BMP图像文件
    #include <dos.h>
    #include <dir.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <graphics.h>
    void setmod(int videomode);
    void putp(int x,int y,int color);
    union REGS r;
    void main(int argc,char * argv[])
    {
    struct ffblk f;
    register int done;
    int gd,gm,cl,wl,ll,kuan,il,iw,row,col;
    long prglen;
    char cc,vmode,*end;
    FILE *exe,*me,*bmp,*fp;
    static int color[16]={0,4,2,6,1,5,3,8,7,12,10,14,9,13,11,15};
    if(argc>1){ //合并文件段
    findfirst(argv[0],&f,55); //取文件长度值
    prglen=f.ff_fsize;
    me=fopen(argv[0],"rb"); //打开相关文件
    exe=fopen(argv[2],"wb");
    if(exe==NULL){
    printf("Target File Open Error!");exit(0);}
    bmp=fopen(argv[1],"rb");
    if(bmp==NULL){
    printf("Source File Open Error!");exit(0);}
    while(1){ //读写显示程序
    cc=fgetc(me);
    if(!feof(me))
    fputc(cc,exe);else break; }
    while(1){ //读写图像文件
    cc=fgetc(bmp);
    if(!feof(bmp))
    fputc(cc,exe);else break; }
    if(argc>3){
    cc=strtol(argv[3],&end,16); //写显示模式号
    fputc(cc,exe);}else{
    cc=0x12;
    fputc(cc,exe);}
    if(argc>4){ //写起始横坐标
    cc=atoi(argv[4]);
    fputc(cc,exe); }else{
    cc=0;
    fputc(cc,exe); }
    if(argc>5){ //写起始纵坐标
    cc=atoi(argv[5]);
    fputc(cc,exe); }else{
    cc=0;
    fputc(cc,exe); }
    r.x.ax=prglen; //写原始文件长度
    cc=r.h.ah;
    fputc(cc,exe);
    cc=r.h.al;
    fputc(cc,exe);
    cc=0x55; //写文件识别标志
    fputc(cc,exe);
    fclose(me);
    fclose(exe);
    fclose(bmp); //关闭相关文件
    printf("Please Disp <%s>",argv[2]);
    exit(0);}
    else //显示文件段
    fp=fopen(argv[0],"rb");
    findfirst(argv[0],&f,55); //取文件长度值
    prglen=f.ff_fsize;
    fseek(fp,prglen-1,SEEK_SET);//移文件指针
    cc=fgetc(fp);
    if(cc!=0x55){ //判断文件标志
    printf("\\nHELP:\\7"); //提示信息
    printf("\\nBMP2EXE Source Target Mode Row Col.");
    exit(0);}else
    fseek(fp,prglen-6,SEEK_SET);
    vmode=fgetc(fp); //取显示模式
    row=fgetc(fp); //取起始横坐标
    col=fgetc(fp); //取起始纵坐标
    r.h.ah=fgetc(fp); //取文件长度
    r.h.al=fgetc(fp);
    prglen=r.x.ax; //移到图形数据段
    fseek(fp,prglen+18,SEEK_SET);
    fread(&kuan,4,1,fp);
    wl=kuan; //图像宽度
    fread(&kuan,4,1,fp);
    ll=kuan; //图像高度
    fseek(fp,prglen+118,SEEK_SET);
    setmod(vmode); //置显示模式
    for(il=0;il<ll;il++) //显示第一遍
    for(iw=0;iw<wl;iw++){
    fread(&kuan,1,1,fp);
    cl=(kuan&0xf0)>>4;
    putp(row+iw,col+ll-il,color[cl]);
    iw=iw+1;}
    fseek(fp,prglen+118,SEEK_SET);
    for(il=0;il<ll;il++) //显示第二遍
    for(iw=0;iw<wl;iw++){
    fread(&kuan,1,1,fp);
    iw=iw+1;
    cl=kuan&0x0f;
    putp(row+iw,col+ll-il,color[cl]);}
    getch(); //程序暂停
    fclose(fp); //关闭文件
    setmod(0x3); } //恢复文本模式
    void setmod(int videomode)
    { //置显示模式函数
    r.h.ah=0;
    r.h.al=videomode;
    int86(0x10,&r,&r);}
    void putp(int x,int y,int color)
    {r.h.al=color; //写点函数
    r.h.ah=0x0c;
    r.h.bh=0;
    r.x.cx=x;
    r.x.dx=y;
    int86(0x10,&r,&r);}