Index: oup/current/Global/Exporters.pas
===================================================================
--- oup/current/Global/Exporters.pas	(revision 181)
+++ oup/current/Global/Exporters.pas	(revision 192)
@@ -225,5 +225,5 @@
   img := TOniImage.Create;
   img.Load(ConnectionID, FileID);
-  img.WriteToBMP(filename+'.bmp');
+  img.WriteToFile(filename+'.bmp');
   img.Free;
 end;
Index: oup/current/Global/OniImgClass.pas
===================================================================
--- oup/current/Global/OniImgClass.pas	(revision 181)
+++ oup/current/Global/OniImgClass.pas	(revision 192)
@@ -4,8 +4,5 @@
 
 uses Math, Dialogs, Types, SysUtils, Classes, Data, ConnectionManager, TypeDefs,
-  Imaging, ImagingTypes;
-
-type
-  TImgDataType = set of (DT_OniReverted, DT_Oni, DT_Decoded32);
+  Imaging, ImagingTypes, Graphics;
 
 
@@ -13,47 +10,34 @@
   TOniImage = class
   private
-    FLoaded:    Boolean;
-    FDataType:  TImgDataType;
-    FData:      TByteData;
-    FWidth, FHeight: Word;
-    FDepth:     Byte;
-    FStoreType: Byte;
-
-    FImage:     TImageData;
-
-    function ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
-    procedure RevertImage;
-    procedure DecompressImage;
+    FImages: TDynImageDataArray;
+    function GetImage(MipGen: Integer): TImageData;
+    function GetWidth(MipGen: Integer): Integer;
+    function GetHeight(MipGen: Integer): Integer;
+    function GetImageFormat: TImageFormat;
+    procedure SetImageFormat(Format: TImageFormat);
+    function GetHasMipMaps: Boolean;
   protected
   public
-    property Image:     TImageData   Read FImage     Write FImage;
-    property Loaded:    Boolean      Read FLoaded    Write FLoaded;
-    property DataType:  TImgDataType Read FDataType  Write FDataType;
-    property Width:     Word         Read FWidth     Write FWidth;
-    property Height:    Word         Read FHeight    Write FHeight;
-    property Depth:     Byte         Read FDepth     Write FDepth;
-    property StoreType: Byte         Read FStoreType Write FStoreType;
-    property Data:      TByteData    Read FData      Write FData;
+    property Images: TDynImageDataArray         read FImages;
+    property Image[MipGen: Integer]: TImageData read GetImage;
+    property Width[MipGen: Integer]: Integer    read GetWidth;
+    property Height[MipGen: Integer]: Integer   read GetHeight;
+    property Format: TImageFormat read GetImageFormat write SetImageFormat;
+    property HasMipMaps: Boolean read GetHasMipMaps;
 
     constructor Create;
+    procedure Free;
     function Load(ConnectionID, FileID: Integer): Boolean;
     function LoadFromPSpc(ConnectionID, FileID: Integer): Boolean;
     function LoadFromTXMP(ConnectionID, FileID: Integer): Boolean;
     function LoadFromTXMB(ConnectionID, FileID: Integer): Boolean;
-    function GetImgSize(w,h, storetype: Integer): Integer;
-    function GetImageDataSize(fading: Boolean): Integer;
-
-    procedure DecodeImageTo32bit;
-
-    procedure GetAsData(var Target: TStream); overload;
-    procedure GetAsData(var Target: TByteData); overload;
-    procedure GetAs32bit(var Target: TStream); overload;
-    procedure GetAs32bit(var Target: TByteData); overload;
-    procedure GetAsBMP(var Target: TStream); overload;
-    procedure GetAsBMP(var Target: TByteData); overload;
-    function LoadFromBMP(filename: String): Boolean;
-    function WriteToBMP(filename: String): Boolean;
-    function GetMipMappedImage(var Target: TStream): Boolean; overload;
-    function GetMipMappedImage(var Target: TByteData): Boolean; overload;
+
+    procedure SaveDataToStream(MipMaps: Boolean; var Target: TStream);
+
+    function LoadFromFile(filename: String): Boolean;
+    function WriteToFile(filename: String): Boolean;
+
+    procedure DrawOnCanvas(Canvas: TCanvas; Index: Integer);
+    function GetImageSize(MipMaps: Boolean): Integer;
   published
   end;
@@ -63,256 +47,92 @@
 
 //uses Functions;
-uses Img_DDSTypes;
+uses Img_DDSTypes, ImagingComponents;
+
+
+procedure TOniImage.DrawOnCanvas(Canvas: TCanvas; Index: Integer);
+var
+  singleimg: TImageData;
+  rect: TRect;
+begin
+  InitImage(singleimg);
+  CloneImage(FImages[Index], singleimg);
+  ConvertImage(singleimg, ifX8R8G8B8);
+  rect.Left := 0;
+  rect.Top := 0;
+  rect.Right := singleimg.Width - 1;
+  rect.Bottom := singleimg.Height - 1;
+  Canvas.Brush.Color := $C8D0D4;
+  Canvas.FillRect(Canvas.ClipRect);
+  DisplayImageData(Canvas, rect, singleimg, rect);
+  FreeImage(singleimg);
+end;
+
 
 
 constructor TOniImage.Create;
 begin
-  Self.FLoaded   := False;
-  Self.FDataType := [];
-  SetLength(Self.FData, 0);
-  Self.FWidth     := 0;
-  Self.FHeight    := 0;
-  Self.FDepth     := 0;
-  Self.FStoreType := 0;
-
-  InitImage(FImage);
-end;
-
-
-
-
-function TOniImage.ResizeImage(oldx, oldy: Integer; img: TByteData): TByteData;
-var
-  i, j: Integer;
-  col, row, row_orig: Integer;
-begin
-  SetLength(Result, (oldx div 2) * (oldy div 2) * (Self.FDepth div 8));
-  row_orig := 0;
-  row      := 0;
-  col      := 0;
-  for i := 0 to (oldx * oldy) - 1 do
-  begin
-    if ((i mod oldx) = 0) and (i > 0) then
-    begin
-      Inc(row_orig);
-      if (row_orig mod 2) = 0 then
-      begin
-        Inc(row);
-        col := 0;
-      end;
-    end;
-    if (row_orig mod 2) = 0 then
-    begin
-      if (i mod 2) = 0 then
-      begin
-        for j := 0 to (Self.FDepth div 8) - 1 do
-          Result[((row * (oldx div 2)) + col) * (Self.FDepth div 8) + j] :=
-            img[(i * (Self.FDepth div 8)) + j];
-        Inc(col);
-      end;
-    end;
-  end;
-end;
-
-
-
-
-procedure TOniImage.RevertImage;
-var
-  x, y, i: Integer;
-  tempd:   TByteData;
-begin
-  SetLength(tempd, Self.FWidth * Self.FHeight * (Self.FDepth div 8));
-  for y := 0 to Self.FHeight - 1 do
-    for x := 0 to Self.FWidth - 1 do
-      for i := 0 to (Self.FDepth div 8) - 1 do
-        tempd[((Self.FWidth * (Self.FHeight - 1 - y) + x) * (Self.FDepth div 8)) + i] :=
-          Self.FData[(Self.FWidth * y + x) * (Self.FDepth div 8) + i];
-  for x := 0 to High(tempd) do
-    Self.FData[x] := tempd[x];
-  if DT_OniReverted in Self.FDataType then
-    Self.FDataType := Self.FDataType - [DT_OniReverted]
-  else
-    Self.FDataType := Self.FDataType + [DT_OniReverted];
-end;
-
-
-
-
-procedure TOniImage.DecodeImageTo32bit;
-var
-  x, y:  Integer;
-  tempd: TByteData;
-begin
-  if not (DT_Decoded32 in Self.FDataType) then
-  begin
-    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
-    case Self.FStoreType of
-      0: // 16bit, RGB444, A4?
-      begin
-        for y := 0 to Self.FHeight - 1 do
-        begin
-          for x := 0 to Self.FWidth - 1 do
-          begin
-            tempd[((Self.FWidth * y + x) * 4) + 0] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $000F) / $000F * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 1] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $00F0) / $00F0 * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 2] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $0F00) / $0F00 * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
-          end;
-        end;
-      end;
-      1, 2: // 16bit, RGB555, A1?
-      begin
-        for y := 0 to Self.FHeight - 1 do
-        begin
-          for x := 0 to Self.FWidth - 1 do
-          begin
-            tempd[((Self.FWidth * y + x) * 4) + 0] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $001F) / $001F * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 1] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $03E0) / $03E0 * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 2] :=
-              Round(((Self.FData[(Self.FWidth * y + x) * 2] + Self.FData[(Self.FWidth * y + x) * 2 + 1] * 256) and
-              $7C00) / $7C00 * 255);
-            tempd[((Self.FWidth * y + x) * 4) + 3] := 0;
-          end;
-        end;
-      end;
-      8: // 32bit, RGB888, A8?
-      begin end;
-      9: // Compressed, RGB565
-      begin
-        DecompressImage;
-      end;
-    end;
-    Self.FDepth := 32;
-    if (Self.FStoreType <> 9) and (Self.FStoreType <> 8) then
-    begin
-      SetLength(Self.FData, Length(tempd));
-      for x := 0 to High(tempd) do
-        Self.FData[x] := tempd[x];
-    end;
-    Self.FStoreType := 8;
-    if DT_Oni in Self.FDataType then
-      Self.FDataType := Self.FDataType - [DT_Oni];
-    Self.FDataType := Self.FDataType + [DT_Decoded32];
-  end;
-  if DT_OniReverted in Self.FDataType then
-    Self.RevertImage;
-end;
-
-
-
-
-procedure TOniImage.DecompressImage;
-type
-  Tcolor = record
-    RGBb: Byte;
-    RGBg: Byte;
-    RGBr: Byte;
-    RGBa: Byte;
-  end;
-var
-  i, j, x, y: Integer;
-  color:      array[1..4] of Tcolor;
-  pixel:      array[1..16] of Byte;
-  tempd:      TByteData;
-begin
-  x := 0;
-  y := 0;
-  SetLength(tempd, Self.FWidth * Self.FHeight * 4);
-  for i := 0 to ((Self.FWidth * Self.FHeight) div 16) - 1 do
-  begin
-    Color[1].RGBb := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $001F) /
-      $001F * 255);
-    Color[1].RGBg := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $07E0) /
-      $07E0 * 255);
-    Color[1].RGBr := Round(((Self.FData[(i * 8) + 0] + Self.FData[(i * 8) + 1] * 256) and $F800) /
-      $F800 * 255);
-    Color[1].RGBa := 255;
-    Color[2].RGBb := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $001F) /
-      $001F * 255);
-    Color[2].RGBg := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $07E0) /
-      $07E0 * 255);
-    Color[2].RGBr := Round(((Self.FData[(i * 8) + 2] + Self.FData[(i * 8) + 3] * 256) and $F800) /
-      $F800 * 255);
-    Color[2].RGBa := 255;
-    Color[3].RGBb := Round(Color[1].RGBb / 3 * 2 + Color[2].RGBb / 3);
-    Color[3].RGBg := Round(Color[1].RGBg / 3 * 2 + Color[2].RGBg / 3);
-    Color[3].RGBr := Round(Color[1].RGBr / 3 * 2 + Color[2].RGBr / 3);
-    Color[3].RGBa := 255;
-    Color[4].RGBb := Round(Color[1].RGBb / 3 + Color[2].RGBb / 3 * 2);
-    Color[4].RGBg := Round(Color[1].RGBg / 3 + Color[2].RGBg / 3 * 2);
-    Color[4].RGBr := Round(Color[1].RGBr / 3 + Color[2].RGBr / 3 * 2);
-    Color[4].RGBa := 255;
-    Pixel[1]      := Round((Self.FData[(i * 8) + 4] and $C0) / $40 + 1);
-    Pixel[2]      := Round((Self.FData[(i * 8) + 4] and $30) / $10 + 1);
-    Pixel[3]      := Round((Self.FData[(i * 8) + 4] and $0C) / $04 + 1);
-    Pixel[4]      := Round((Self.FData[(i * 8) + 4] and $03) + 1);
-    Pixel[5]      := Round((Self.FData[(i * 8) + 5] and $C0) / $40 + 1);
-    Pixel[6]      := Round((Self.FData[(i * 8) + 5] and $30) / $10 + 1);
-    Pixel[7]      := Round((Self.FData[(i * 8) + 5] and $0C) / $04 + 1);
-    Pixel[8]      := Round((Self.FData[(i * 8) + 5] and $03) + 1);
-    Pixel[9]      := Round((Self.FData[(i * 8) + 6] and $C0) / $40 + 1);
-    Pixel[10]     := Round((Self.FData[(i * 8) + 6] and $30) / $10 + 1);
-    Pixel[11]     := Round((Self.FData[(i * 8) + 6] and $0C) / $04 + 1);
-    Pixel[12]     := Round((Self.FData[(i * 8) + 6] and $03) + 1);
-    Pixel[13]     := Round((Self.FData[(i * 8) + 7] and $C0) / $40 + 1);
-    Pixel[14]     := Round((Self.FData[(i * 8) + 7] and $30) / $10 + 1);
-    Pixel[15]     := Round((Self.FData[(i * 8) + 7] and $0C) / $04 + 1);
-    Pixel[16]     := Round((Self.FData[(i * 8) + 7] and $03) + 1);
-    for j := 0 to 3 do
-    begin
-      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[16 - j]].RGBb;
-      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[16 - j]].RGBg;
-      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[16 - j]].RGBr;
-      tempd[((y + 3) * Self.FWidth + x + j) * 4 + 3] := 0;
-    end;
-    for j := 0 to 3 do
-    begin
-      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[12 - j]].RGBb;
-      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[12 - j]].RGBg;
-      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[12 - j]].RGBr;
-      tempd[((y + 2) * Self.FWidth + x + j) * 4 + 3] := 0;
-    end;
-    for j := 0 to 3 do
-    begin
-      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[8 - j]].RGBb;
-      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[8 - j]].RGBg;
-      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[8 - j]].RGBr;
-      tempd[((y + 1) * Self.FWidth + x + j) * 4 + 3] := 0;
-    end;
-    for j := 0 to 3 do
-    begin
-      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 0] := Color[Pixel[4 - j]].RGBb;
-      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 1] := Color[Pixel[4 - j]].RGBg;
-      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 2] := Color[Pixel[4 - j]].RGBr;
-      tempd[((y + 0) * Self.FWidth + x + j) * 4 + 3] := 0;
-    end;
-    x := x + 4;
-    if x = Self.FWidth then
-    begin
-      y := y + 4;
-      x := 0;
-    end;
-  end;
-  SetLength(Self.FData, Length(tempd));
-  for i := 0 to High(tempd) do
-    Self.FData[i] := tempd[i];
-  Self.FStoreType := 8;
-  Self.FDepth    := 32;
-  Self.FDataType := Self.FDataType - [DT_Oni] + [DT_Decoded32];
-end;
-
-
-
+end;
+
+
+
+procedure TOniImage.Free;
+begin
+  FreeImagesInArray(FImages);
+end;
+
+
+
+
+function TOniImage.GetImage(MipGen: Integer): TImageData;
+begin
+  if MipGen <= Length(FImages) then
+  begin
+    InitImage(Result);
+    CloneImage(FImages[MipGen-1], Result);
+  end;
+end;
+
+
+
+function TOniImage.GetWidth(MipGen: Integer): Integer;
+begin
+  if MipGen <= Length(FImages) then
+    Result := FImages[MipGen-1].Width
+  else
+    Result := -1;
+end;
+
+
+function TOniImage.GetHeight(MipGen: Integer): Integer;
+begin
+  if MipGen <= Length(FImages) then
+    Result := FImages[MipGen-1].Height
+  else
+    Result := -1;
+end;
+
+
+function TOniImage.GetImageFormat: TImageFormat;
+begin
+  if Length(FImages) > 0 then
+    Result := FImages[0].Format
+  else
+    Result := ifUnknown;
+end;
+
+procedure TOniImage.SetImageFormat(Format: TImageFormat);
+var
+  i: Integer;
+begin
+  if Length(FImages) > 0 then
+    for i := 0 to High(FImages) do
+      ConvertImage(FImages[i], Format);
+end;
+
+
+function TOniImage.GetHasMipMaps: Boolean;
+begin
+  Result := Length(FImages) > 1;
+end;
 
 
@@ -370,4 +190,5 @@
   col, row: Byte;
 begin
+(*
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $08, SizeOf(PSpc), @PSpc);
   PSpc.TXMP := PSpc.TXMP div 256;
@@ -472,4 +293,5 @@
   Self.FDataType  := [DT_Decoded32];
   //    Self.RevertImage;
+*)
 end;
 
@@ -484,9 +306,13 @@
   imginfo: Integer;
   x,y, i: Integer;
+
+  _width, _height: Word;
+  _storetype: Byte;
+  _depth: Byte;
 begin
   Result := True;
-  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(Self.FWidth), @Self.FWidth);
-  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(Self.FHeight), @Self.FHeight);
-  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(Self.FStoreType), @Self.FStoreType);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8C, SizeOf(_width), @_width);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $8E, SizeOf(_height), @_height);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $90, SizeOf(_storetype), @_storetype);
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $88, SizeOf(imginfo), @imginfo);
   if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
@@ -495,11 +321,11 @@
     ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $A0, SizeOf(img_addr), @img_addr);
 
-  case Self.FStoreType of
+  case _storetype of
     0, 1, 2:
-      Self.FDepth := 16;
-    8:
-      Self.FDepth := 32;
+      _depth := 16;
+    7, 8:
+      _depth := 32;
     9:
-      Self.FDepth := 16;
+      _depth := 16;
     else
       Result := False;
@@ -507,9 +333,4 @@
   end;
 
-  if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
-    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
-  else
-    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
-
   with hdr do
   begin
@@ -519,5 +340,5 @@
       Size := 124;
       Flags := DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or DDSD_HEIGHT;
-      if FStoreType = 9 then
+      if _storetype = 9 then
         Flags := Flags or DDSD_LINEARSIZE
       else
@@ -525,19 +346,22 @@
       if (imginfo and $01) > 0 then
         Flags := Flags or DDSD_MIPMAPCOUNT;
-      Height := FHeight;
-      Width := FWidth;
-      if FStoreType = 9 then
-        PitchOrLinearSize := FWidth * FHeight div 2
+      Height := _height;
+      Width := _width;
+      if _storetype = 9 then
+        PitchOrLinearSize := width * height div 2
       else
-        PitchOrLinearSize := FWidth * FDepth div 2;
+        PitchOrLinearSize := width * _depth div 8;
       Depth := 0;
       MipMapCount := 1;
-      x := FWidth;
-      y := FHeight;
-      while (x > 1) and (y > 1) do
+      if (imginfo and $01) > 0 then
       begin
-        x := x div 2;
-        y := y div 2;
-        Inc(MipMapCount);
+        x := width;
+        y := height;
+        while (x > 1) and (y > 1) do
+        begin
+          x := x div 2;
+          y := y div 2;
+          Inc(MipMapCount);
+        end;
       end;
       for i := 1 to 11 do
@@ -546,19 +370,67 @@
       begin
         Size := 32;
-        if FStoreType = 9 then
+        if _storetype = 9 then
           Flags := DDPF_FOURCC
         else
           Flags := DDPF_RGB;
+        if _storetype in [0, 2] then
+          Flags := Flags or DDPF_ALPHAPIXELS;
+        if _storetype = 9 then
+          FOURCC := 'DXT1'
+        else
+        begin
+          RGBBitCount := _depth;
+          case _storetype of
+            0: begin
+              RBitMask := $0F00;
+              GBitMask := $00F0;
+              BBitMask := $000F;
+              AlphaBitMask := $F000;
+            end;
+            1, 2: begin
+              RBitMask := $7C00;
+              GBitMask := $03E0;
+              BBitMask := $001F;
+              if _storetype = 2 then
+                AlphaBitMask := $8000
+              else
+                AlphaBitMask := $0000;
+            end;
+            8: begin
+              RBitMask := $00FF0000;
+              GBitMask := $0000FF00;
+              BBitMask := $000000FF;
+              AlphaBitMask := $00000000;
+            end;
+          end;
+        end;
       end;
-    end;
-  end; 
-  LoadImageFromStream(data, FImage);
-{
+      with DDSCAPS2 do
+      begin
+        Caps1 := DDSCAPS_TEXTURE;
+        if (imginfo and $01) > 0 then
+          Caps1 := Caps1 or DDSCAPS_COMPLEX or DDSCAPS_MIPMAP;
+        Caps2 := 0;
+        Reserved[1] := 0;
+        Reserved[2] := 0;
+      end;
+    end;
+  end;
+
+  data := TMemoryStream.Create;
+  data.Write(hdr, SizeOf(hdr));
   if ConManager.Connection[ConnectionID].DataOS = DOS_WIN then
-    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, FData)
-  else
-    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, FData);
-}
-  Self.FDataType := [DT_OniReverted, DT_Oni];
+    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $9C, TStream(data))
+  else
+    ConManager.Connection[ConnectionID].LoadRawFile(fileid, $A0, TStream(data));
+  data.Seek(0, soFromBeginning);
+  result := LoadMultiImageFromStream(data, FImages);
+  data.Free;
+
+  if not result then
+  begin
+    ShowMessage('Error while loading file' + #13#10 + DetermineStreamFormat(data));
+//    data.SaveToFile('m:\prob.dds');
+  end;
 end;
 
@@ -572,351 +444,129 @@
   linkcount: Integer;
   link: Integer;
-  images_decoded: array of TOniImage;
+  images: array of TOniImage;
   x_start, y_start: Integer;
-begin
-  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(Self.FWidth), @Self.FWidth);
-  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(Self.FHeight), @Self.FHeight);
+
+  width, height: Word;
+begin
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $10, SizeOf(width), @width);
+  ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $12, SizeOf(height), @height);
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $18, SizeOf(cols), @cols);
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1A, SizeOf(rows), @rows);
   ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $1C, SizeOf(linkcount), @linkcount);
-  SetLength(images_decoded, linkcount);
+  SetLength(images, linkcount);
   for i := 0 to linkcount - 1 do
   begin
     ConManager.Connection[ConnectionID].LoadDatFilePart(fileid, $20 + i * 4, SizeOf(link), @link);
     link := link div 256;
-    images_decoded[i] := TOniImage.Create;
-    images_decoded[i].LoadFromTXMP(ConnectionID, link);
-    images_decoded[i].DecodeImageTo32bit;
-    images_decoded[i].RevertImage;
-  end;
-  SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+    images[i] := TOniImage.Create;
+    images[i].LoadFromTXMP(ConnectionID, link);
+    SetLength(FImages, 1);
+    NewImage(width, height, ifA1R5G5B5, FImages[0]);
+  end;
   for y := 0 to rows - 1 do
   begin
     for x := 0 to cols - 1 do
     begin
-      imgid   := y * cols + x;
+      imgid := y * cols + x;
       x_start := 0;
       y_start := 0;
       for i := 0 to x do
         if i < x then
-          x_start := x_start + images_decoded[i].Width;
+          x_start := x_start + images[i].Image[0].Width;
       for i := 0 to y do
         if i < y then
-          y_start := y_start + images_decoded[i].Height;
-      for y2 := 0 to images_decoded[imgid].Height - 1 do
+          y_start := y_start + images[i].Image[0].Height;
+      CopyRect(images[imgid].Image[0], 0, 0, images[imgid].Image[0].Width,
+          images[imgid].Image[0].Height, FImages[0], x_start, y_start);
+    end;
+  end;
+  for i := 0 to linkcount - 1 do
+    images[i].Free;
+end;
+
+
+
+procedure TOniImage.SaveDataToStream(MipMaps: Boolean; var Target: TStream);
+var
+  images: TDynImageDataArray;
+  mem: TMemoryStream;
+  i: Integer;
+begin
+  if Length(FImages) = 0 then
+    Exit;
+  if MipMaps then
+  begin
+    if Length(FImages) = 1 then
+    begin
+      if not GenerateMipMaps(FImages[0], 0, images) then
       begin
-        for x2 := 0 to images_decoded[imgid].Width - 1 do
-        begin
-          if ((x_start + x2) < Self.FWidth) and ((y_start + y2) < Self.FHeight) then
-          begin
-            pixelid := y_start * Self.FWidth + x_start + y2 * Self.FWidth + x2;
-            Self.FData[pixelid * 4 + 0] :=
-              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 0];
-            Self.FData[pixelid * 4 + 1] :=
-              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 1];
-            Self.FData[pixelid * 4 + 2] :=
-              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 2];
-            Self.FData[pixelid * 4 + 3] :=
-              images_decoded[imgid].Data[(y2 * images_decoded[imgid].Width + x2) * 4 + 3];
-          end;
-        end;
+        ShowMessage('Could not generate MipMaps');
+        Exit;
       end;
-    end;
-  end;
-  for i := 0 to linkcount - 1 do
-    images_decoded[i].Free;
-  Self.FDepth     := 32;
-  Self.FStoreType := 8;
-  Self.FDataType  := [DT_Decoded32];
-  Self.RevertImage;
-end;
-
-
-
-function TOniImage.GetImgSize(w,h, storetype: Integer): Integer;
-begin
-  case storetype of
-    0, 1, 2:
-      Result := w*h*2;
-    8:
-      Result := w*h*4;
-    9:
-      Result := Max(1, w div 4) * Max(1, h div 4) * 8;
-  else
-    Result := -1;
-  end;
-end;
-
-
-function TOniImage.GetImageDataSize(fading: Boolean): Integer;
-var
-  size: Integer;
-  x, y: Word;
-begin
-  x    := Self.FWidth;
-  y    := Self.FHeight;
-  size := GetImgSize(x, y, FStoreType);
-  if fading then
-  begin
-    repeat
-      x    := Max(x div 2, 1);
-      y    := Max(y div 2, 1);
-      size := size + GetImgSize(x, y, FStoreType);
-    until (x = 1) and (y = 1);
-  end;
-  Result := size;
-end;
-
-
-
-
-procedure TOniImage.GetAsData(var Target: TStream);
-var
-  revert: Boolean;
-begin
-  //    if not (DT_Decoded32 in Self.FDataType) then
-  //      Self.DecodeImage;
-  if not (DT_OniReverted in Self.FDataType) then
-  begin
-    revert := True;
-    Self.RevertImage;
+    end
+    else
+    begin
+      SetLength(images, Length(FImages));
+      for i := 0 to High(FImages) do
+        CloneImage(FImages[i], images[i]);
+    end;
+    mem := TMemoryStream.Create;
+    if not SaveMultiImageToStream('dds', mem, images) then
+    begin
+      ShowMessage('Could not save images to stream');
+      Exit;
+    end;
+    FreeImagesInArray(images);
   end
   else
-    revert := False;
+  begin
+    mem := TMemoryStream.Create;
+    if not SaveImageToStream('dds', mem, FImages[0]) then
+    begin
+      ShowMessage('Could not save image to stream');
+      Exit;
+    end;
+  end;
   if not Assigned(Target) then
     Target := TMemoryStream.Create;
-  Target.Write(FData[0], Length(FData));
+
+//  mem.Seek(0, soFromBeginning);
+//  mem.SaveToFile('m:\dds.dds');
+
+  mem.Seek(128, soFromBeginning);
+  Target.CopyFrom(mem, mem.Size - 128);
+  mem.Free;
   Target.Seek(0, soFromBeginning);
-  if revert then
-    Self.RevertImage;
-end;
-
-procedure TOniImage.GetAsData(var Target: TByteData);
-var
-  mem: TStream;
-begin
-  mem := TMemoryStream.Create;
-  GetAsData(mem);
-  SetLength(Target, mem.Size);
-  mem.Read(Target[0], mem.Size);
-  mem.Free;
-end;
-
-
-procedure TOniImage.GetAs32bit(var Target: TStream);
-begin
-  if not (DT_Decoded32 in Self.FDataType) then
-    Self.DecodeImageTo32bit;
-  if not Assigned(Target) then
-    Target := TMemoryStream.Create;
-  Target.Write(FData[0], Length(FData));
-  Target.Seek(0, soFromBeginning);
-end;
-
-procedure TOniImage.GetAs32bit(var Target: TByteData);
-var
-  mem: TStream;
-begin
-  mem := TMemoryStream.Create;
-  GetAs32bit(mem);
-  SetLength(Target, mem.Size);
-  mem.Read(Target[0], mem.Size);
-  mem.Free;
-end;
-
-
-procedure TOniImage.GetAsBMP(var Target: TByteData);
-const
-  BMPheader: array[0..53] of Byte =
-    ($42, $4D, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0,
-    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,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-var
-  i, x, y: Integer;
-begin
-  if not (DT_Decoded32 in Self.FDataType) then
-    Self.DecodeImageTo32bit;
-
-  SetLength(Target, Self.FWidth * Self.FHeight * 3 + 54);
-  for y := 0 to Self.FHeight - 1 do
-  begin
-    for x := 0 to Self.FWidth - 1 do
-    begin
-      Target[((Self.FWidth * y + x) * 3) + 0 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 0];
-      Target[((Self.FWidth * y + x) * 3) + 1 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 1];
-      Target[((Self.FWidth * y + x) * 3) + 2 + 54] := Self.FData[(Self.FWidth * y + x) * 4 + 2];
-    end;
-  end;
-
-  for i := 0 to High(BMPheader) do
-    Target[i] := BMPheader[i];
-  Target[2] := ((Self.FWidth * Self.FHeight * 3 + 54) and $000000FF) div $1;
-  Target[3]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $0000FF00) div $100;
-  Target[4]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $00FF0000) div $10000;
-  Target[5]  := ((Self.FWidth * Self.FHeight * 3 + 54) and $FF000000) div $1000000;
-  Target[18] := (Self.FWidth and $000000FF) div $1;
-  Target[19] := (Self.FWidth and $0000FF00) div $100;
-  Target[20] := (Self.FWidth and $00FF0000) div $10000;
-  Target[21] := (Self.FWidth and $FF000000) div $1000000;
-  Target[22] := (Self.FHeight and $000000FF) div $1;
-  Target[23] := (Self.FHeight and $0000FF00) div $100;
-  Target[24] := (Self.FHeight and $00FF0000) div $10000;
-  Target[25] := (Self.FHeight and $FF000000) div $1000000;
-  Target[34] := ((Self.FWidth * Self.FHeight * 3) and $000000FF) div $1;
-  Target[35] := ((Self.FWidth * Self.FHeight * 3) and $0000FF00) div $100;
-  Target[36] := ((Self.FWidth * Self.FHeight * 3) and $00FF0000) div $10000;
-  Target[37] := ((Self.FWidth * Self.FHeight * 3) and $FF000000) div $1000000;
-end;
-
-
-procedure TOniImage.GetAsBMP(var Target: TStream);
-var
-  data: TByteData;
-  streampos: Integer;
-begin
-  GetAsBMP(data);
-  streampos := Target.Position;
-  Target.Write(data[0], Length(data));
-  Target.Seek(streampos, soFromBeginning);
-end;
-
-
-function TOniImage.LoadFromBMP(filename: String): Boolean;
-var
-  filestream: TFileStream;
-  tempd:      TByteData;
-
-  x, y: Integer;
-begin
-  filestream := TFileStream.Create(filename, fmOpenRead);
-  SetLength(tempd, filestream.Size);
-  filestream.Read(tempd[0], filestream.Size);
-  filestream.Free;
-
-  if not ((tempd[00] = $42) and (tempd[01] = $4D)) then
-  begin
-    Result := False;
-    ShowMessage('Not a standard 24bit bitmap');
-    Exit;
-  end;
-  if not (tempd[10] = 54) then
-  begin
-    Result := False;
-    ShowMessage('Imagedata has to start at 0x54');
-    Exit;
-  end;
-  if not (tempd[14] = 40) then
-  begin
-    Result := False;
-    ShowMessage('Second bitmap header has to have 40 bytes');
-    Exit;
-  end;
-  if not (tempd[28] = 24) then
-  begin
-    Result := False;
-    ShowMessage('Bitmap has to have 24bits');
-    Exit;
-  end;
-  if not (tempd[30] = 0) then
-  begin
-    Result := False;
-    ShowMessage('Bitmap has to be uncompressed');
-    Exit;
-  end;
-
-  Self.FWidth     := tempd[18] + tempd[19] * 256 + tempd[20] * 256 * 256 + tempd[21] * 256 * 256 * 256;
-  Self.FHeight    := tempd[22] + tempd[23] * 256 + tempd[24] * 256 * 256 + tempd[25] * 256 * 256 * 256;
-  Self.FDepth     := 32;
-  Self.FStoreType := 8;
-
-  SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
-  for y := 0 to Self.FHeight - 1 do
-  begin
-    for x := 0 to Self.FWidth - 1 do
-    begin
-      Self.FData[((Self.FWidth * y + x) * 4) + 0] := tempd[54 + (Self.FWidth * y + x) * 3 + 0];
-      Self.FData[((Self.FWidth * y + x) * 4) + 1] := tempd[54 + (Self.FWidth * y + x) * 3 + 1];
-      Self.FData[((Self.FWidth * y + x) * 4) + 2] := tempd[54 + (Self.FWidth * y + x) * 3 + 2];
-      Self.FData[((Self.FWidth * y + x) * 4) + 3] := 0;
-    end;
-  end;
-
-  Self.FDataType := [DT_Decoded32];
-end;
-
-
-
-
-function TOniImage.WriteToBMP(filename: String): Boolean;
-var
-  filestream: TFileStream;
-begin
-  filestream := TFileStream.Create(filename, fmCreate);
-  GetAsBMP(TStream(filestream));
-  filestream.Free;
-end;
-
-
-
-function TOniImage.GetMipMappedImage(var Target: TByteData): Boolean;
-var
-  i:      Integer;
-  x, y:   Word;
-  fadelvldata: TByteData;
-  revert: Boolean;
-begin
-  Result := False;
-
-  //    if not (DT_Decoded32 in Self.FDataType) then
-  //      Self.DecodeImage;
-  if Self.FStoreType = 9 then
-    Self.DecompressImage;
-  if not (DT_OniReverted in Self.FDataType) then
-  begin
-    revert := True;
-    Self.RevertImage;
+end;
+
+
+function TOniImage.LoadFromFile(filename: String): Boolean;
+begin
+  if not LoadMultiImageFromFile(filename, FImages) then
+    ShowMessage('Couldn''t load image file');
+end;
+
+
+function TOniImage.WriteToFile(filename: String): Boolean;
+begin
+  SaveMultiImageToFile(filename, FImages);
+end;
+
+
+
+function TOniImage.GetImageSize(MipMaps: Boolean): Integer;
+var
+  i: Integer;
+begin
+  if Length(FImages) > 0 then
+  begin
+    Result := FImages[0].Size;
+    if mipmaps then
+      for i := 1 to High(FImages) do
+        Result := Result + FImages[i].Size;
   end
   else
-    revert := False;
-
-  x := Self.FWidth;
-  y := Self.FHeight;
-  SetLength(Target, x * y * Self.FDepth div 8);
-  SetLength(fadelvldata, x * y * Self.FDepth div 8);
-  for i := 0 to Length(Target) - 1 do
-  begin
-    Target[i] := Self.FData[i];
-    fadelvldata[i] := Self.FData[i];
-  end;
-  repeat
-    fadelvldata := Self.ResizeImage(x, y, fadelvldata);
-    x := x div 2;
-    y := y div 2;
-    SetLength(Target, Length(Target) + x * y * Self.FDepth div 8);
-    for i := 0 to Length(fadelvldata) - 1 do
-      Target[Length(Target) - x * y * Self.FDepth div 8 + i] := fadelvldata[i];
-  until (x = 1) or (y = 1) or ((x mod 2) = 1) or ((y mod 2) = 1);
-  if (x > 1) and (y > 1) then
-    Exit;
-  Result := True;
-
-  if revert then
-    Self.RevertImage;
-end;
-
-
-function TOniImage.GetMipMappedImage(var Target: TStream): Boolean;
-var
-  data: TByteData;
-  streampos: Integer;
-begin
-  Result := GetMipMappedImage(data);
-  if not Assigned(Target) then
-    Target := TMemoryStream.Create;
-  streampos := Target.Position;
-  Target.Write(data[0], Length(data));
-  Target.Seek(streampos, soFromBeginning);
-end;
-
+    Result := -1;
+end;
 
 end.
