Changeset 192 for oup/current/Global


Ignore:
Timestamp:
May 24, 2007, 7:48:18 PM (18 years ago)
Author:
alloc
Message:
 
Location:
oup/current/Global
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • oup/current/Global/Exporters.pas

    r113 r192  
    225225  img := TOniImage.Create;
    226226  img.Load(ConnectionID, FileID);
    227   img.WriteToBMP(filename+'.bmp');
     227  img.WriteToFile(filename+'.bmp');
    228228  img.Free;
    229229end;
  • oup/current/Global/OniImgClass.pas

    r181 r192  
    44
    55uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs,
    6   Imaging, ImagingTypes;
    7 
    8 type
    9   TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
     6  Imaging, ImagingTypes, Graphics;
    107
    118
     
    1310  TOniImage = class
    1411  private
    15     FLoaded:    Boolean;
    16     FDataType:  TImgDataType;
    17     FData:      TByteData;
    18     FWidth, FHeight: Word;
    19     FDepth:     Byte;
    20     FStoreType: Byte;
    21 
    22     FImage:     TImageData;
    23 
    24     function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
    25     procedure RevertImage;
    26     procedure DecompressImage;
     12    FImages: TDynImageDataArray;
     13    function GetImage(MipGen: Integer): TImageData;
     14    function GetWidth(MipGen: Integer): Integer;
     15    function GetHeight(MipGen: Integer): Integer;
     16    function GetImageFormat: TImageFormat;
     17    procedure SetImageFormat(Format: TImageFormat);
     18    function GetHasMipMaps: Boolean;
    2719  protected
    2820  public
    29     property Image:     TImageData   Read FImage     Write FImage;
    30     property Loaded:    Boolean      Read FLoaded    Write FLoaded;
    31     property DataType:  TImgDataType Read FDataType  Write FDataType;
    32     property Width:     Word         Read FWidth     Write FWidth;
    33     property Height:    Word         Read FHeight    Write FHeight;
    34     property Depth:     Byte         Read FDepth     Write FDepth;
    35     property StoreType: Byte         Read FStoreType Write FStoreType;
    36     property Data:      TByteData    Read FData      Write FData;
     21    property Images: TDynImageDataArray         read FImages;
     22    property Image[MipGen: Integer]: TImageData read GetImage;
     23    property Width[MipGen: Integer]: Integer    read GetWidth;
     24    property Height[MipGen: Integer]: Integer   read GetHeight;
     25    property Format: TImageFormat read GetImageFormat write SetImageFormat;
     26    property HasMipMaps: Boolean read GetHasMipMaps;
    3727
    3828    constructor Create;
     29    procedure Free;
    3930    function Load(ConnectionID, FileID: Integer): Boolean;
    4031    function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
    4132    function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
    4233    function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
    43     function GetImgSize(w,h, storetype: Integer): Integer;
    44     function GetImageDataSize(fading: Boolean): Integer;
    45 
    46     procedure DecodeImageTo32bit;
    47 
    48     procedure GetAsData(var Target: TStream); overload;
    49     procedure GetAsData(var Target: TByteData); overload;
    50     procedure GetAs32bit(var Target: TStream); overload;
    51     procedure GetAs32bit(var Target: TByteData); overload;
    52     procedure GetAsBMP(var Target: TStream); overload;
    53     procedure GetAsBMP(var Target: TByteData); overload;
    54     function LoadFromBMP(filename: String): Boolean;
    55     function WriteToBMP(filename: String): Boolean;
    56     function GetMipMappedImage(var Target: TStream): Boolean; overload;
    57     function GetMipMappedImage(var Target: TByteData): Boolean; overload;
     34
     35    procedure SaveDataToStream(MipMaps: Boolean; var Target: TStream);
     36
     37    function LoadFromFile(filename: String): Boolean;
     38    function WriteToFile(filename: String): Boolean;
     39
     40    procedure DrawOnCanvas(Canvas: TCanvas; Index: Integer);
     41    function GetImageSize(MipMaps: Boolean): Integer;
    5842  published
    5943  end;
     
    6347
    6448//uses Functions;
    65 uses Img_DDSTypes;
     49uses Img_DDSTypes, ImagingComponents;
     50
     51
     52procedure TOniImage.DrawOnCanvas(Canvas: TCanvas; Index: Integer);
     53var
     54  singleimg: TImageData;
     55  rect: TRect;
     56begin
     57  InitImage(singleimg);
     58  CloneImage(FImages[Index], singleimg);
     59  ConvertImage(singleimg, ifX8R8G8B8);
     60  rect.Left := 0;
     61  rect.Top := 0;
     62  rect.Right := singleimg.Width - 1;
     63  rect.Bottom := singleimg.Height - 1;
     64  Canvas.Brush.Color := $C8D0D4;
     65  Canvas.FillRect(Canvas.ClipRect);
     66  DisplayImageData(Canvas, rect, singleimg, rect);
     67  FreeImage(singleimg);
     68end;
     69
    6670
    6771
    6872constructor TOniImage.Create;
    6973begin
    70   Self.FLoaded   := False;
    71   Self.FDataType := [];
    72   SetLength(Self.FData, 0);
    73   Self.FWidth     := 0;
    74   Self.FHeight    := 0;
    75   Self.FDepth     := 0;
    76   Self.FStoreType := 0;
    77 
    78   InitImage(FImage);
    79 end;
    80 
    81 
    82 
    83 
    84 function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
    85 var
    86   i, j: Integer;
    87   col, row, row_orig: Integer;
    88 begin
    89   SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
    90   row_orig := 0;
    91   row      := 0;
    92   col      := 0;
    93   for i := 0 to (oldx * oldy) - 1 do
    94   begin
    95     if ((i mod oldx) = 0) and (i > 0) then
    96     begin
    97       Inc(row_orig);
    98       if (row_orig mod 2) = 0 then
    99       begin
    100         Inc(row);
    101         col := 0;
    102       end;
    103     end;
    104     if (row_orig mod 2) = 0 then
    105     begin
    106       if (i mod 2) = 0 then
    107       begin
    108         for j := 0 to (Self.FDepth div 8) - 1 do
    109           Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
    110             img[(i * (Self.FDepth div 8)) + j];
    111         Inc(col);
    112       end;
    113     end;
    114   end;
    115 end;
    116 
    117 
    118 
    119 
    120 procedure TOniImage.RevertImage;
    121 var
    122   x, y, i: Integer;
    123   tempd:   TByteData;
    124 begin
    125   SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
    126   for y := 0 to Self.FHeight - 1 do
    127     for x := 0 to Self.FWidth - 1 do
    128       for i := 0 to (Self.FDepth div 8) - 1 do
    129         tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
    130           Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
    131   for x := 0 to High(tempd) do
    132     Self.FData[x] := tempd[x];
    133   if DT_OniReverted in Self.FDataType then
    134     Self.FDataType := Self.FDataType - [DT_OniReverted]
    135   else
    136     Self.FDataType := Self.FDataType + [DT_OniReverted];
    137 end;
    138 
    139 
    140 
    141 
    142 procedure TOniImage.DecodeImageTo32bit;
    143 var
    144   x, y:  Integer;
    145   tempd: TByteData;
    146 begin
    147   if not (DT_Decoded32 in Self.FDataType) then
    148   begin
    149     SetLength(tempd, Self.FWidth * Self.FHeight * 4);
    150     case Self.FStoreType of
    151       0: // 16bit, RGB444, A4?
    152       begin
    153         for y := 0 to Self.FHeight - 1 do
    154         begin
    155           for x := 0 to Self.FWidth - 1 do
    156           begin
    157             tempd[((Self.FWidth * y + x) * 4) + 0] :=
    158               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    159               $000F) / $000F * 255);
    160             tempd[((Self.FWidth * y + x) * 4) + 1] :=
    161               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    162               $00F0) / $00F0 * 255);
    163             tempd[((Self.FWidth * y + x) * 4) + 2] :=
    164               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    165               $0F00) / $0F00 * 255);
    166             tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
    167           end;
    168         end;
    169       end;
    170       1, 2: // 16bit, RGB555, A1?
    171       begin
    172         for y := 0 to Self.FHeight - 1 do
    173         begin
    174           for x := 0 to Self.FWidth - 1 do
    175           begin
    176             tempd[((Self.FWidth * y + x) * 4) + 0] :=
    177               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    178               $001F) / $001F * 255);
    179             tempd[((Self.FWidth * y + x) * 4) + 1] :=
    180               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    181               $03E0) / $03E0 * 255);
    182             tempd[((Self.FWidth * y + x) * 4) + 2] :=
    183               Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
    184               $7C00) / $7C00 * 255);
    185             tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
    186           end;
    187         end;
    188       end;
    189       8: // 32bit, RGB888, A8?
    190       begin end;
    191       9: // Compressed, RGB565
    192       begin
    193         DecompressImage;
    194       end;
    195     end;
    196     Self.FDepth := 32;
    197     if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
    198     begin
    199       SetLength(Self.FData, Length(tempd));
    200       for x := 0 to High(tempd) do
    201         Self.FData[x] := tempd[x];
    202     end;
    203     Self.FStoreType := 8;
    204     if DT_Oni in Self.FDataType then
    205       Self.FDataType := Self.FDataType - [DT_Oni];
    206     Self.FDataType := Self.FDataType + [DT_Decoded32];
    207   end;
    208   if DT_OniReverted in Self.FDataType then
    209     Self.RevertImage;
    210 end;
    211 
    212 
    213 
    214 
    215 procedure TOniImage.DecompressImage;
    216 type
    217   Tcolor = record
    218     RGBb: Byte;
    219     RGBg: Byte;
    220     RGBr: Byte;
    221     RGBa: Byte;
    222   end;
    223 var
    224   i, j, x, y: Integer;
    225   color:      array[1..4] of Tcolor;
    226   pixel:      array[1..16] of Byte;
    227   tempd:      TByteData;
    228 begin
    229   x := 0;
    230   y := 0;
    231   SetLength(tempd, Self.FWidth * Self.FHeight * 4);
    232   for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
    233   begin
    234     Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
    235       $001F * 255);
    236     Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
    237       $07E0 * 255);
    238     Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
    239       $F800 * 255);
    240     Color[1].RGBa := 255;
    241     Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
    242       $001F * 255);
    243     Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
    244       $07E0 * 255);
    245     Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
    246       $F800 * 255);
    247     Color[2].RGBa := 255;
    248     Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
    249     Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
    250     Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
    251     Color[3].RGBa := 255;
    252     Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
    253     Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
    254     Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
    255     Color[4].RGBa := 255;
    256     Pixel[1]      := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
    257     Pixel[2]      := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
    258     Pixel[3]      := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
    259     Pixel[4]      := Round((Self.FData[(i * 8) + 4] and $03) + 1);
    260     Pixel[5]      := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
    261     Pixel[6]      := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
    262     Pixel[7]      := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
    263     Pixel[8]      := Round((Self.FData[(i * 8) + 5] and $03) + 1);
    264     Pixel[9]      := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
    265     Pixel[10]     := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
    266     Pixel[11]     := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
    267     Pixel[12]     := Round((Self.FData[(i * 8) + 6] and $03) + 1);
    268     Pixel[13]     := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
    269     Pixel[14]     := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
    270     Pixel[15]     := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
    271     Pixel[16]     := Round((Self.FData[(i * 8) + 7] and $03) + 1);
    272     for j := 0 to 3 do
    273     begin
    274       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
    275       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
    276       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
    277       tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
    278     end;
    279     for j := 0 to 3 do
    280     begin
    281       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
    282       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
    283       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
    284       tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
    285     end;
    286     for j := 0 to 3 do
    287     begin
    288       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
    289       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
    290       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
    291       tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
    292     end;
    293     for j := 0 to 3 do
    294     begin
    295       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
    296       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
    297       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
    298       tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
    299     end;
    300     x := x + 4;
    301     if x = Self.FWidth then
    302     begin
    303       y := y + 4;
    304       x := 0;
    305     end;
    306   end;
    307   SetLength(Self.FData, Length(tempd));
    308   for i := 0 to High(tempd) do
    309     Self.FData[i] := tempd[i];
    310   Self.FStoreType := 8;
    311   Self.FDepth    := 32;
    312   Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
    313 end;
    314 
    315 
    316 
     74end;
     75
     76
     77
     78procedure TOniImage.Free;
     79begin
     80  FreeImagesInArray(FImages);
     81end;
     82
     83
     84
     85
     86function TOniImage.GetImage(MipGen: Integer): TImageData;
     87begin
     88  if MipGen <= Length(FImages) then
     89  begin
     90    InitImage(Result);
     91    CloneImage(FImages[MipGen-1], Result);
     92  end;
     93end;
     94
     95
     96
     97function TOniImage.GetWidth(MipGen: Integer): Integer;
     98begin
     99  if MipGen <= Length(FImages) then
     100    Result := FImages[MipGen-1].Width
     101  else
     102    Result := -1;
     103end;
     104
     105
     106function TOniImage.GetHeight(MipGen: Integer): Integer;
     107begin
     108  if MipGen <= Length(FImages) then
     109    Result := FImages[MipGen-1].Height
     110  else
     111    Result := -1;
     112end;
     113
     114
     115function TOniImage.GetImageFormat: TImageFormat;
     116begin
     117  if Length(FImages) > 0 then
     118    Result := FImages[0].Format
     119  else
     120    Result := ifUnknown;
     121end;
     122
     123procedure TOniImage.SetImageFormat(Format: TImageFormat);
     124var
     125  i: Integer;
     126begin
     127  if Length(FImages) > 0 then
     128    for i := 0 to High(FImages) do
     129      ConvertImage(FImages[i], Format);
     130end;
     131
     132
     133function TOniImage.GetHasMipMaps: Boolean;
     134begin
     135  Result := Length(FImages) > 1;
     136end;
    317137
    318138
     
    370190  col, row: Byte;
    371191begin
     192(*
    372193  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
    373194  PSpc.TXMP := PSpc.TXMP div 256;
     
    472293  Self.FDataType  := [DT_Decoded32];
    473294  //    Self.RevertImage;
     295*)
    474296end;
    475297
     
    484306  imginfo: Integer;
    485307  x,y, i: Integer;
     308
     309  _width, _height: Word;
     310  _storetype: Byte;
     311  _depth: Byte;
    486312begin
    487313  Result := True;
    488   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
    489   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
    490   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType), @Self.FStoreType);
     314  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(_width), @_width);
     315  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(_height), @_height);
     316  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(_storetype), @_storetype);
    491317  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo);
    492318  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
     
    495321    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
    496322
    497   case Self.FStoreType of
     323  case _storetype of
    498324    0, 1, 2:
    499       Self.FDepth := 16;
    500     8:
    501       Self.FDepth := 32;
     325      _depth := 16;
     326    7, 8:
     327      _depth := 32;
    502328    9:
    503       Self.FDepth := 16;
     329      _depth := 16;
    504330    else
    505331      Result := False;
     
    507333  end;
    508334
    509   if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
    510     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
    511   else
    512     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
    513 
    514335  with hdr do
    515336  begin
     
    519340      Size := 124;
    520341      Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
    521       if FStoreType = 9 then
     342      if _storetype = 9 then
    522343        Flags := Flags or DDSD_LINEARSIZE
    523344      else
     
    525346      if (imginfo and $01) > 0 then
    526347        Flags := Flags or DDSD_MIPMAPCOUNT;
    527       Height := FHeight;
    528       Width := FWidth;
    529       if FStoreType = 9 then
    530         PitchOrLinearSize := FWidth * FHeight div 2
     348      Height := _height;
     349      Width := _width;
     350      if _storetype = 9 then
     351        PitchOrLinearSize := width * height div 2
    531352      else
    532         PitchOrLinearSize := FWidth * FDepth div 2;
     353        PitchOrLinearSize := width * _depth div 8;
    533354      Depth := 0;
    534355      MipMapCount := 1;
    535       x := FWidth;
    536       y := FHeight;
    537       while (x > 1) and (y > 1) do
     356      if (imginfo and $01) > 0 then
    538357      begin
    539         x := x div 2;
    540         y := y div 2;
    541         Inc(MipMapCount);
     358        x := width;
     359        y := height;
     360        while (x > 1) and (y > 1) do
     361        begin
     362          x := x div 2;
     363          y := y div 2;
     364          Inc(MipMapCount);
     365        end;
    542366      end;
    543367      for i := 1 to 11 do
     
    546370      begin
    547371        Size := 32;
    548         if FStoreType = 9 then
     372        if _storetype = 9 then
    549373          Flags := DDPF_FOURCC
    550374        else
    551375          Flags := DDPF_RGB;
     376        if _storetype in [0, 2] then
     377          Flags := Flags or DDPF_ALPHAPIXELS;
     378        if _storetype = 9 then
     379          FOURCC := 'DXT1'
     380        else
     381        begin
     382          RGBBitCount := _depth;
     383          case _storetype of
     384            0: begin
     385              RBitMask := $0F00;
     386              GBitMask := $00F0;
     387              BBitMask := $000F;
     388              AlphaBitMask := $F000;
     389            end;
     390            1, 2: begin
     391              RBitMask := $7C00;
     392              GBitMask := $03E0;
     393              BBitMask := $001F;
     394              if _storetype = 2 then
     395                AlphaBitMask := $8000
     396              else
     397                AlphaBitMask := $0000;
     398            end;
     399            8: begin
     400              RBitMask := $00FF0000;
     401              GBitMask := $0000FF00;
     402              BBitMask := $000000FF;
     403              AlphaBitMask := $00000000;
     404            end;
     405          end;
     406        end;
    552407      end;
    553     end;
    554   end;
    555   LoadImageFromStream(data, FImage);
    556 {
     408      with DDSCAPS2 do
     409      begin
     410        Caps1 := DDSCAPS_TEXTURE;
     411        if (imginfo and $01) > 0 then
     412          Caps1 := Caps1 or DDSCAPS_COMPLEX or DDSCAPS_MIPMAP;
     413        Caps2 := 0;
     414        Reserved[1] := 0;
     415        Reserved[2] := 0;
     416      end;
     417    end;
     418  end;
     419
     420  data := TMemoryStream.Create;
     421  data.Write(hdr, SizeOf(hdr));
    557422  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
    558     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
    559   else
    560     ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
    561 }
    562   Self.FDataType := [DT_OniReverted, DT_Oni];
     423    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
     424  else
     425    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
     426  data.Seek(0, soFromBeginning);
     427  result := LoadMultiImageFromStream(data, FImages);
     428  data.Free;
     429
     430  if not result then
     431  begin
     432    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
     433//    data.SaveToFile('m:\prob.dds');
     434  end;
    563435end;
    564436
     
    572444  linkcount: Integer;
    573445  link: Integer;
    574   images_decoded: array of TOniImage;
     446  images: array of TOniImage;
    575447  x_start, y_start: Integer;
    576 begin
    577   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
    578   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
     448
     449  width, height: Word;
     450begin
     451  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(width), @width);
     452  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(height), @height);
    579453  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
    580454  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
    581455  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
    582   SetLength(images_decoded, linkcount);
     456  SetLength(images, linkcount);
    583457  for i := 0 to linkcount - 1 do
    584458  begin
    585459    ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
    586460    link := link div 256;
    587     images_decoded[i] := TOniImage.Create;
    588     images_decoded[i].LoadFromTXMP(ConnectionID, link);
    589     images_decoded[i].DecodeImageTo32bit;
    590     images_decoded[i].RevertImage;
    591   end;
    592   SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
     461    images[i] := TOniImage.Create;
     462    images[i].LoadFromTXMP(ConnectionID, link);
     463    SetLength(FImages, 1);
     464    NewImage(width, height, ifA1R5G5B5, FImages[0]);
     465  end;
    593466  for y := 0 to rows - 1 do
    594467  begin
    595468    for x := 0 to cols - 1 do
    596469    begin
    597       imgid   := y * cols + x;
     470      imgid := y * cols + x;
    598471      x_start := 0;
    599472      y_start := 0;
    600473      for i := 0 to x do
    601474        if i < x then
    602           x_start := x_start + images_decoded[i].Width;
     475          x_start := x_start + images[i].Image[0].Width;
    603476      for i := 0 to y do
    604477        if i < y then
    605           y_start := y_start + images_decoded[i].Height;
    606       for y2 := 0 to images_decoded[imgid].Height - 1 do
     478          y_start := y_start + images[i].Image[0].Height;
     479      CopyRect(images[imgid].Image[0], 0, 0, images[imgid].Image[0].Width,
     480          images[imgid].Image[0].Height, FImages[0], x_start, y_start);
     481    end;
     482  end;
     483  for i := 0 to linkcount - 1 do
     484    images[i].Free;
     485end;
     486
     487
     488
     489procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
     490var
     491  images: TDynImageDataArray;
     492  mem: TMemoryStream;
     493  i: Integer;
     494begin
     495  if Length(FImages) = 0 then
     496    Exit;
     497  if MipMaps then
     498  begin
     499    if Length(FImages) = 1 then
     500    begin
     501      if not GenerateMipMaps(FImages[0], 0, images) then
    607502      begin
    608         for x2 := 0 to images_decoded[imgid].Width - 1 do
    609         begin
    610           if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
    611           begin
    612             pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
    613             Self.FData[pixelid * 4 + 0] :=
    614               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
    615             Self.FData[pixelid * 4 + 1] :=
    616               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
    617             Self.FData[pixelid * 4 + 2] :=
    618               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
    619             Self.FData[pixelid * 4 + 3] :=
    620               images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
    621           end;
    622         end;
     503        ShowMessage('Could not generate MipMaps');
     504        Exit;
    623505      end;
    624     end;
    625   end;
    626   for i := 0 to linkcount - 1 do
    627     images_decoded[i].Free;
    628   Self.FDepth     := 32;
    629   Self.FStoreType := 8;
    630   Self.FDataType  := [DT_Decoded32];
    631   Self.RevertImage;
    632 end;
    633 
    634 
    635 
    636 function TOniImage.GetImgSize(w,h, storetype: Integer): Integer;
    637 begin
    638   case storetype of
    639     0, 1, 2:
    640       Result := w*h*2;
    641     8:
    642       Result := w*h*4;
    643     9:
    644       Result := Max(1, w div 4) * Max(1, h div 4) * 8;
    645   else
    646     Result := -1;
    647   end;
    648 end;
    649 
    650 
    651 function TOniImage.GetImageDataSize(fading: Boolean): Integer;
    652 var
    653   size: Integer;
    654   x, y: Word;
    655 begin
    656   x    := Self.FWidth;
    657   y    := Self.FHeight;
    658   size := GetImgSize(x, y, FStoreType);
    659   if fading then
    660   begin
    661     repeat
    662       x    := Max(x div 2, 1);
    663       y    := Max(y div 2, 1);
    664       size := size + GetImgSize(x, y, FStoreType);
    665     until (x = 1) and (y = 1);
    666   end;
    667   Result := size;
    668 end;
    669 
    670 
    671 
    672 
    673 procedure TOniImage.GetAsData(var Target: TStream);
    674 var
    675   revert: Boolean;
    676 begin
    677   //    if not (DT_Decoded32 in Self.FDataType) then
    678   //      Self.DecodeImage;
    679   if not (DT_OniReverted in Self.FDataType) then
    680   begin
    681     revert := True;
    682     Self.RevertImage;
     506    end
     507    else
     508    begin
     509      SetLength(images, Length(FImages));
     510      for i := 0 to High(FImages) do
     511        CloneImage(FImages[i], images[i]);
     512    end;
     513    mem := TMemoryStream.Create;
     514    if not SaveMultiImageToStream('dds', mem, images) then
     515    begin
     516      ShowMessage('Could not save images to stream');
     517      Exit;
     518    end;
     519    FreeImagesInArray(images);
    683520  end
    684521  else
    685     revert := False;
     522  begin
     523    mem := TMemoryStream.Create;
     524    if not SaveImageToStream('dds', mem, FImages[0]) then
     525    begin
     526      ShowMessage('Could not save image to stream');
     527      Exit;
     528    end;
     529  end;
    686530  if not Assigned(Target) then
    687531    Target := TMemoryStream.Create;
    688   Target.Write(FData[0], Length(FData));
     532
     533//  mem.Seek(0, soFromBeginning);
     534//  mem.SaveToFile('m:\dds.dds');
     535
     536  mem.Seek(128, soFromBeginning);
     537  Target.CopyFrom(mem, mem.Size - 128);
     538  mem.Free;
    689539  Target.Seek(0, soFromBeginning);
    690   if revert then
    691     Self.RevertImage;
    692 end;
    693 
    694 procedure TOniImage.GetAsData(var Target: TByteData);
    695 var
    696   mem: TStream;
    697 begin
    698   mem := TMemoryStream.Create;
    699   GetAsData(mem);
    700   SetLength(Target, mem.Size);
    701   mem.Read(Target[0], mem.Size);
    702   mem.Free;
    703 end;
    704 
    705 
    706 procedure TOniImage.GetAs32bit(var Target: TStream);
    707 begin
    708   if not (DT_Decoded32 in Self.FDataType) then
    709     Self.DecodeImageTo32bit;
    710   if not Assigned(Target) then
    711     Target := TMemoryStream.Create;
    712   Target.Write(FData[0], Length(FData));
    713   Target.Seek(0, soFromBeginning);
    714 end;
    715 
    716 procedure TOniImage.GetAs32bit(var Target: TByteData);
    717 var
    718   mem: TStream;
    719 begin
    720   mem := TMemoryStream.Create;
    721   GetAs32bit(mem);
    722   SetLength(Target, mem.Size);
    723   mem.Read(Target[0], mem.Size);
    724   mem.Free;
    725 end;
    726 
    727 
    728 procedure TOniImage.GetAsBMP(var Target: TByteData);
    729 const
    730   BMPheader: array[0..53] of Byte =
    731     ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
    732     40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, $18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    733     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    734 var
    735   i, x, y: Integer;
    736 begin
    737   if not (DT_Decoded32 in Self.FDataType) then
    738     Self.DecodeImageTo32bit;
    739 
    740   SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
    741   for y := 0 to Self.FHeight - 1 do
    742   begin
    743     for x := 0 to Self.FWidth - 1 do
    744     begin
    745       Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
    746       Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
    747       Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
    748     end;
    749   end;
    750 
    751   for i := 0 to High(BMPheader) do
    752     Target[i] := BMPheader[i];
    753   Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
    754   Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
    755   Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
    756   Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
    757   Target[18] := (Self.FWidth and $000000FF) div $1;
    758   Target[19] := (Self.FWidth and $0000FF00) div $100;
    759   Target[20] := (Self.FWidth and $00FF0000) div $10000;
    760   Target[21] := (Self.FWidth and $FF000000) div $1000000;
    761   Target[22] := (Self.FHeight and $000000FF) div $1;
    762   Target[23] := (Self.FHeight and $0000FF00) div $100;
    763   Target[24] := (Self.FHeight and $00FF0000) div $10000;
    764   Target[25] := (Self.FHeight and $FF000000) div $1000000;
    765   Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
    766   Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
    767   Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
    768   Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
    769 end;
    770 
    771 
    772 procedure TOniImage.GetAsBMP(var Target: TStream);
    773 var
    774   data: TByteData;
    775   streampos: Integer;
    776 begin
    777   GetAsBMP(data);
    778   streampos := Target.Position;
    779   Target.Write(data[0], Length(data));
    780   Target.Seek(streampos, soFromBeginning);
    781 end;
    782 
    783 
    784 function TOniImage.LoadFromBMP(filename: String): Boolean;
    785 var
    786   filestream: TFileStream;
    787   tempd:      TByteData;
    788 
    789   x, y: Integer;
    790 begin
    791   filestream := TFileStream.Create(filename, fmOpenRead);
    792   SetLength(tempd, filestream.Size);
    793   filestream.Read(tempd[0], filestream.Size);
    794   filestream.Free;
    795 
    796   if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
    797   begin
    798     Result := False;
    799     ShowMessage('Not a standard 24bit bitmap');
    800     Exit;
    801   end;
    802   if not (tempd[10] = 54) then
    803   begin
    804     Result := False;
    805     ShowMessage('Imagedata has to start at 0x54');
    806     Exit;
    807   end;
    808   if not (tempd[14] = 40) then
    809   begin
    810     Result := False;
    811     ShowMessage('Second bitmap header has to have 40 bytes');
    812     Exit;
    813   end;
    814   if not (tempd[28] = 24) then
    815   begin
    816     Result := False;
    817     ShowMessage('Bitmap has to have 24bits');
    818     Exit;
    819   end;
    820   if not (tempd[30] = 0) then
    821   begin
    822     Result := False;
    823     ShowMessage('Bitmap has to be uncompressed');
    824     Exit;
    825   end;
    826 
    827   Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
    828   Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
    829   Self.FDepth     := 32;
    830   Self.FStoreType := 8;
    831 
    832   SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
    833   for y := 0 to Self.FHeight - 1 do
    834   begin
    835     for x := 0 to Self.FWidth - 1 do
    836     begin
    837       Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
    838       Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
    839       Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
    840       Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
    841     end;
    842   end;
    843 
    844   Self.FDataType := [DT_Decoded32];
    845 end;
    846 
    847 
    848 
    849 
    850 function TOniImage.WriteToBMP(filename: String): Boolean;
    851 var
    852   filestream: TFileStream;
    853 begin
    854   filestream := TFileStream.Create(filename, fmCreate);
    855   GetAsBMP(TStream(filestream));
    856   filestream.Free;
    857 end;
    858 
    859 
    860 
    861 function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
    862 var
    863   i:      Integer;
    864   x, y:   Word;
    865   fadelvldata: TByteData;
    866   revert: Boolean;
    867 begin
    868   Result := False;
    869 
    870   //    if not (DT_Decoded32 in Self.FDataType) then
    871   //      Self.DecodeImage;
    872   if Self.FStoreType = 9 then
    873     Self.DecompressImage;
    874   if not (DT_OniReverted in Self.FDataType) then
    875   begin
    876     revert := True;
    877     Self.RevertImage;
     540end;
     541
     542
     543function TOniImage.LoadFromFile(filename: String): Boolean;
     544begin
     545  if not LoadMultiImageFromFile(filename, FImages) then
     546    ShowMessage('Couldn''t load image file');
     547end;
     548
     549
     550function TOniImage.WriteToFile(filename: String): Boolean;
     551begin
     552  SaveMultiImageToFile(filename, FImages);
     553end;
     554
     555
     556
     557function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
     558var
     559  i: Integer;
     560begin
     561  if Length(FImages) > 0 then
     562  begin
     563    Result := FImages[0].Size;
     564    if mipmaps then
     565      for i := 1 to High(FImages) do
     566        Result := Result + FImages[i].Size;
    878567  end
    879568  else
    880     revert := False;
    881 
    882   x := Self.FWidth;
    883   y := Self.FHeight;
    884   SetLength(Target, x * y * Self.FDepth div 8);
    885   SetLength(fadelvldata, x * y * Self.FDepth div 8);
    886   for i := 0 to Length(Target) - 1 do
    887   begin
    888     Target[i] := Self.FData[i];
    889     fadelvldata[i] := Self.FData[i];
    890   end;
    891   repeat
    892     fadelvldata := Self.ResizeImage(x, y, fadelvldata);
    893     x := x div 2;
    894     y := y div 2;
    895     SetLength(Target, Length(Target) + x * y * Self.FDepth div 8);
    896     for i := 0 to Length(fadelvldata) - 1 do
    897       Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
    898   until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
    899   if (x > 1) and (y > 1) then
    900     Exit;
    901   Result := True;
    902 
    903   if revert then
    904     Self.RevertImage;
    905 end;
    906 
    907 
    908 function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
    909 var
    910   data: TByteData;
    911   streampos: Integer;
    912 begin
    913   Result := GetMipMappedImage(data);
    914   if not Assigned(Target) then
    915     Target := TMemoryStream.Create;
    916   streampos := Target.Position;
    917   Target.Write(data[0], Length(data));
    918   Target.Seek(streampos, soFromBeginning);
    919 end;
    920 
     569    Result := -1;
     570end;
    921571
    922572end.
Note: See TracChangeset for help on using the changeset viewer.