开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 319|回复: 6
收起左侧

[讨论] 有没有Delphi大佬

[复制链接]
结帖率:67% (8/12)
发表于 3 天前 | 显示全部楼层 |阅读模式   山东省*
有没有Delphi大佬帮忙转易语言
结帖率:67% (8/12)

签到天数: 14 天

 楼主| 发表于 昨天 18:35 | 显示全部楼层   山东省*

代码放不上来
回复 支持 反对

使用道具 举报

结帖率:67% (8/12)

签到天数: 14 天

 楼主| 发表于 昨天 16:08 | 显示全部楼层   山东省*
本帖最后由 奔放的牛 于 2025-5-13 16:10 编辑

[Delphi] 纯文本查看 复制代码
unit was;

interface

uses
  SysUtils, Classes, Graphics, Dialogs, StrUtils;

type
  TWasPixel = record
    Alpha: Byte;
    Index: Byte;
  end;

  TWasImageInfo = record
    Key_X: Integer;
    Key_Y: Integer;
    Width: Integer;
    Height: Integer;
  end;

  TWasImage = record
    Info: TWasImageInfo;
    Data: array of TWasPixel;
  end;

  TWasFileInfo = record
    wfType: Word;
    whSize: Word;
    SpriteCount: Word;
    FrameCount: Word;
    MaxWidth: Word;
    MaxHeight: Word;
    Key_X: Word;
    Key_Y: Word;
  end;

  HighPal = array [0..255] of Word;
  
  TWasFile = class
  private
    // 图片信息
    Info: TWasFileInfo;
    Data: array of TWasImage;
    HeadData: array of Byte;  // 存储多余的文件头
    HeadDataSize: Integer;

    // 2个调色板
    OriginalPal: array [0..255] of Word;
    CurrentPal: array [0..255] of Word;

    // 原始文件
    FName: string;
    FSize: Cardinal;
    FData: array of Byte;
    fInitialized: Boolean;

    // xxxxxxxxxxxxxxxxxx
    procedure DecodeFromStream(var Dest: TWasImage; Stream: TStream);
    procedure Init();
    procedure Burn();
  public
    constructor Create();
    destructor Destroy(); override;
    // 相关方法
    procedure LoadFromFile(const FileName: string);
    procedure SaveToFile(const FileName: string);
    procedure Draw(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
    procedure DrawByKey(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
    function GetSpriteCount(): Integer;
    function GetFrameCount(): Integer;
    function GetWidth(): Integer;
    function GetHeight(): Integer;
    function GetFileName(): String;
    function GetIsInit(): Boolean;
    procedure GetCurrentPal(var aHighPal: HighPal);
    procedure GetOriginalPal(var aHighPal: HighPal);
    procedure SetCurrentPal(aHighPal: HighPal);
    procedure ResetCurrentPal();
    procedure SaveToTGA();
    procedure DrawToTGA(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
    procedure Close;
  end;

function PosLast(substr1,str1: widestring):Integer;

implementation

procedure TWasFile.Close;
begin
  Burn;
  Init;
end;

procedure TWasFile.Init();
begin
  Info.wfType := 0;
  Info.whSize := 0;
  Info.SpriteCount := 0;
  Info.FrameCount := 0;
  Info.MaxWidth := 0;
  Info.MaxHeight := 0;
  Info.Key_X := 0;
  Info.Key_Y := 0;

  Self.FName := '';
  Self.FSize := 0;

  Self.HeadDataSize := 0;
end;

procedure TWasFile.Burn();
var
  i: Integer;
begin
  for i:=Low(Data) to High(Data) do
  begin
    Data.Data := nil;
  end;
  Data := nil;
  FData := nil;

  HeadData := nil;
  
  fInitialized := false;
end;

constructor TWasFile.Create();
begin
  Init;
  fInitialized := false;
end;

destructor TWasFile.Destroy();
begin
  Burn;
end;

procedure TWasFile.DecodeFromStream(var Dest: TWasImage; Stream: TStream);
var
  StartPos: Int64;  // 文件在 Stream 中的 Offset
  LineOffset: array of Cardinal;
  x,y: Integer;
  tmp, tmp2: Byte;
  alpha: Byte;
  i: Integer;
  Width, Height: Integer;
begin
  StartPos := Stream.Position;
  Stream.Read(Dest.Info, SizeOf(Dest.Info));

  Width := Dest.Info.Width;
  Height := Dest.Info.Height;

  LineOffset := nil;
  SetLength(LineOffset, Height);
  Dest.Data := nil;
  SetLength(Dest.Data, Width * Height);

  for i:=Low(Dest.Data) to High(Dest.Data) do
  begin
    // 初始化Data,因为后面有跳过某些字节的操作
    Dest.Data.Alpha := $0;
    Dest.Data.Index := $0;
  end;

  Stream.Read(LineOffset[0], 4 * Height);

  for y:=0 to Height-1 do
  begin
    x := 0;
    Stream.Seek(StartPos + LineOffset[y], soFromBeginning);
    while (x < Width) do
    begin
      Stream.Read(tmp, 1);
      case (tmp and $C0) of
        $00:  // 00 - 透明色
        begin
          if (tmp and $20)>0 then
          begin
            tmp2 := tmp and $1F;  // alpha
            Stream.Read(tmp, 1);
            Dest.Data[y*Width+x].Index := tmp;
            Dest.Data[y*Width+x].Alpha := tmp2;
            Inc(x);
          end
          else if tmp<>0 then
          begin
            // 重复alpha像素的分支
            tmp2 := tmp and $1F;  // 次数
            Stream.Read(alpha, 1);
            alpha := alpha and $1F;
            Stream.Read(tmp, 1);
            for i:=1 to tmp2 do
            begin
              Dest.Data[y*Width+x].Alpha := alpha;
              Dest.Data[y*Width+x].Index := tmp;
              Inc(x);
            end;
          end
          else
          begin
            // tmp 是$0表示数据段结束
            if x>Width then
              raise Exception.Create('第'+IntToStr(y)+'行遇到错误数据啦!');
            x := Width;
          end;
        end;
        $40:  // 01 - 像素组
        begin
          tmp2 := tmp and $3F;
          for i:=1 to tmp2 do
          begin
            Stream.Read(tmp, 1);
            Dest.Data[y*Width+x].Alpha := 32;//$1F;
            Dest.Data[y*Width+x].Index := tmp;
            inc(x);
          end;
        end;
        $80:  // 10 - 重复n次
        begin
          tmp2 := tmp and $3F;
          Stream.Read(tmp, 1);
          for i:=1 to tmp2 do
          begin
            Dest.Data[y*Width+x].Alpha := 32;//$1F;
            Dest.Data[y*Width+x].Index := tmp;
            inc(x);
          end;
        end;
        $C0:  // 11 - 跳过n字节
        begin
          tmp2 := tmp and $3F;
          x := x + tmp2;
        end;
      end;  // end of case

      if x>Width then
        raise Exception.Create('第'+IntToStr(y)+'行遇到错误数据啦!');
    end;  // end of while
  end;
  LineOffset := nil;
end;

procedure TWasFile.LoadFromFile(const FileName: string);
var
  Stream: TStream;
  FileOffset: array of Cardinal;
  i: Integer;
begin
  Stream := TMemoryStream.Create;
  try
    TMemoryStream(Stream).LoadFromFile(FileName);
    Burn;
    Init;
    Stream.Read(Info, SizeOf(Info));
    if Info.wfType <> $5053 then
      raise Exception.Create('错误的文件标识!');
    if Info.whSize < $0C then
      raise Exception.Create('错误的文件版本,请与作者联系!')
    else if Info.whSize > $0C then
    begin
      // 当文件头大小大于$0C的时候
      HeadDataSize := Info.whSize - $0C;
      SetLength(HeadData, HeadDataSize);
      Stream.Read(HeadData[0], HeadDataSize);
    end;
    if (Info.SpriteCount < 1) or (Info.FrameCount < 1) then
      raise Exception.Create('错误的精灵数或帧数!');
    // 开始加载图片
    i := Info.SpriteCount * Info.FrameCount;
    SetLength(Data, i);
    SetLength(FileOffset, i);
    Stream.Read(OriginalPal[0], 512); // 高彩调色板
    Stream.Read(FileOffset[0], 4*i);  // 子文件偏移量

    for i:=Low(FileOffset) to High(FileOffset) do
    begin
      if FileOffset=0 then
      begin
        // 想不出更合适的办法了
        with Data do
        begin
          Info.Width := 1;
          Info.Height := 1;
          Info.Key_X := 0;
          Info.Key_Y := 0;
          SetLength(Data, 1);
          Data[0].Alpha := $0;
          Data[0].Index := $0;
        end;
      end
      else
      begin
        Stream.Seek(FileOffset+Info.whSize+4, soFromBeginning);
        DecodeFromStream(Data, Stream);
      end;
    end;

    FName := FileName;
    FSize := Stream.Size - $204 - Info.whSize;
    FData := nil;
    SetLength(FData, FSize);
    Stream.Seek($4+Info.whSize, soFromBeginning);
    Stream.Read(CurrentPal[0], $200);
    Stream.Read(FData[0], FSize);
    fInitialized := true;
  finally
    Stream.Free;
  end;
end;

procedure TWasFile.DrawByKey(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
var
  New_X: Integer;
  New_Y: Integer;
  New_Width: Integer;
  New_Height: Integer;
  New_Left: Integer;
  New_Top: Integer;

  i,j: Integer;
  pDest: PByteArray;
  Color: Word;
  Alpha: Byte;
begin
  if not fInitialized then
    raise Exception.Create('没加载图片,画什么啊!');
  if (Index<0) or (Index>(Info.SpriteCount * Info.FrameCount)) then
    raise Exception.Create('没有第'+IntToStr(Index)+'张图片,没法画!');

  // 裁减
  New_X := X - Data[Index].Info.Key_X;
  New_Y := Y - Data[Index].Info.Key_Y;
  New_Width := Data[Index].Info.Width;
  New_Height := Data[Index].Info.Height;
  New_Left := 0;
  New_Top := 0;

  if (New_X > Dest.Width) or (New_Y > Dest.Height) then
    exit;
  if (New_X + New_Width) > Dest.Width then
    New_Width := Dest.Width - New_X;
  if (New_Y + New_Height) > Dest.Height then
    New_Height := Dest.Height - New_Y;

  if New_X < 0 then
  begin
    New_Left := -New_X;
    New_X := 0;
  end;
  if New_Y < 0 then
  begin
    New_Top := -New_Y;
    New_Y := 0
  end;

  for i:=New_Top to New_Height-1 do
  begin
    pDest := Dest.ScanLine[New_Y+i-New_Top];
    Inc(LongWord(pDest), 3*New_X);
    for j:=New_Left to New_Width-1 do
    begin
      Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];
      Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;
      pDest[0] := (((Color and $001F) shl 3) - pDest[0]) * Alpha div 32 + pDest[0];
      pDest[1] := (((Color and $07E0) shr 3) - pDest[1]) * Alpha div 32 + pDest[1];
      pDest[2] := (((Color and $F800) shr 8) - pDest[2]) * Alpha div 32 + pDest[2];
      Inc(LongWord(pDest), 3);
    end;
  end;
end;

procedure TWasFile.Draw(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
begin
  DrawByKey(Dest, X+Data[Index].Info.Key_X, Y+Data[Index].Info.Key_Y, Index);
end;

procedure TWasFile.SaveToFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmCreate);
  try
    Stream.Write(Info, SizeOf(Info));
    Stream.Write(HeadData[0], HeadDataSize);
    Stream.Write(CurrentPal[0], $200);
    Stream.Write(FData[0], FSize);
  finally
    Stream.Free;
  end;
end;

function TWasFile.GetSpriteCount(): Integer;
begin
  Result := Info.SpriteCount;
end;

function TWasFile.GetFrameCount(): Integer;
begin
  Result := Info.FrameCount;
end;

function TWasFile.GetWidth(): Integer;
begin
  Result := Info.MaxWidth;
end;

function TWasFile.GetHeight(): Integer;
begin
  Result := Info.MaxHeight;
end;

function TWasFile.GetFileName(): String;
begin
  Result := FName;
end;

function TWasFile.GetIsInit(): Boolean;
begin
  Result := fInitialized;
end;

procedure TWasFile.GetCurrentPal(var aHighPal: HighPal);
var
  i: Integer;
begin
  for i:=0 to 255 do
  begin
    aHighPal := CurrentPal;
  end;
end;

procedure TWasFile.GetOriginalPal(var aHighPal: HighPal);
var
  i: Integer;
begin
  for i:=0 to 255 do
  begin
    aHighPal := OriginalPal;
  end;
end;

procedure TWasFile.SetCurrentPal(aHighPal: HighPal);
var
  i: Integer;
begin
  for i:=0 to 255 do
  begin
    CurrentPal := aHighPal;
  end;
end;

procedure TWasFile.ResetCurrentPal();
var
  i: Integer;
begin
  for i:=0 to 255 do
  begin
    CurrentPal := OriginalPal;
  end;
end;

procedure TWasFile.SaveToTGA();
var
  fs1: TStream;
  i,l,x,y: Integer;
  path: widestring;
  FileName: widestring;
  tmp: Byte;
  bufbmp: TBitmap;
  pDest: PByteArray;
begin
  FileName := FName;
  i := PosLast('.', FileName);
  path := LeftStr(FileName, i-1);

  bufbmp := TBitmap.Create;
  bufbmp.PixelFormat := pf32bit;
  bufbmp.Width := Info.MaxWidth;
  bufbmp.Height := Info.MaxHeight;

  for i:=Low(Data) to High(Data) do
  begin
    FileName := path + Format('%x%.3d.tga',[(i div Info.FrameCount),(i mod Info.FrameCount)]);
    fs1 := TFileStream.Create(FileName, fmCreate);
    l := $00020000;
    fs1.Write(l, 4);
    l := $0;
    fs1.Write(l, 4);
    fs1.Write(l, 4);
    fs1.Write(Info.MaxWidth, 2);
    fs1.Write(Info.MaxHeight, 2);
    tmp := $20;
    fs1.Write(tmp, 1);
    tmp := $08; // 原点在左下用$08,原点在左上用$28;
    fs1.Write(tmp, 1);

    // 清空bufbmp
    for y:=0 to bufbmp.Height-1 do
    begin
      pDest := bufbmp.ScanLine[y];
      for x:=0 to bufbmp.Width-1 do
      begin
        pDest[0]:=0;
        pDest[1]:=0;
        pDest[2]:=0;
        pDest[3]:=0;
        Inc(LongWord(pDest), 4);
      end;
    end;

    DrawToTGA(bufbmp, Info.Key_X, Info.Key_Y, i);

    for y:=bufbmp.Height-1 downto 0 do
    begin
      pDest := bufbmp.ScanLine[y];
      fs1.Write(pDest[0], 4*bufbmp.Width);
    end;
    
    fs1.Free;
  end;
  bufbmp := nil;
end;

function PosLast(substr1,str1: widestring):Integer;
var
  str2: widestring;
  i,l: Integer;
  sum: Integer;
begin
  sum := 0;
  str2 := str1;
//  i := Pos('\',str1);
  i := Pos(substr1, str2);
  while i<>0 do
  begin
    l := Length(str2);
    sum := sum + i;
    str2 := RightStr(str2, l-i);
    i := Pos(substr1, str2);
  end;
  Result := sum;
end;

// 仅为TGA服务
procedure TWasFile.DrawToTGA(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
var
  New_X: Integer;
  New_Y: Integer;
  New_Width: Integer;
  New_Height: Integer;
  New_Left: Integer;
  New_Top: Integer;

  i,j: Integer;
  pDest: PByteArray;
  Color: Word;
  Alpha: Byte;
begin
  if not fInitialized then
    raise Exception.Create('没加载图片,画什么啊!');
  if (Index<0) or (Index>(Info.SpriteCount * Info.FrameCount)) then
    raise Exception.Create('没有第'+IntToStr(Index)+'张图片,没法画!');

  // 裁减
  New_X := X - Data[Index].Info.Key_X;
  New_Y := Y - Data[Index].Info.Key_Y;
  New_Width := Data[Index].Info.Width;
  New_Height := Data[Index].Info.Height;
  New_Left := 0;
  New_Top := 0;

  if (New_X > Dest.Width) or (New_Y > Dest.Height) then
    exit;
  if (New_X + New_Width) > Dest.Width then
    New_Width := Dest.Width - New_X;
  if (New_Y + New_Height) > Dest.Height then
    New_Height := Dest.Height - New_Y;

  if New_X < 0 then
  begin
    New_Left := -New_X;
    New_X := 0;
  end;
  if New_Y < 0 then
  begin
    New_Top := -New_Y;
    New_Y := 0
  end;

  for i:=New_Top to New_Height-1 do
  begin
    pDest := Dest.ScanLine[New_Y+i-New_Top];
    Inc(LongWord(pDest), 4*New_X);
    for j:=New_Left to New_Width-1 do
    begin
      Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];
      Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;
      if Alpha=0 then
      begin
        // 0号调色板不一定是黑色,为了photoshop里显示的效果
        // 强制写入黑色
        pDest[0] := 0;
        pDest[1] := 0;
        pDest[2] := 0;
        pDest[3] := 0;
      end
      else if Alpha=32 then
      begin
        pDest[0] := ((Color and $001F) shl 3) and $F8;
        pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);
        pDest[1] := ((Color and $07E0) shr 3) and $FC;
        pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);
        pDest[2] := ((Color and $F800) shr 8) and $F8;
        pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);
        pDest[3] := 255;
      end
      else
      begin
        // alpha 像素导出处
        // 貌似wascompress是先合并再导出,而不是直接导出,所以发黑
{        pDest[0] := (((Color and $001F) shl 3) * Alpha div 32) and $F8;
        pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);
        pDest[1] := (((Color and $07E0) shr 3) * Alpha div 32) and $FC;
        pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);
        pDest[2] := (((Color and $F800) shr 8) * Alpha div 32) and $F8;
        pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);}

        // 正常的TGA导出
        pDest[0] := ((Color and $001F) shl 3) and $F8;
        pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);
        pDest[1] := ((Color and $07E0) shr 3) and $FC;
        pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);
        pDest[2] := ((Color and $F800) shr 8) and $F8;
        pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);
        pDest[3]:=Alpha*8;
      end;
      Inc(LongWord(pDest), 4);
    end;
  end;
end;


end.
回复 支持 反对

使用道具 举报

结帖率:67% (8/12)

签到天数: 14 天

 楼主| 发表于 昨天 15:48 | 显示全部楼层   山东省*
unit was;  interface  uses   SysUtils, Classes, Graphics, Dialogs, StrUtils;  type   TWasPixel = record     Alpha: Byte;     Index: Byte;   end;    TWasImageInfo = record     Key_X: Integer;     Key_Y: Integer;     Width: Integer;     Height: Integer;   end;    TWasImage = record     Info: TWasImageInfo;     Data: array of TWasPixel;   end;    TWasFileInfo = record     wfType: Word;     whSize: Word;     SpriteCount: Word;     FrameCount: Word;     MaxWidth: Word;     MaxHeight: Word;     Key_X: Word;     Key_Y: Word;   end;    HighPal = array [0..255] of Word;      TWasFile = class   private     // 图片信息     Info: TWasFileInfo;     Data: array of TWasImage;     HeadData: array of Byte;  // 存储多余的文件头     HeadDataSize: Integer;      // 2个调色板     OriginalPal: array [0..255] of Word;     CurrentPal: array [0..255] of Word;      // 原始文件     FName: string;     FSize: Cardinal;     FData: array of Byte;     fInitialized: Boolean;      // xxxxxxxxxxxxxxxxxx     procedure DecodeFromStream(var Dest: TWasImage; Stream: TStream);     procedure Init();     procedure Burn();   public     constructor Create();     destructor Destroy(); override;     // 相关方法     procedure LoadFromFile(const FileName: string);     procedure SaveToFile(const FileName: string);     procedure Draw(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);     procedure DrawByKey(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);     function GetSpriteCount(): Integer;     function GetFrameCount(): Integer;     function GetWidth(): Integer;     function GetHeight(): Integer;     function GetFileName(): String;     function GetIsInit(): Boolean;     procedure GetCurrentPal(var aHighPal: HighPal);     procedure GetOriginalPal(var aHighPal: HighPal);     procedure SetCurrentPal(aHighPal: HighPal);     procedure ResetCurrentPal();     procedure SaveToTGA();     procedure DrawToTGA(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);     procedure Close;   end;  function PosLast(substr1,str1: widestring):Integer;  implementation  procedure TWasFile.Close; begin   Burn;   Init; end;  procedure TWasFile.Init(); begin   Info.wfType := 0;   Info.whSize := 0;   Info.SpriteCount := 0;   Info.FrameCount := 0;   Info.MaxWidth := 0;   Info.MaxHeight := 0;   Info.Key_X := 0;   Info.Key_Y := 0;    Self.FName := '';   Self.FSize := 0;    Self.HeadDataSize := 0; end;  procedure TWasFile.Burn(); var   i: Integer; begin   for i:=Low(Data) to High(Data) do   begin     Data[i].Data := nil;   end;   Data := nil;   FData := nil;    HeadData := nil;      fInitialized := false; end;  constructor TWasFile.Create(); begin   Init;   fInitialized := false; end;  destructor TWasFile.Destroy(); begin   Burn; end;  procedure TWasFile.DecodeFromStream(var Dest: TWasImage; Stream: TStream); var   StartPos: Int64;  // 文件在 Stream 中的 Offset   LineOffset: array of Cardinal;   x,y: Integer;   tmp, tmp2: Byte;   alpha: Byte;   i: Integer;   Width, Height: Integer; begin   StartPos := Stream.Position;   Stream.Read(Dest.Info, SizeOf(Dest.Info));    Width := Dest.Info.Width;   Height := Dest.Info.Height;    LineOffset := nil;   SetLength(LineOffset, Height);   Dest.Data := nil;   SetLength(Dest.Data, Width * Height);    for i:=Low(Dest.Data) to High(Dest.Data) do   begin     // 初始化Data,因为后面有跳过某些字节的操作     Dest.Data[i].Alpha := $0;     Dest.Data[i].Index := $0;   end;    Stream.Read(LineOffset[0], 4 * Height);    for y:=0 to Height-1 do   begin     x := 0;     Stream.Seek(StartPos + LineOffset[y], soFromBeginning);     while (x < Width) do     begin       Stream.Read(tmp, 1);       case (tmp and $C0) of         $00:  // 00 - 透明色         begin           if (tmp and $20)>0 then           begin             tmp2 := tmp and $1F;  // alpha             Stream.Read(tmp, 1);             Dest.Data[y*Width+x].Index := tmp;             Dest.Data[y*Width+x].Alpha := tmp2;             Inc(x);           end           else if tmp<>0 then           begin             // 重复alpha像素的分支             tmp2 := tmp and $1F;  // 次数             Stream.Read(alpha, 1);             alpha := alpha and $1F;             Stream.Read(tmp, 1);             for i:=1 to tmp2 do             begin               Dest.Data[y*Width+x].Alpha := alpha;               Dest.Data[y*Width+x].Index := tmp;               Inc(x);             end;           end           else           begin             // tmp 是$0表示数据段结束             if x>Width then               raise Exception.Create('第'+IntToStr(y)+'行遇到错误数据啦!');             x := Width;           end;         end;         $40:  // 01 - 像素组         begin           tmp2 := tmp and $3F;           for i:=1 to tmp2 do           begin             Stream.Read(tmp, 1);             Dest.Data[y*Width+x].Alpha := 32;//$1F;             Dest.Data[y*Width+x].Index := tmp;             inc(x);           end;         end;         $80:  // 10 - 重复n次         begin           tmp2 := tmp and $3F;           Stream.Read(tmp, 1);           for i:=1 to tmp2 do           begin             Dest.Data[y*Width+x].Alpha := 32;//$1F;             Dest.Data[y*Width+x].Index := tmp;             inc(x);           end;         end;         $C0:  // 11 - 跳过n字节         begin           tmp2 := tmp and $3F;           x := x + tmp2;         end;       end;  // end of case        if x>Width then         raise Exception.Create('第'+IntToStr(y)+'行遇到错误数据啦!');     end;  // end of while   end;   LineOffset := nil; end;  procedure TWasFile.LoadFromFile(const FileName: string); var   Stream: TStream;   FileOffset: array of Cardinal;   i: Integer; begin   Stream := TMemoryStream.Create;   try     TMemoryStream(Stream).LoadFromFile(FileName);     Burn;     Init;     Stream.Read(Info, SizeOf(Info));     if Info.wfType <> $5053 then       raise Exception.Create('错误的文件标识!');     if Info.whSize < $0C then       raise Exception.Create('错误的文件版本,请与作者联系!')     else if Info.whSize > $0C then     begin       // 当文件头大小大于$0C的时候       HeadDataSize := Info.whSize - $0C;       SetLength(HeadData, HeadDataSize);       Stream.Read(HeadData[0], HeadDataSize);     end;     if (Info.SpriteCount < 1) or (Info.FrameCount < 1) then       raise Exception.Create('错误的精灵数或帧数!');     // 开始加载图片     i := Info.SpriteCount * Info.FrameCount;     SetLength(Data, i);     SetLength(FileOffset, i);     Stream.Read(OriginalPal[0], 512); // 高彩调色板     Stream.Read(FileOffset[0], 4*i);  // 子文件偏移量      for i:=Low(FileOffset) to High(FileOffset) do     begin       if FileOffset[i]=0 then       begin         // 想不出更合适的办法了         with Data[i] do         begin           Info.Width := 1;           Info.Height := 1;           Info.Key_X := 0;           Info.Key_Y := 0;           SetLength(Data, 1);           Data[0].Alpha := $0;           Data[0].Index := $0;         end;       end       else       begin         Stream.Seek(FileOffset[i]+Info.whSize+4, soFromBeginning);         DecodeFromStream(Data[i], Stream);       end;     end;      FName := FileName;     FSize := Stream.Size - $204 - Info.whSize;     FData := nil;     SetLength(FData, FSize);     Stream.Seek($4+Info.whSize, soFromBeginning);     Stream.Read(CurrentPal[0], $200);     Stream.Read(FData[0], FSize);     fInitialized := true;   finally     Stream.Free;   end; end;  procedure TWasFile.DrawByKey(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer); var   New_X: Integer;   New_Y: Integer;   New_Width: Integer;   New_Height: Integer;   New_Left: Integer;   New_Top: Integer;    i,j: Integer;   pDest: PByteArray;   Color: Word;   Alpha: Byte; begin   if not fInitialized then     raise Exception.Create('没加载图片,画什么啊!');   if (Index<0) or (Index>(Info.SpriteCount * Info.FrameCount)) then     raise Exception.Create('没有第'+IntToStr(Index)+'张图片,没法画!');    // 裁减   New_X := X - Data[Index].Info.Key_X;   New_Y := Y - Data[Index].Info.Key_Y;   New_Width := Data[Index].Info.Width;   New_Height := Data[Index].Info.Height;   New_Left := 0;   New_Top := 0;    if (New_X > Dest.Width) or (New_Y > Dest.Height) then     exit;   if (New_X + New_Width) > Dest.Width then     New_Width := Dest.Width - New_X;   if (New_Y + New_Height) > Dest.Height then     New_Height := Dest.Height - New_Y;    if New_X < 0 then   begin     New_Left := -New_X;     New_X := 0;   end;   if New_Y < 0 then   begin     New_Top := -New_Y;     New_Y := 0   end;    for i:=New_Top to New_Height-1 do   begin     pDest := Dest.ScanLine[New_Y+i-New_Top];     Inc(LongWord(pDest), 3*New_X);     for j:=New_Left to New_Width-1 do     begin       Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];       Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;       pDest[0] := (((Color and $001F) shl 3) - pDest[0]) * Alpha div 32 + pDest[0];       pDest[1] := (((Color and $07E0) shr 3) - pDest[1]) * Alpha div 32 + pDest[1];       pDest[2] := (((Color and $F800) shr 8) - pDest[2]) * Alpha div 32 + pDest[2];       Inc(LongWord(pDest), 3);     end;   end; end;  procedure TWasFile.Draw(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer); begin   DrawByKey(Dest, X+Data[Index].Info.Key_X, Y+Data[Index].Info.Key_Y, Index); end;  procedure TWasFile.SaveToFile(const FileName: string); var   Stream: TStream; begin   Stream := TFileStream.Create(FileName, fmCreate);   try     Stream.Write(Info, SizeOf(Info));     Stream.Write(HeadData[0], HeadDataSize);     Stream.Write(CurrentPal[0], $200);     Stream.Write(FData[0], FSize);   finally     Stream.Free;   end; end;  function TWasFile.GetSpriteCount(): Integer; begin   Result := Info.SpriteCount; end;  function TWasFile.GetFrameCount(): Integer; begin   Result := Info.FrameCount; end;  function TWasFile.GetWidth(): Integer; begin   Result := Info.MaxWidth; end;  function TWasFile.GetHeight(): Integer; begin   Result := Info.MaxHeight; end;  function TWasFile.GetFileName(): String; begin   Result := FName; end;  function TWasFile.GetIsInit(): Boolean; begin   Result := fInitialized; end;  procedure TWasFile.GetCurrentPal(var aHighPal: HighPal); var   i: Integer; begin   for i:=0 to 255 do   begin     aHighPal[i] := CurrentPal[i];   end; end;  procedure TWasFile.GetOriginalPal(var aHighPal: HighPal); var   i: Integer; begin   for i:=0 to 255 do   begin     aHighPal[i] := OriginalPal[i];   end; end;  procedure TWasFile.SetCurrentPal(aHighPal: HighPal); var   i: Integer; begin   for i:=0 to 255 do   begin     CurrentPal[i] := aHighPal[i];   end; end;  procedure TWasFile.ResetCurrentPal(); var   i: Integer; begin   for i:=0 to 255 do   begin     CurrentPal[i] := OriginalPal[i];   end; end;  procedure TWasFile.SaveToTGA(); var   fs1: TStream;   i,l,x,y: Integer;   path: widestring;   FileName: widestring;   tmp: Byte;   bufbmp: TBitmap;   pDest: PByteArray; begin   FileName := FName;   i := PosLast('.', FileName);   path := LeftStr(FileName, i-1);    bufbmp := TBitmap.Create;   bufbmp.PixelFormat := pf32bit;   bufbmp.Width := Info.MaxWidth;   bufbmp.Height := Info.MaxHeight;    for i:=Low(Data) to High(Data) do   begin     FileName := path + Format('%x%.3d.tga',[(i div Info.FrameCount),(i mod Info.FrameCount)]);     fs1 := TFileStream.Create(FileName, fmCreate);     l := $00020000;     fs1.Write(l, 4);     l := $0;     fs1.Write(l, 4);     fs1.Write(l, 4);     fs1.Write(Info.MaxWidth, 2);     fs1.Write(Info.MaxHeight, 2);     tmp := $20;     fs1.Write(tmp, 1);     tmp := $08; // 原点在左下用$08,原点在左上用$28;     fs1.Write(tmp, 1);      // 清空bufbmp     for y:=0 to bufbmp.Height-1 do     begin       pDest := bufbmp.ScanLine[y];       for x:=0 to bufbmp.Width-1 do       begin         pDest[0]:=0;         pDest[1]:=0;         pDest[2]:=0;         pDest[3]:=0;         Inc(LongWord(pDest), 4);       end;     end;      DrawToTGA(bufbmp, Info.Key_X, Info.Key_Y, i);      for y:=bufbmp.Height-1 downto 0 do     begin       pDest := bufbmp.ScanLine[y];       fs1.Write(pDest[0], 4*bufbmp.Width);     end;          fs1.Free;   end;   bufbmp := nil; end;  function PosLast(substr1,str1: widestring):Integer; var   str2: widestring;   i,l: Integer;   sum: Integer; begin   sum := 0;   str2 := str1; //  i := Pos('\',str1);   i := Pos(substr1, str2);   while i<>0 do   begin     l := Length(str2);     sum := sum + i;     str2 := RightStr(str2, l-i);     i := Pos(substr1, str2);   end;   Result := sum; end;  // 仅为TGA服务 procedure TWasFile.DrawToTGA(Dest: TBitmap; X: Integer; Y: Integer; Index: Integer); var   New_X: Integer;   New_Y: Integer;   New_Width: Integer;   New_Height: Integer;   New_Left: Integer;   New_Top: Integer;    i,j: Integer;   pDest: PByteArray;   Color: Word;   Alpha: Byte; begin   if not fInitialized then     raise Exception.Create('没加载图片,画什么啊!');   if (Index<0) or (Index>(Info.SpriteCount * Info.FrameCount)) then     raise Exception.Create('没有第'+IntToStr(Index)+'张图片,没法画!');    // 裁减   New_X := X - Data[Index].Info.Key_X;   New_Y := Y - Data[Index].Info.Key_Y;   New_Width := Data[Index].Info.Width;   New_Height := Data[Index].Info.Height;   New_Left := 0;   New_Top := 0;    if (New_X > Dest.Width) or (New_Y > Dest.Height) then     exit;   if (New_X + New_Width) > Dest.Width then     New_Width := Dest.Width - New_X;   if (New_Y + New_Height) > Dest.Height then     New_Height := Dest.Height - New_Y;    if New_X < 0 then   begin     New_Left := -New_X;     New_X := 0;   end;   if New_Y < 0 then   begin     New_Top := -New_Y;     New_Y := 0   end;    for i:=New_Top to New_Height-1 do   begin     pDest := Dest.ScanLine[New_Y+i-New_Top];     Inc(LongWord(pDest), 4*New_X);     for j:=New_Left to New_Width-1 do     begin       Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];       Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;       if Alpha=0 then       begin         // 0号调色板不一定是黑色,为了photoshop里显示的效果         // 强制写入黑色         pDest[0] := 0;         pDest[1] := 0;         pDest[2] := 0;         pDest[3] := 0;       end       else if Alpha=32 then       begin         pDest[0] := ((Color and $001F) shl 3) and $F8;         pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);         pDest[1] := ((Color and $07E0) shr 3) and $FC;         pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);         pDest[2] := ((Color and $F800) shr 8) and $F8;         pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);         pDest[3] := 255;       end       else       begin         // alpha 像素导出处         // 貌似wascompress是先合并再导出,而不是直接导出,所以发黑 {        pDest[0] := (((Color and $001F) shl 3) * Alpha div 32) and $F8;         pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);         pDest[1] := (((Color and $07E0) shr 3) * Alpha div 32) and $FC;         pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);         pDest[2] := (((Color and $F800) shr 8) * Alpha div 32) and $F8;         pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);}          // 正常的TGA导出         pDest[0] := ((Color and $001F) shl 3) and $F8;         pDest[0] := pDest[0] or ((pDest[0] shr 3) and 7);         pDest[1] := ((Color and $07E0) shr 3) and $FC;         pDest[1] := pDest[1] or ((pDest[1] shr 2) and 3);         pDest[2] := ((Color and $F800) shr 8) and $F8;         pDest[2] := pDest[2] or ((pDest[2] shr 3) and 7);         pDest[3]:=Alpha*8;       end;       Inc(LongWord(pDest), 4);     end;   end; end;   end.
回复 支持 反对

使用道具 举报

结帖率:67% (8/12)

签到天数: 14 天

 楼主| 发表于 昨天 14:16 | 显示全部楼层   山东省*
  
unit was;
interface
uses
SysUtils, Classes, Graphics, Dialogs, StrUtils;
type
TWasPixel = record
Alpha: Byte;
Index: Byte;
end;
TWasImageInfo = record
Key_X: Integer;
Key_Y: Integer;
Width: Integer;
Height: Integer;
end;
TWasImage = record
Info: TWasImageInfo;
Data: array of TWasPixel;
end;
TWasFileInfo = record
wfType: Word;
whSize: Word;
SpriteCount: Word;
FrameCount: Word;
MaxWidth: Word;
MaxHeight: Word;
Key_X: Word;
Key_Y: Word;
end;
HighPal = array [0..255] of Word;

TWasFile = class
private
// 图片信息
Info: TWasFileInfo;
Data: array of TWasImage;
HeadData: array of Byte;  // 存储多余的文件头
HeadDataSize: Integer;
// 2个调色板
OriginalPal: array [0..255] of Word;
CurrentPal: array [0..255] of Word;
// 原始文件
FName: string;
FSize: Cardinal;
FData: array of Byte;
fInitialized: Boolean;
// xxxxxxxxxxxxxxxxxx
procedure DecodeFromStream (var Dest: TWasImage; Stream: TStream);
procedure Init ();
procedure Burn ();
public
constructor Create ();
destructor Destroy (); override;
// 相关方法
procedure LoadFromFile (const FileName: string);
procedure SaveToFile (const FileName: string);
procedure Draw (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
procedure DrawByKey (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
function GetSpriteCount (): Integer;
function GetFrameCount (): Integer;
function GetWidth (): Integer;
function GetHeight (): Integer;
function GetFileName (): String;
function GetIsInit (): Boolean;
procedure GetCurrentPal (var aHighPal: HighPal);
procedure GetOriginalPal (var aHighPal: HighPal);
procedure SetCurrentPal (aHighPal: HighPal);
procedure ResetCurrentPal ();
procedure SaveToTGA ();
procedure DrawToTGA (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
procedure Close;
end;
function PosLast (substr1,str1: widestring):Integer;
implementation
procedure TWasFile.Close;
begin
Burn;
Init;
end;
procedure TWasFile.Init ();
begin
Info.wfType := 0;
Info.whSize := 0;
Info.SpriteCount := 0;
Info.FrameCount := 0;
Info.MaxWidth := 0;
Info.MaxHeight := 0;
Info.Key_X := 0;
Info.Key_Y := 0;
Self.FName := ' ';
Self.FSize := 0;
Self.HeadDataSize := 0;
end;
procedure TWasFile.Burn ();
var
i: Integer;
begin
for i:=Low (Data) to High (Data) do
begin
Data[i].Data := nil;
end;
Data := nil;
FData := nil;
HeadData := nil;

fInitialized := false;
end;
constructor TWasFile.Create ();
begin
Init;
fInitialized := false;
end;
destructor TWasFile.Destroy ();
begin
Burn;
end;
procedure TWasFile.DecodeFromStream (var Dest: TWasImage; Stream: TStream);
var
StartPos: Int64;  // 文件在 Stream 中的 Offset
LineOffset: array of Cardinal;
x,y: Integer;
tmp, tmp2: Byte;
alpha: Byte;
i: Integer;
Width, Height: Integer;
begin
StartPos := Stream.Position;
Stream.Read (Dest.Info, SizeOf (Dest.Info));
Width := Dest.Info.Width;
Height := Dest.Info.Height;
LineOffset := nil;
SetLength (LineOffset, Height);
Dest.Data := nil;
SetLength (Dest.Data, Width * Height);
for i:=Low (Dest.Data) to High (Dest.Data) do
begin
// 初始化Data,因为后面有跳过某些字节的操作
Dest.Data[i].Alpha := $0;
Dest.Data[i].Index := $0;
end;
Stream.Read (LineOffset[0], 4 * Height);
for y:=0 to Height-1 do
begin
x := 0;
Stream.Seek (StartPos + LineOffset[y], soFromBeginning);
while (x < Width) do
begin
Stream.Read (tmp, 1);
case (tmp and $C0) of
$00:  // 00 - 透明色
begin
if (tmp and $20)>0 then
begin
tmp2 := tmp and $1F;  // alpha
Stream.Read (tmp, 1);
Dest.Data[y*Width+x].Index := tmp;
Dest.Data[y*Width+x].Alpha := tmp2;
Inc (x);
end
else if tmp<>0 then
begin
// 重复alpha像素的分支
tmp2 := tmp and $1F;  // 次数
Stream.Read (alpha, 1);
alpha := alpha and $1F;
Stream.Read (tmp, 1);
for i:=1 to tmp2 do
begin
Dest.Data[y*Width+x].Alpha := alpha;
Dest.Data[y*Width+x].Index := tmp;
Inc (x);
end;
end
else
begin
// tmp 是$0表示数据段结束
if x>Width then
raise Exception.Create ( ' 第'+IntToStr(y)+'行遇到错误数据啦!');
x := Width;
end;
end;
$40:  // 01 - 像素组
begin
tmp2 := tmp and $3F;
for i:=1 to tmp2 do
begin
Stream.Read (tmp, 1);
Dest.Data[y*Width+x].Alpha := 32;//$1F;
Dest.Data[y*Width+x].Index := tmp;
inc (x);
end;
end;
$80:  // 10 - 重复n次
begin
tmp2 := tmp and $3F;
Stream.Read (tmp, 1);
for i:=1 to tmp2 do
begin
Dest.Data[y*Width+x].Alpha := 32;//$1F;
Dest.Data[y*Width+x].Index := tmp;
inc (x);
end;
end;
$C0:  // 11 - 跳过n字节
begin
tmp2 := tmp and $3F;
x := x + tmp2;
end;
end;  // end of case
if x>Width then
raise Exception.Create ( ' 第'+IntToStr(y)+'行遇到错误数据啦!');
end;  // end of while
end;
LineOffset := nil;
end;
procedure TWasFile.LoadFromFile (const FileName: string);
var
Stream: TStream;
FileOffset: array of Cardinal;
i: Integer;
begin
Stream := TMemoryStream.Create;
try
TMemoryStream (Stream).LoadFromFile (FileName);
Burn;
Init;
Stream.Read (Info, SizeOf (Info));
if Info.wfType <> $5053 then
raise Exception.Create ( ' 错误的文件标识!');
if Info.whSize < $0C then
raise Exception.Create ( ' 错误的文件版本,请与作者联系!')
else if Info.whSize > $0C then
begin
// 当文件头大小大于$0C的时候
HeadDataSize := Info.whSize - $0C;
SetLength (HeadData, HeadDataSize);
Stream.Read (HeadData[0], HeadDataSize);
end;
if (Info.SpriteCount < 1) or (Info.FrameCount < 1) then
raise Exception.Create ( ' 错误的精灵数或帧数!');
// 开始加载图片
i := Info.SpriteCount * Info.FrameCount;
SetLength (Data, i);
SetLength (FileOffset, i);
Stream.Read (OriginalPal[0], 512); // 高彩调色板
Stream.Read (FileOffset[0], 4*i);  // 子文件偏移量
for i:=Low (FileOffset) to High (FileOffset) do
begin
if FileOffset[i]=0 then
begin
// 想不出更合适的办法了
with Data[i] do
begin
Info.Width := 1;
Info.Height := 1;
Info.Key_X := 0;
Info.Key_Y := 0;
SetLength (Data, 1);
Data[0].Alpha := $0;
Data[0].Index := $0;
end;
end
else
begin
Stream.Seek (FileOffset[i]+Info.whSize+4, soFromBeginning);
DecodeFromStream (Data[i], Stream);
end;
end;
FName := FileName;
FSize := Stream.Size - $204 - Info.whSize;
FData := nil;
SetLength (FData, FSize);
Stream.Seek ($4+Info.whSize, soFromBeginning);
Stream.Read (CurrentPal[0], $200);
Stream.Read (FData[0], FSize);
fInitialized := true;
finally
Stream.Free;
end;
end;
procedure TWasFile.DrawByKey (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
var
New_X: Integer;
New_Y: Integer;
New_Width: Integer;
New_Height: Integer;
New_Left: Integer;
New_Top: Integer;
i,j: Integer;
pDest: PByteArray;
Color: Word;
Alpha: Byte;
begin
if not fInitialized then
raise Exception.Create ( ' 没加载图片,画什么啊!');
if (Index<0) or (Index> (Info.SpriteCount * Info.FrameCount)) then
raise Exception.Create ( ' 没有第'+IntToStr(Index)+'张图片,没法画!');
// 裁减
New_X := X - Data[Index].Info.Key_X;
New_Y := Y - Data[Index].Info.Key_Y;
New_Width := Data[Index].Info.Width;
New_Height := Data[Index].Info.Height;
New_Left := 0;
New_Top := 0;
if (New_X > Dest.Width) or (New_Y > Dest.Height) then
exit;
if (New_X + New_Width) > Dest.Width then
New_Width := Dest.Width - New_X;
if (New_Y + New_Height) > Dest.Height then
New_Height := Dest.Height - New_Y;
if New_X < 0 then
begin
New_Left := -New_X;
New_X := 0;
end;
if New_Y < 0 then
begin
New_Top := -New_Y;
New_Y := 0
end;
for i:=New_Top to New_Height-1 do
begin
pDest := Dest.ScanLine[New_Y+i-New_Top];
Inc (LongWord (pDest), 3*New_X);
for j:=New_Left to New_Width-1 do
begin
Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];
Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;
pDest[0] := ( ( (Color and $001F) shl 3) - pDest[0]) * Alpha div 32 + pDest[0];
pDest[1] := ( ( (Color and $07E0) shr 3) - pDest[1]) * Alpha div 32 + pDest[1];
pDest[2] := ( ( (Color and $F800) shr 8) - pDest[2]) * Alpha div 32 + pDest[2];
Inc (LongWord (pDest), 3);
end;
end;
end;
procedure TWasFile.Draw (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
begin
DrawByKey (Dest, X+Data[Index].Info.Key_X, Y+Data[Index].Info.Key_Y, Index);
end;
procedure TWasFile.SaveToFile (const FileName: string);
var
Stream: TStream;
begin
Stream := TFileStream.Create (FileName, fmCreate);
try
Stream.Write (Info, SizeOf (Info));
Stream.Write (HeadData[0], HeadDataSize);
Stream.Write (CurrentPal[0], $200);
Stream.Write (FData[0], FSize);
finally
Stream.Free;
end;
end;
function TWasFile.GetSpriteCount (): Integer;
begin
Result := Info.SpriteCount;
end;
function TWasFile.GetFrameCount (): Integer;
begin
Result := Info.FrameCount;
end;
function TWasFile.GetWidth (): Integer;
begin
Result := Info.MaxWidth;
end;
function TWasFile.GetHeight (): Integer;
begin
Result := Info.MaxHeight;
end;
function TWasFile.GetFileName (): String;
begin
Result := FName;
end;
function TWasFile.GetIsInit (): Boolean;
begin
Result := fInitialized;
end;
procedure TWasFile.GetCurrentPal (var aHighPal: HighPal);
var
i: Integer;
begin
for i:=0 to 255 do
begin
aHighPal[i] := CurrentPal[i];
end;
end;
procedure TWasFile.GetOriginalPal (var aHighPal: HighPal);
var
i: Integer;
begin
for i:=0 to 255 do
begin
aHighPal[i] := OriginalPal[i];
end;
end;
procedure TWasFile.SetCurrentPal (aHighPal: HighPal);
var
i: Integer;
begin
for i:=0 to 255 do
begin
CurrentPal[i] := aHighPal[i];
end;
end;
procedure TWasFile.ResetCurrentPal ();
var
i: Integer;
begin
for i:=0 to 255 do
begin
CurrentPal[i] := OriginalPal[i];
end;
end;
procedure TWasFile.SaveToTGA ();
var
fs1: TStream;
i,l,x,y: Integer;
path: widestring;
FileName: widestring;
tmp: Byte;
bufbmp: TBitmap;
pDest: PByteArray;
begin
FileName := FName;
i := PosLast ( ' .', FileName);
path := LeftStr (FileName, i-1);
bufbmp := TBitmap.Create;
bufbmp.PixelFormat := pf32bit;
bufbmp.Width := Info.MaxWidth;
bufbmp.Height := Info.MaxHeight;
for i:=Low (Data) to High (Data) do
begin
FileName := path + Format ( ' %x%.3d.tga',[(i div Info.FrameCount),(i mod Info.FrameCount)]);
fs1 := TFileStream.Create (FileName, fmCreate);
l := $00020000;
fs1.Write (l, 4);
l := $0;
fs1.Write (l, 4);
fs1.Write (l, 4);
fs1.Write (Info.MaxWidth, 2);
fs1.Write (Info.MaxHeight, 2);
tmp := $20;
fs1.Write (tmp, 1);
tmp := $08; // 原点在左下用$08,原点在左上用$28;
fs1.Write (tmp, 1);
// 清空bufbmp
for y:=0 to bufbmp.Height-1 do
begin
pDest := bufbmp.ScanLine[y];
for x:=0 to bufbmp.Width-1 do
begin
pDest[0]:=0;
pDest[1]:=0;
pDest[2]:=0;
pDest[3]:=0;
Inc (LongWord (pDest), 4);
end;
end;
DrawToTGA (bufbmp, Info.Key_X, Info.Key_Y, i);
for y:=bufbmp.Height-1 downto 0 do
begin
pDest := bufbmp.ScanLine[y];
fs1.Write (pDest[0], 4*bufbmp.Width);
end;

fs1.Free;
end;
bufbmp := nil;
end;
function PosLast (substr1,str1: widestring):Integer;
var
str2: widestring;
i,l: Integer;
sum: Integer;
begin
sum := 0;
str2 := str1;
//  i := Pos ( ' \',str1);
i := Pos (substr1, str2);
while i<>0 do
begin
l := Length (str2);
sum := sum + i;
str2 := RightStr (str2, l-i);
i := Pos (substr1, str2);
end;
Result := sum;
end;
// 仅为TGA服务
procedure TWasFile.DrawToTGA (Dest: TBitmap; X: Integer; Y: Integer; Index: Integer);
var
New_X: Integer;
New_Y: Integer;
New_Width: Integer;
New_Height: Integer;
New_Left: Integer;
New_Top: Integer;
i,j: Integer;
pDest: PByteArray;
Color: Word;
Alpha: Byte;
begin
if not fInitialized then
raise Exception.Create ( ' 没加载图片,画什么啊!');
if (Index<0) or (Index> (Info.SpriteCount * Info.FrameCount)) then
raise Exception.Create ( ' 没有第'+IntToStr(Index)+'张图片,没法画!');
// 裁减
New_X := X - Data[Index].Info.Key_X;
New_Y := Y - Data[Index].Info.Key_Y;
New_Width := Data[Index].Info.Width;
New_Height := Data[Index].Info.Height;
New_Left := 0;
New_Top := 0;
if (New_X > Dest.Width) or (New_Y > Dest.Height) then
exit;
if (New_X + New_Width) > Dest.Width then
New_Width := Dest.Width - New_X;
if (New_Y + New_Height) > Dest.Height then
New_Height := Dest.Height - New_Y;
if New_X < 0 then
begin
New_Left := -New_X;
New_X := 0;
end;
if New_Y < 0 then
begin
New_Top := -New_Y;
New_Y := 0
end;
for i:=New_Top to New_Height-1 do
begin
pDest := Dest.ScanLine[New_Y+i-New_Top];
Inc (LongWord (pDest), 4*New_X);
for j:=New_Left to New_Width-1 do
begin
Color := CurrentPal[Data[Index].Data[i*Data[Index].Info.Width+j].Index];
Alpha := Data[Index].Data[i*Data[Index].Info.Width+j].Alpha;
if Alpha=0 then
begin
// 0号调色板不一定是黑色,为了photoshop里显示的效果
// 强制写入黑色
pDest[0] := 0;
pDest[1] := 0;
pDest[2] := 0;
pDest[3] := 0;
end
else if Alpha=32 then
begin
pDest[0] := ( (Color and $001F) shl 3) and $F8;
pDest[0] := pDest[0] or ( (pDest[0] shr 3) and 7);
pDest[1] := ( (Color and $07E0) shr 3) and $FC;
pDest[1] := pDest[1] or ( (pDest[1] shr 2) and 3);
pDest[2] := ( (Color and $F800) shr 8) and $F8;
pDest[2] := pDest[2] or ( (pDest[2] shr 3) and 7);
pDest[3] := 255;
end
else
begin
// alpha 像素导出处
// 貌似wascompress是先合并再导出,而不是直接导出,所以发黑
{        pDest[0] := ( ( (Color and $001F) shl 3) * Alpha div 32) and $F8;
pDest[0] := pDest[0] or ( (pDest[0] shr 3) and 7);
pDest[1] := ( ( (Color and $07E0) shr 3) * Alpha div 32) and $FC;
pDest[1] := pDest[1] or ( (pDest[1] shr 2) and 3);
pDest[2] := ( ( (Color and $F800) shr 8) * Alpha div 32) and $F8;
pDest[2] := pDest[2] or ( (pDest[2] shr 3) and 7);}
// 正常的TGA导出
pDest[0] := ( (Color and $001F) shl 3) and $F8;
pDest[0] := pDest[0] or ( (pDest[0] shr 3) and 7);
pDest[1] := ( (Color and $07E0) shr 3) and $FC;
pDest[1] := pDest[1] or ( (pDest[1] shr 2) and 3);
pDest[2] := ( (Color and $F800) shr 8) and $F8;
pDest[2] := pDest[2] or ( (pDest[2] shr 3) and 7);
pDest[3]:=Alpha*8;
end;
Inc (LongWord (pDest), 4);
end;
end;
end;
end.

回复 支持 反对

使用道具 举报

结帖率:100% (10/10)

签到天数: 5 天

发表于 昨天 14:04 | 显示全部楼层   江苏省南通市
发来看看
回复 支持 反对

使用道具 举报

结帖率:50% (1/2)

签到天数: 2 天

发表于 3 天前 | 显示全部楼层   广西壮族自治区桂林市
什么代码,出多少钱,给我发消息
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表