* refactored LoadDDS
[LazOpenGLCore.git] / glBitmap.pas
index 74b9233..72c81e0 100644 (file)
@@ -645,7 +645,11 @@ type
 
     tfDepth16,
     tfDepth24,
-    tfDepth32
+    tfDepth32,
+
+    tfS3tcDtx1RGBA,
+    tfS3tcDtx3RGBA,
+    tfS3tcDtx5RGBA
   );
 
   TglBitmapFileType = (
@@ -1004,6 +1008,7 @@ procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
 
 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
 function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
+function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
 
 var
   glBitmapDefaultDeleteTextureOnFree: Boolean;
@@ -1052,7 +1057,10 @@ type
     fFormat: TglBitmapFormat;
     fWithAlpha: TglBitmapFormat;
     fWithoutAlpha: TglBitmapFormat;
+    fRGBInverted: TglBitmapFormat;
+    fUncompressed: TglBitmapFormat;
     fPixelSize: Single;
+    fIsCompressed: Boolean;
 
     fRange: TglBitmapColorRec;
     fShift: TShiftRec;
@@ -1066,8 +1074,10 @@ type
     property Format:       TglBitmapFormat read fFormat;
     property WithAlpha:    TglBitmapFormat read fWithAlpha;
     property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
+    property RGBInverted:  TglBitmapFormat read fRGBInverted;
     property Components:   Integer         read GetComponents;
     property PixelSize:    Single          read fPixelSize;
+    property IsCompressed: Boolean         read fIsCompressed;
 
     property glFormat:         Cardinal read fglFormat;
     property glInternalFormat: Cardinal read fglInternalFormat;
@@ -1410,8 +1420,26 @@ type
     constructor Create; override;
   end;
 
+  TfdS3tcDtx1RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
+  TfdS3tcDtx3RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
+  TfdS3tcDtx5RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-  TBitfieldFormat = class(TFormatDescriptor)
+  TbmpBitfieldFormat = class(TFormatDescriptor)
   private
     procedure SetRedMask  (const aValue: UInt64);
     procedure SetGreenMask(const aValue: UInt64);
@@ -1432,17 +1460,21 @@ type
   end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-  TColorTableEnty = packed record
+  TbmpColorTableEnty = packed record
     b, g, r, a: Byte;
   end;
-  TColorTable = array of TColorTableEnty;
-  TColorTableFormat = class(TFormatDescriptor)
+  TbmpColorTable = array of TbmpColorTableEnty;
+  TbmpColorTableFormat = class(TFormatDescriptor)
   private
-    fColorTable: TColorTable;
+    fColorTable: TbmpColorTable;
   public
     property PixelSize:  Single            read fPixelSize  write fPixelSize;
-    property ColorTable: TColorTable       read fColorTable write fColorTable;
+    property ColorTable: TbmpColorTable    read fColorTable write fColorTable;
     property Range:      TglBitmapColorRec read fRange      write fRange;
+    property Shift:      TShiftRec         read fShift      write fShift;
+    property Format:     TglBitmapFormat   read fFormat     write fFormat;
+
+    procedure CreateColorTable;
 
     procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
     procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
@@ -1519,7 +1551,11 @@ const
 
     TfdDepth16,
     TfdDepth24,
-    TfdDepth32
+    TfdDepth32,
+
+    TfdS3tcDtx1RGBA,
+    TfdS3tcDtx3RGBA,
+    TfdS3tcDtx5RGBA
   );
 
 var
@@ -1550,10 +1586,68 @@ begin
 end;
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean;
+var
+  i: Integer;
+begin
+  result := false;
+  for i := 0 to high(r1.arr) do
+    if (r1.arr[i] <> r2.arr[i]) then
+      exit;
+  result := true;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec;
+begin
+  result.r := r;
+  result.g := g;
+  result.b := b;
+  result.a := a;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
 begin
+  result := [ftDDS];
+
+  if (aFormat in [
+        //4 bbp
+        tfLuminance4,
+
+        //8bpp
+        tfR3G3B2, tfLuminance8,
+
+        //16bpp
+        tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
+        tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4,
+
+        //24bpp
+        tfBGR8, tfRGB8,
+
+        //32bpp
+        tfRGB10, tfRGB10A2, tfRGBA8,
+        tfBGR10, tfBGR10A2, tfBGRA8]) then
+    result := result + [ftBMP];
+
+  if (aFormat in [
+        //8 bpp
+        tfLuminance8, tfAlpha8,
+
+        //16 bpp
+        tfLuminance16, tfLuminance8Alpha8,
+        tfRGB5, tfRGB5A1, tfRGBA4,
+        tfBGR5, tfBGR5A1, tfBGRA4,
+
+        //24 bpp
+        tfRGB8, tfBGR8,
+
+        //32 bpp
+        tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then
+    result := result + [ftTGA];
+
   //TODO Supported File Formats!
-  result := [ftDDS, ftTGA, ftBMP];
+
   (*
   {$IFDEF GLB_SUPPORT_PNG_WRITE}
   if aFormat in [
@@ -2170,7 +2264,10 @@ begin
   fFormat       := tfEmpty;
   fWithAlpha    := tfEmpty;
   fWithoutAlpha := tfEmpty;
+  fRGBInverted  := tfEmpty;
+  fUncompressed := tfEmpty;
   fPixelSize    := 0.0;
+  fIsCompressed := false;
 
   fglFormat         := 0;
   fglInternalFormat := 0;
@@ -2898,6 +2995,7 @@ begin
   fFormat           := tfRGB4;
   fWithAlpha        := tfRGBA4;
   fWithoutAlpha     := tfRGB4;
+  fRGBInverted      := tfBGR4;
   fRange.r          := $F;
   fRange.g          := $F;
   fRange.b          := $F;
@@ -2915,6 +3013,7 @@ begin
   fFormat           := tfR5G6B5;
   fWithAlpha        := tfRGBA4;
   fWithoutAlpha     := tfR5G6B5;
+  fRGBInverted      := tfB5G6R5;
   fRange.r          := $1F;
   fRange.g          := $3F;
   fRange.b          := $1F;
@@ -2932,6 +3031,7 @@ begin
   fFormat           := tfRGB5;
   fWithAlpha        := tfRGB5A1;
   fWithoutAlpha     := tfRGB5;
+  fRGBInverted      := tfBGR5;
   fRange.r          := $1F;
   fRange.g          := $1F;
   fRange.b          := $1F;
@@ -2949,6 +3049,7 @@ begin
   fFormat           := tfRGB8;
   fWithAlpha        := tfRGBA8;
   fWithoutAlpha     := tfRGB8;
+  fRGBInverted      := tfBGR8;
   fglInternalFormat := GL_RGB8;
 end;
 
@@ -2958,6 +3059,7 @@ begin
   fFormat           := tfRGB10;
   fWithAlpha        := tfRGB10A2;
   fWithoutAlpha     := tfRGB10;
+  fRGBInverted      := tfBGR10;
   fRange.r          := $3FF;
   fRange.g          := $3FF;
   fRange.b          := $3FF;
@@ -2975,6 +3077,7 @@ begin
   fFormat           := tfRGB12;
   fWithAlpha        := tfRGBA12;
   fWithoutAlpha     := tfRGB12;
+  fRGBInverted      := tfBGR12;
   fglInternalFormat := GL_RGB12;
 end;
 
@@ -2984,6 +3087,7 @@ begin
   fFormat           := tfRGB16;
   fWithAlpha        := tfRGBA16;
   fWithoutAlpha     := tfRGB16;
+  fRGBInverted      := tfBGR16;
   fglInternalFormat := GL_RGB16;
 end;
 
@@ -2993,6 +3097,7 @@ begin
   fFormat           := tfRGBA2;
   fWithAlpha        := tfRGBA2;
   fWithoutAlpha     := tfR3G3B2;
+  fRGBInverted      := tfBGRA2;
   fglInternalFormat := GL_RGBA2;
 end;
 
@@ -3002,6 +3107,7 @@ begin
   fFormat           := tfRGBA4;
   fWithAlpha        := tfRGBA4;
   fWithoutAlpha     := tfRGB4;
+  fRGBInverted      := tfBGRA4;
   fRange.r          := $F;
   fRange.g          := $F;
   fRange.b          := $F;
@@ -3021,6 +3127,7 @@ begin
   fFormat           := tfRGB5A1;
   fWithAlpha        := tfRGB5A1;
   fWithoutAlpha     := tfRGB5;
+  fRGBInverted      := tfBGR5A1;
   fRange.r          := $1F;
   fRange.g          := $1F;
   fRange.b          := $1F;
@@ -3040,6 +3147,7 @@ begin
   fFormat           := tfRGBA8;
   fWithAlpha        := tfRGBA8;
   fWithoutAlpha     := tfRGB8;
+  fRGBInverted      := tfBGRA8;
   fglInternalFormat := GL_RGBA8;
 end;
 
@@ -3049,6 +3157,7 @@ begin
   fFormat           := tfRGB10A2;
   fWithAlpha        := tfRGB10A2;
   fWithoutAlpha     := tfRGB10;
+  fRGBInverted      := tfBGR10A2;
   fRange.r          := $3FF;
   fRange.g          := $3FF;
   fRange.b          := $3FF;
@@ -3068,6 +3177,7 @@ begin
   fFormat           := tfRGBA12;
   fWithAlpha        := tfRGBA12;
   fWithoutAlpha     := tfRGB12;
+  fRGBInverted      := tfBGRA12;
   fglInternalFormat := GL_RGBA12;
 end;
 
@@ -3077,6 +3187,7 @@ begin
   fFormat           := tfRGBA16;
   fWithAlpha        := tfRGBA16;
   fWithoutAlpha     := tfRGB16;
+  fRGBInverted      := tfBGRA16;
   fglInternalFormat := GL_RGBA16;
 end;
 
@@ -3087,6 +3198,7 @@ begin
   fFormat           := tfBGR4;
   fWithAlpha        := tfBGRA4;
   fWithoutAlpha     := tfBGR4;
+  fRGBInverted      := tfRGB4;
   fRange.r          := $F;
   fRange.g          := $F;
   fRange.b          := $F;
@@ -3109,6 +3221,7 @@ begin
   fFormat           := tfB5G6R5;
   fWithAlpha        := tfBGRA4;
   fWithoutAlpha     := tfB5G6R5;
+  fRGBInverted      := tfR5G6B5;
   fRange.r          := $1F;
   fRange.g          := $3F;
   fRange.b          := $1F;
@@ -3120,9 +3233,6 @@ begin
   fglDataFormat     := GL_UNSIGNED_SHORT_5_6_5;
 end;
 
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 constructor TfdBGR5.Create;
 begin
   inherited Create;
@@ -3130,6 +3240,7 @@ begin
   fFormat           := tfBGR5;
   fWithAlpha        := tfBGR5A1;
   fWithoutAlpha     := tfBGR5;
+  fRGBInverted      := tfRGB5;
   fRange.r          := $1F;
   fRange.g          := $1F;
   fRange.b          := $1F;
@@ -3149,6 +3260,7 @@ begin
   fFormat           := tfBGR8;
   fWithAlpha        := tfBGRA8;
   fWithoutAlpha     := tfBGR8;
+  fRGBInverted      := tfRGB8;
   fglInternalFormat := GL_RGB8;
 end;
 
@@ -3158,6 +3270,7 @@ begin
   fFormat           := tfBGR10;
   fWithAlpha        := tfBGR10A2;
   fWithoutAlpha     := tfBGR10;
+  fRGBInverted      := tfRGB10;
   fRange.r          := $3FF;
   fRange.g          := $3FF;
   fRange.b          := $3FF;
@@ -3177,6 +3290,7 @@ begin
   fFormat           := tfBGR12;
   fWithAlpha        := tfBGRA12;
   fWithoutAlpha     := tfBGR12;
+  fRGBInverted      := tfRGB12;
   fglInternalFormat := GL_RGB12;
 end;
 
@@ -3186,6 +3300,7 @@ begin
   fFormat           := tfBGR16;
   fWithAlpha        := tfBGRA16;
   fWithoutAlpha     := tfBGR16;
+  fRGBInverted      := tfRGB16;
   fglInternalFormat := GL_RGB16;
 end;
 
@@ -3195,6 +3310,7 @@ begin
   fFormat           := tfBGRA2;
   fWithAlpha        := tfBGRA4;
   fWithoutAlpha     := tfBGR4;
+  fRGBInverted      := tfRGBA2;
   fglInternalFormat := GL_RGBA2;
 end;
 
@@ -3204,6 +3320,7 @@ begin
   fFormat           := tfBGRA4;
   fWithAlpha        := tfBGRA4;
   fWithoutAlpha     := tfBGR4;
+  fRGBInverted      := tfRGBA4;
   fRange.r          := $F;
   fRange.g          := $F;
   fRange.b          := $F;
@@ -3223,6 +3340,7 @@ begin
   fFormat           := tfBGR5A1;
   fWithAlpha        := tfBGR5A1;
   fWithoutAlpha     := tfBGR5;
+  fRGBInverted      := tfRGB5A1;
   fRange.r          := $1F;
   fRange.g          := $1F;
   fRange.b          := $1F;
@@ -3242,6 +3360,7 @@ begin
   fFormat           := tfBGRA8;
   fWithAlpha        := tfBGRA8;
   fWithoutAlpha     := tfBGR8;
+  fRGBInverted      := tfRGBA8;
   fglInternalFormat := GL_RGBA8;
 end;
 
@@ -3251,6 +3370,7 @@ begin
   fFormat           := tfBGR10A2;
   fWithAlpha        := tfBGR10A2;
   fWithoutAlpha     := tfBGR10;
+  fRGBInverted      := tfRGB10A2;
   fRange.r          := $3FF;
   fRange.g          := $3FF;
   fRange.b          := $3FF;
@@ -3270,6 +3390,7 @@ begin
   fFormat           := tfBGRA12;
   fWithAlpha        := tfBGRA12;
   fWithoutAlpha     := tfBGR12;
+  fRGBInverted      := tfRGBA12;
   fglInternalFormat := GL_RGBA12;
 end;
 
@@ -3279,6 +3400,7 @@ begin
   fFormat           := tfBGRA16;
   fWithAlpha        := tfBGRA16;
   fWithoutAlpha     := tfBGR16;
+  fRGBInverted      := tfRGBA16;
   fglInternalFormat := GL_RGBA16;
 end;
 
@@ -3310,6 +3432,84 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx1RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx1RGBA;
+  fWithAlpha        := tfS3tcDtx1RGBA;
+  fUncompressed     := tfRGB5A1;
+  fPixelSize        := 0.5;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx3RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx3RGBA;
+  fWithAlpha        := tfS3tcDtx3RGBA;
+  fUncompressed     := tfRGBA8;
+  fPixelSize        := 1.0;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx5RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx3RGBA;
+  fWithAlpha        := tfS3tcDtx3RGBA;
+  fUncompressed     := tfRGBA8;
+  fPixelSize        := 1.0;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 class procedure TFormatDescriptor.Init;
@@ -3363,31 +3563,31 @@ end;
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.SetRedMask(const aValue: UInt64);
+procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64);
 begin
   Update(aValue, fRange.r, fShift.r);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.SetGreenMask(const aValue: UInt64);
+procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64);
 begin
   Update(aValue, fRange.g, fShift.g);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.SetBlueMask(const aValue: UInt64);
+procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64);
 begin
   Update(aValue, fRange.b, fShift.b);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.SetAlphaMask(const aValue: UInt64);
+procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64);
 begin
   Update(aValue, fRange.a, fShift.a);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
+procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
   aShift: Byte);
 begin
   aShift := 0;
@@ -3409,7 +3609,7 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 var
   data: UInt64;
   s: Integer;
@@ -3434,7 +3634,7 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+procedure TbmpBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 var
   data: UInt64;
   s, i: Integer;
@@ -3458,12 +3658,87 @@ end;
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+procedure TbmpColorTableFormat.CreateColorTable;
+var
+  bits: Byte;
+  len: Integer;
+  i: Integer;
 begin
-  raise EglBitmapException.Create('mapping of color table formats is not supported');
+  if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
+    raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
+
+  if (Format = tfLuminance4) then
+    SetLength(fColorTable, 16)
+  else
+    SetLength(fColorTable, 256);
+
+  case Format of
+    tfLuminance4: begin
+      for i := 0 to High(fColorTable) do begin
+        fColorTable[i].r := 16 * i;
+        fColorTable[i].g := 16 * i;
+        fColorTable[i].b := 16 * i;
+        fColorTable[i].a := 0;
+      end;
+    end;
+
+    tfLuminance8: begin
+      for i := 0 to High(fColorTable) do begin
+        fColorTable[i].r := i;
+        fColorTable[i].g := i;
+        fColorTable[i].b := i;
+        fColorTable[i].a := 0;
+      end;
+    end;
+
+    tfR3G3B2: begin
+      for i := 0 to High(fColorTable) do begin
+        fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255);
+        fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255);
+        fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255);
+        fColorTable[i].a := 0;
+      end;
+    end;
+  end;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+var
+  d: Byte;
+begin
+  if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then
+    raise EglBitmapException.Create(UNSUPPORTED_FORMAT);
+
+  case Format of
+    tfLuminance4: begin
+      if (aMapData = nil) then
+        aData^ := 0;
+      d := LuminanceWeight(aPixel) and Range.r;
+      aData^ := aData^ or (d shl (4 - PtrInt(aMapData)));
+      inc(aMapData, 4);
+      if (PtrInt(aMapData) >= 8) then begin
+        inc(aData);
+        aMapData := nil;
+      end;
+    end;
+
+    tfLuminance8: begin
+      aData^ := LuminanceWeight(aPixel) and Range.r;
+      inc(aData);
+    end;
+
+    tfR3G3B2: begin
+      aData^ := Round(
+        ((aPixel.Data.r and Range.r) shl Shift.r) or
+        ((aPixel.Data.g and Range.g) shl Shift.g) or
+        ((aPixel.Data.b and Range.b) shl Shift.b));
+      inc(aData);
+    end;
+  end;
 end;
 
-procedure TColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 type
   PUInt64 = ^UInt64;
 var
@@ -3500,7 +3775,7 @@ begin
   inc(aData, s);
 end;
 
-destructor TColorTableFormat.Destroy;
+destructor TbmpColorTableFormat.Destroy;
 begin
   SetLength(fColorTable, 0);
   inherited Destroy;
@@ -3892,6 +4167,8 @@ procedure TglBitmap.LoadFromFile(const aFilename: String);
 var
   fs: TFileStream;
 begin
+  if not FileExists(aFilename) then
+    raise EglBitmapException.Create('file does not exist: ' + aFilename);
   fFilename := aFilename;
   fs := TFileStream.Create(fFilename, fmOpenRead);
   try
@@ -5906,16 +6183,6 @@ type
     biClrImportant: Cardinal;
   end;
 
-  (* TODO: delete?
-  TBMPInfoOS = packed record
-    biSize: Cardinal;
-    biWidth: Longint;
-    biHeight: Longint;
-    biPlanes: Word;
-    biBitCount: Word;
-  end;
-  *)
-
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
 
@@ -5952,10 +6219,10 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
     end;
   end;
 
-  function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TColorTableFormat;
+  function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat;
   var
     i, c: Integer;
-    ColorTable: TColorTable;
+    ColorTable: TbmpColorTable;
   begin
     result := nil;
     if (aInfo.biBitCount >= 16) then
@@ -5966,20 +6233,20 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
       c := 1 shl aInfo.biBitCount;
     SetLength(ColorTable, c);
     for i := 0 to c-1 do begin
-      aStream.Read(ColorTable[i], SizeOf(TColorTableEnty));
+      aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty));
       if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
         aFormat := tfRGB8;
     end;
 
-    result := TColorTableFormat.Create;
+    result := TbmpColorTableFormat.Create;
     result.PixelSize  := aInfo.biBitCount / 8;
     result.ColorTable := ColorTable;
-    result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
+    result.Range      := glBitmapColorRec($FF, $FF, $FF, $00);
   end;
 
   //////////////////////////////////////////////////////////////////////////////////////////////////
   function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
-    const aInfo: TBMPInfo): TBitfieldFormat;
+    const aInfo: TBMPInfo): TbmpBitfieldFormat;
   var
     TmpFormat: TglBitmapFormat;
     FormatDesc: TFormatDescriptor;
@@ -5999,7 +6266,7 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
       if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
         aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
 
-      result := TBitfieldFormat.Create;
+      result := TbmpBitfieldFormat.Create;
       result.PixelSize := aInfo.biBitCount / 8;
       result.RedMask   := aMask.r;
       result.GreenMask := aMask.g;
@@ -6016,7 +6283,7 @@ var
   LineBuf, ImageData, TmpData: PByte;
   SourceMD, DestMD: Pointer;
   BmpFormat: TglBitmapFormat;
-  ColorTable: TColorTable;
+  ColorTable: TbmpColorTable;
 
   //records
   Mask: TglBitmapColorRec;
@@ -6134,12 +6401,15 @@ procedure TglBitmap.SaveBMP(const aStream: TStream);
 var
   Header: TBMPHeader;
   Info: TBMPInfo;
-  pData, pTemp: pByte;
+  Converter: TbmpColorTableFormat;
+  FormatDesc: TFormatDescriptor;
+  SourceFD, DestFD: Pointer;
+  pData, srcData, dstData, ConvertBuffer: pByte;
 
+  Pixel: TglBitmapPixelData;
   PixelFormat: TglBitmapPixelData;
-  FormatDesc: TFormatDescriptor;
-  ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
-  Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
+  ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx, i: Integer;
+  RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
 
   PaddingBuff: Cardinal;
 
@@ -6152,8 +6422,11 @@ begin
   if not (ftBMP in FormatGetSupportedFiles(Format)) then
     raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
 
-  ImageSize := TFormatDescriptor.Get(Format).GetSize(Dimension);
+  Converter  := nil;
+  FormatDesc := TFormatDescriptor.Get(Format);
+  ImageSize  := FormatDesc.GetSize(Dimension);
 
+  FillChar(Header, SizeOf(Header), 0);
   Header.bfType      := BMP_MAGIC;
   Header.bfSize      := SizeOf(Header) + SizeOf(Info) + ImageSize;
   Header.bfReserved1 := 0;
@@ -6167,100 +6440,142 @@ begin
   Info.biPlanes      := 1;
   Info.biCompression := BMP_COMP_RGB;
   Info.biSizeImage   := ImageSize;
-  case Format of
-    tfR3G3B2, tfLuminance8: begin
-      Info.biBitCount  :=  8;
-      Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
-    end;
 
-    tfRGB5, tfRGB5A1, tfR5G6B5, tfRGB4, tfRGBA4,
-    tfBGR5, tfBGR5A1, tfB5G6R5, tfBGR4, tfBGRA4: begin
-      Info.biBitCount    := 16;
-      Info.biCompression := BMP_COMP_BITFIELDS;
-    end;
-
-    tfBGR8, tfRGB8: begin
-      Info.biBitCount := 24;
-    end;
+  try
+    case Format of
+      tfLuminance4: begin
+        Info.biBitCount  := 4;
+        Header.bfSize    := Header.bfSize    + 16 * SizeOf(Cardinal);
+        Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
+        Converter           := TbmpColorTableFormat.Create;
+        Converter.PixelSize := 0.5;
+        Converter.Format    := Format;
+        Converter.Range     := glBitmapColorRec($F, $F, $F, $0);
+        Converter.CreateColorTable;
+      end;
 
-    tfRGB10, tfRGB10A2, tfRGBA8,
-    tfBGR10, tfBGR10A2, tfBGRA8: begin
-      Info.biBitCount    := 32;
-      Info.biCompression := BMP_COMP_BITFIELDS;
-    end;
-  else
-    raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
-  end;
-  Info.biXPelsPerMeter := 2835;
-  Info.biYPelsPerMeter := 2835;
+      tfR3G3B2, tfLuminance8: begin
+        Info.biBitCount  :=  8;
+        Header.bfSize    := Header.bfSize    + 256 * SizeOf(Cardinal);
+        Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
+        Converter           := TbmpColorTableFormat.Create;
+        Converter.PixelSize := 1;
+        Converter.Format    := Format;
+        if (Format = tfR3G3B2) then begin
+          Converter.Range := glBitmapColorRec($7, $7, $3, $0);
+          Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
+        end else
+          Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
+        Converter.CreateColorTable;
+      end;
 
-  // prepare bitmasks
-  if Info.biCompression = BMP_COMP_BITFIELDS then begin
-    Info.biSize      := Info.biSize      + 4 * SizeOf(Cardinal);
-    Header.bfSize    := Header.bfSize    + 4 * SizeOf(Cardinal);
-    Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
+      tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
+      tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin
+        Info.biBitCount    := 16;
+        Info.biCompression := BMP_COMP_BITFIELDS;
+      end;
 
-    FormatDesc := TFormatDescriptor.Get(Format);
-    RedMask   := FormatDesc.RedMask;
-    GreenMask := FormatDesc.GreenMask;
-    BlueMask  := FormatDesc.BlueMask;
-    AlphaMask := FormatDesc.AlphaMask;
-  end;
+      tfBGR8, tfRGB8: begin
+        Info.biBitCount := 24;
+      end;
 
-  // headers
-  aStream.Write(Header, SizeOf(Header));
-  aStream.Write(Info, SizeOf(Info));
-
-  // colortable
-  if Info.biBitCount = 8 then begin
-    Temp := 0;
-    for ColorIdx := Low(Byte) to High(Byte) do begin
-      aStream.Write(Temp, 4);
-      Temp := Temp + $00010101;
+      tfRGB10, tfRGB10A2, tfRGBA8,
+      tfBGR10, tfBGR10A2, tfBGRA8: begin
+        Info.biBitCount    := 32;
+        Info.biCompression := BMP_COMP_BITFIELDS;
+      end;
+    else
+      raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
+    end;
+    Info.biXPelsPerMeter := 2835;
+    Info.biYPelsPerMeter := 2835;
+
+    // prepare bitmasks
+    if Info.biCompression = BMP_COMP_BITFIELDS then begin
+      Header.bfSize    := Header.bfSize    + 4 * SizeOf(Cardinal);
+      Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal);
+
+      RedMask    := FormatDesc.RedMask;
+      GreenMask  := FormatDesc.GreenMask;
+      BlueMask   := FormatDesc.BlueMask;
+      AlphaMask  := FormatDesc.AlphaMask;
     end;
-  end;
-
-  // bitmasks
-  if Info.biCompression = BMP_COMP_BITFIELDS then begin
-    aStream.Write(RedMask,   SizeOf(Cardinal));
-    aStream.Write(GreenMask, SizeOf(Cardinal));
-    aStream.Write(BlueMask,  SizeOf(Cardinal));
-    aStream.Write(AlphaMask, SizeOf(Cardinal));
-  end;
-
-  // image data
-  LineSize := Trunc(Width * TFormatDescriptor.Get(Format).PixelSize);
-  Padding := GetLineWidth - LineSize;
-  PaddingBuff := 0;
 
-  pData := Data;
-  Inc(pData, (Height -1) * LineSize);
+    // headers
+    aStream.Write(Header, SizeOf(Header));
+    aStream.Write(Info, SizeOf(Info));
+
+    // colortable
+    if Assigned(Converter) then
+      aStream.Write(Converter.ColorTable[0].b,
+        SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
+
+    // bitmasks
+    if Info.biCompression = BMP_COMP_BITFIELDS then begin
+      aStream.Write(RedMask,   SizeOf(Cardinal));
+      aStream.Write(GreenMask, SizeOf(Cardinal));
+      aStream.Write(BlueMask,  SizeOf(Cardinal));
+      aStream.Write(AlphaMask, SizeOf(Cardinal));
+    end;
 
-  // prepare row buffer. But only for RGB because RGBA supports color masks
-  // so it's possible to change color within the image.
-  if (Format = tfRGB8) then
-    GetMem(pTemp, fRowSize)
-  else
-    pTemp := nil;
+    // image data
+    rbLineSize  := Round(Info.biWidth * FormatDesc.PixelSize);
+    wbLineSize  := Round(Info.biWidth * Info.biBitCount / 8);
+    Padding     := GetLineWidth - wbLineSize;
+    PaddingBuff := 0;
+
+    pData := Data;
+    inc(pData, (Height-1) * rbLineSize);
+
+    // prepare row buffer. But only for RGB because RGBA supports color masks
+    // so it's possible to change color within the image.
+    if Assigned(Converter) then begin
+      FormatDesc.PreparePixel(Pixel);
+      GetMem(ConvertBuffer, wbLineSize);
+      SourceFD := FormatDesc.CreateMappingData;
+      DestFD   := Converter.CreateMappingData;
+    end else
+      ConvertBuffer := nil;
 
-  try
-    // write image data
-    for LineIdx := 0 to Height - 1 do begin
-      // preparing row
-      if Format = tfRGB8 then begin
-        Move(pData^, pTemp^, fRowSize);
-        SwapRGB(pTemp, Width, false);
-      end else
-        pTemp := pData;
-      aStream.Write(pTemp^, LineSize);
-      Dec(pData, LineSize);
-      if Padding > 0 then
-        aStream.Write(PaddingBuff, Padding);
+    try
+      for LineIdx := 0 to Height - 1 do begin
+        // preparing row
+        if Assigned(Converter) then begin
+          srcData := pData;
+          dstData := ConvertBuffer;
+          for PixelIdx := 0 to Info.biWidth-1 do begin
+            FormatDesc.Unmap(srcData, Pixel, SourceFD);
+            with FormatDesc do begin
+              //TODO use convert function
+              for i := 0 to 3 do
+                if (Converter.Range.arr[i] <> Range.arr[i]) then begin
+                  if (Range.arr[i] > 0) then
+                    Pixel.Data.arr[i] := Round(Pixel.Data.arr[i] / Range.arr[i] * Converter.Range.arr[i])
+                  else
+                    Pixel.Data.arr[i] := 0;
+                end;
+            end;
+            Converter.Map(Pixel, dstData, DestFD);
+          end;
+          aStream.Write(ConvertBuffer^, wbLineSize);
+        end else begin
+          aStream.Write(pData^, rbLineSize);
+        end;
+        dec(pData, rbLineSize);
+        if (Padding > 0) then
+          aStream.Write(PaddingBuff, Padding);
+      end;
+    finally
+      // destroy row buffer
+      if Assigned(ConvertBuffer) then begin
+        FormatDesc.FreeMappingData(SourceFD);
+        Converter.FreeMappingData(DestFD);
+        FreeMem(ConvertBuffer);
+      end;
     end;
   finally
-    // destroy row buffer
-    if Format = tfRGB8 then
-      FreeMem(pTemp);
+    if Assigned(Converter) then
+      Converter.Free;
   end;
 end;
 
@@ -6272,29 +6587,43 @@ type
     ImageID: Byte;
     ColorMapType: Byte;
     ImageType: Byte;
-    ColorMapSpec: Array[0..4] of Byte;
+    //ColorMapSpec: Array[0..4] of Byte;
+    ColorMapStart: Word;
+    ColorMapLength: Word;
+    ColorMapEntrySize: Byte;
     OrigX: Word;
     OrigY: Word;
     Width: Word;
     Height: Word;
     Bpp: Byte;
-    ImageDes: Byte;
+    ImageDesc: Byte;
   end;
 
 const
-  TGA_UNCOMPRESSED_RGB = 2;
-  TGA_UNCOMPRESSED_GRAY = 3;
-  TGA_COMPRESSED_RGB = 10;
-  TGA_COMPRESSED_GRAY = 11;
+  TGA_UNCOMPRESSED_COLOR_TABLE =  1;
+  TGA_UNCOMPRESSED_RGB         =  2;
+  TGA_UNCOMPRESSED_GRAY        =  3;
+  TGA_COMPRESSED_COLOR_TABLE   =  9;
+  TGA_COMPRESSED_RGB           = 10;
+  TGA_COMPRESSED_GRAY          = 11;
+
+  TGA_NONE_COLOR_TABLE = 0;
+  TGA_COLOR_TABLE      = 1;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
 var
   Header: TTGAHeader;
-  NewImage, pData: PByte;
-  StreamPos: Int64;
-  PixelSize, LineSize, YStart, YEnd, YInc: Integer;
-  Format: TglBitmapFormat;
+  ImageData: PByte;
+  StartPosition: Int64;
+  PixelSize, LineSize: Integer;
+  tgaFormat: TglBitmapFormat;
+  FormatDesc: TFormatDescriptor;
+  Counter: packed record
+    X, Y: packed record
+      low, high, dir: Integer;
+    end;
+  end;
 
 const
   CACHE_SIZE = $4000;
@@ -6302,195 +6631,233 @@ const
   ////////////////////////////////////////////////////////////////////////////////////////
   procedure ReadUncompressed;
   var
-    RowSize: Integer;
+    i, j: Integer;
+    buf, tmp1, tmp2: PByte;
   begin
-    RowSize := Header.Width * PixelSize;
-    // copy line by line
-    while YStart <> YEnd + YInc do begin
-      pData := NewImage;
-      Inc(pData, YStart * LineSize);
-      aStream.Read(pData^, RowSize);
-      Inc(YStart, YInc);
+    buf := nil;
+    if (Counter.X.dir < 0) then
+      buf := GetMem(LineSize);
+    try
+      while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin
+        tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart
+        if (Counter.X.dir < 0) then begin               //flip X
+          aStream.Read(buf^, LineSize);
+          tmp2 := buf + LineSize - PixelSize;           //pointer to last pixel in line
+          for i := 0 to Header.Width-1 do begin         //for all pixels in line
+            for j := 0 to PixelSize-1 do begin          //for all bytes in pixel
+              tmp1^ := tmp2^;
+              inc(tmp1);
+              inc(tmp2);
+            end;
+            dec(tmp2, 2*PixelSize);                     //move 2 backwards, because j-loop moved 1 forward
+          end;
+        end else
+          aStream.Read(tmp1^, LineSize);
+        inc(Counter.Y.low, Counter.Y.dir);              //move to next line index
+      end;
+    finally
+      if Assigned(buf) then
+        FreeMem(buf);
     end;
   end;
 
   ////////////////////////////////////////////////////////////////////////////////////////
   procedure ReadCompressed;
-  var
-    HeaderWidth, HeaderHeight: Integer;
-    LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
-
-    Cache: PByte;
-    CacheSize, CachePos: Integer;
-
-    Temp: Byte;
-    TempBuf: Array [0..15] of Byte;
-
-    PixelRepeat: Boolean;
-    PixelToRead, TempPixels: Integer;
 
     /////////////////////////////////////////////////////////////////
+    var
+      TmpData: PByte;
+      LinePixelsRead: Integer;
     procedure CheckLine;
     begin
-      if LinePixelsRead >= HeaderWidth then begin
+      if (LinePixelsRead >= Header.Width) then begin
         LinePixelsRead := 0;
-        pData := NewImage;
-        Inc(YStart, YInc);
-        Inc(pData, YStart * LineSize);
+        inc(Counter.Y.low, Counter.Y.dir);                //next line index
+        TmpData := ImageData + Counter.Y.low * LineSize;  //set line
+        if (Counter.X.dir < 0) then                       //if x flipped then
+          TmpData := TmpData + LineSize - PixelSize;      //set last pixel
       end;
     end;
 
     /////////////////////////////////////////////////////////////////
+    var
+      Cache: PByte;
+      CacheSize, CachePos: Integer;
     procedure CachedRead(out Buffer; Count: Integer);
     var
       BytesRead: Integer;
     begin
-      if (CachePos + Count) > CacheSize then begin
+      if (CachePos + Count > CacheSize) then begin
+        //if buffer overflow save non read bytes
         BytesRead := 0;
-
-        // Read Data
-        if CacheSize - CachePos > 0 then begin
+        if (CacheSize - CachePos > 0) then begin
           BytesRead := CacheSize - CachePos;
-          Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
-          Inc(CachePos, BytesRead);
+          Move(PByteArray(Cache)^[CachePos], Buffer, BytesRead);
+          inc(CachePos, BytesRead);
         end;
 
-        // Reload Data
+        //load cache from file
         CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
         aStream.Read(Cache^, CacheSize);
         CachePos := 0;
 
-        // Read else
-        if Count - BytesRead > 0 then begin
-          Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
-          Inc(CachePos, Count - BytesRead);
+        //read rest of requested bytes
+        if (Count - BytesRead > 0) then begin
+          Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead);
+          inc(CachePos, Count - BytesRead);
         end;
       end else begin
-        Move(pByteArray(Cache)^[CachePos], Buffer, Count);
-        Inc(CachePos, Count);
+        //if no buffer overflow just read the data
+        Move(PByteArray(Cache)^[CachePos], Buffer, Count);
+        inc(CachePos, Count);
+      end;
+    end;
+
+    procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte);
+    begin
+      case PixelSize of
+        1: begin
+          aBuffer^ := aData^;
+          inc(aBuffer, Counter.X.dir);
+        end;
+        2: begin
+          PWord(aBuffer)^ := PWord(aData)^;
+          inc(aBuffer, 2 * Counter.X.dir);
+        end;
+        3: begin
+          PByteArray(aBuffer)^[0] := PByteArray(aData)^[0];
+          PByteArray(aBuffer)^[1] := PByteArray(aData)^[1];
+          PByteArray(aBuffer)^[2] := PByteArray(aData)^[2];
+          inc(aBuffer, 3 * Counter.X.dir);
+        end;
+        4: begin
+          PCardinal(aBuffer)^ := PCardinal(aData)^;
+          inc(aBuffer, 4 * Counter.X.dir);
+        end;
       end;
     end;
 
+  var
+    TotalPixelsToRead, TotalPixelsRead: Integer;
+    Temp: Byte;
+    buf: array [0..3] of Byte; //1 pixel is max 32bit long
+    PixelRepeat: Boolean;
+    PixelsToRead, PixelCount: Integer;
   begin
     CacheSize := 0;
-    CachePos := 0;
+    CachePos  := 0;
 
-    HeaderWidth := Header.Width;
-    HeaderHeight := Header.Height;
+    TotalPixelsToRead := Header.Width * Header.Height;
+    TotalPixelsRead   := 0;
+    LinePixelsRead    := 0;
 
-    GetMem(Cache, CACHE_SIZE); // 16K Buffer
+    GetMem(Cache, CACHE_SIZE);
     try
-      ImgPixelsToRead := HeaderWidth * HeaderHeight;
-      ImgPixelsRead := 0;
-      LinePixelsRead := 0;
+      TmpData := ImageData + Counter.Y.low * LineSize;  //set line
+      if (Counter.X.dir < 0) then                       //if x flipped then
+        TmpData := TmpData + LineSize - PixelSize;      //set last pixel
 
-      pData := NewImage;
-      Inc(pData, YStart * LineSize);
-
-      // Read until all Pixels
       repeat
+        //read CommandByte
         CachedRead(Temp, 1);
-
-        PixelRepeat := Temp and $80 > 0;
-        PixelToRead := (Temp and $7F) + 1;
-
-        Inc(ImgPixelsRead, PixelToRead);
-
-        if PixelRepeat then begin
-          // repeat one pixel x times
-          CachedRead(TempBuf[0], PixelSize);
-
-          // repeat Pixel
-          while PixelToRead > 0 do begin
-            CheckLine;
-
-            TempPixels := HeaderWidth - LinePixelsRead;
-            if PixelToRead < TempPixels then
-              TempPixels := PixelToRead;
-
-            Inc(LinePixelsRead, TempPixels);
-            Dec(PixelToRead, TempPixels);
-
-            while TempPixels > 0 do begin
-              case PixelSize of
-                1: begin
-                  pData^ := TempBuf[0];
-                  Inc(pData);
-                end;
-                2: begin
-                  pWord(pData)^ := pWord(@TempBuf[0])^;
-                  Inc(pData, 2);
-                end;
-                3: begin
-                  pWord(pData)^ := pWord(@TempBuf[0])^;
-                  Inc(pData, 2);
-                  pData^ := TempBuf[2];
-                  Inc(pData);
-                end;
-                4: begin
-                  pDWord(pData)^ := pDWord(@TempBuf[0])^;
-                  Inc(pData, 4);
-                end;
-              end;
-              Dec(TempPixels);
-            end;
-          end;
-        end else begin
-          // copy x pixels
-          while PixelToRead > 0 do begin
-            CheckLine;
-            TempPixels := HeaderWidth - LinePixelsRead;
-            if PixelToRead < TempPixels then
-              TempPixels := PixelToRead;
-            CachedRead(pData^, PixelSize * TempPixels);
-            Inc(pData, PixelSize * TempPixels);
-            Inc(LinePixelsRead, TempPixels);
-            Dec(PixelToRead, TempPixels);
+        PixelRepeat  := (Temp and $80) > 0;
+        PixelsToRead := (Temp and $7F) + 1;
+        inc(TotalPixelsRead, PixelsToRead);
+
+        if PixelRepeat then
+          CachedRead(buf[0], PixelSize);
+        while (PixelsToRead > 0) do begin
+          CheckLine;
+          PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF
+          while (PixelCount > 0) do begin
+            if not PixelRepeat then
+              CachedRead(buf[0], PixelSize);
+            PixelToBuffer(@buf[0], TmpData);
+            inc(LinePixelsRead);
+            dec(PixelsToRead);
+            dec(PixelCount);
           end;
         end;
-      until ImgPixelsRead >= ImgPixelsToRead;
+      until (TotalPixelsRead >= TotalPixelsToRead);
     finally
-      FreeMem(Cache)
+      FreeMem(Cache);
     end;
   end;
 
+  function IsGrayFormat: Boolean;
+  begin
+    result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY];
+  end;
+
 begin
   result := false;
 
   // reading header to test file and set cursor back to begin
-  StreamPos := aStream.Position;
+  StartPosition := aStream.Position;
   aStream.Read(Header, SizeOf(Header));
 
   // no colormapped files
-  if (Header.ColorMapType = 0) then begin
-    if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin
+  if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [
+    TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then
+  begin
+    try
+      if Header.ImageID <> 0 then       // skip image ID
+        aStream.Position := aStream.Position + Header.ImageID;
+
       case Header.Bpp of
-        //TODO 8: Format := tfAlpha8;
-        16: Format := tfLuminance8Alpha8;
-        24: Format := tfBGR8;
-        32: Format := tfBGRA8;
-      else
-        raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
+         8: if IsGrayFormat then case (Header.ImageDesc and $F) of
+               0: tgaFormat := tfLuminance8;
+               8: tgaFormat := tfAlpha8;
+            end;
+
+        16: if IsGrayFormat then case (Header.ImageDesc and $F) of
+               0: tgaFormat := tfLuminance16;
+               8: tgaFormat := tfLuminance8Alpha8;
+            end else case (Header.ImageDesc and $F) of
+               0: tgaFormat := tfBGR5;
+               1: tgaFormat := tfBGR5A1;
+               4: tgaFormat := tfBGRA4;
+            end;
+
+        24: if not IsGrayFormat then case (Header.ImageDesc and $F) of
+               0: tgaFormat := tfBGR8;
+            end;
+
+        32: if not IsGrayFormat then case (Header.ImageDesc and $F) of
+               2: tgaFormat := tfBGR10A2;
+               8: tgaFormat := tfBGRA8;
+            end;
       end;
 
-      // skip image ID
-      if Header.ImageID <> 0 then
-        aStream.Position := aStream.Position + Header.ImageID;
+      if (tgaFormat = tfEmpty) then
+        raise EglBitmapException.Create('LoadTga - unsupported format');
 
-      PixelSize := TFormatDescriptor.Get(Format).GetSize(1, 1);
-      LineSize  := Trunc(Header.Width * PixelSize);
+      FormatDesc := TFormatDescriptor.Get(tgaFormat);
+      PixelSize  := FormatDesc.GetSize(1, 1);
+      LineSize   := FormatDesc.GetSize(Header.Width, 1);
 
-      GetMem(NewImage, LineSize * Header.Height);
+      GetMem(ImageData, LineSize * Header.Height);
       try
+        //column direction
+        if ((Header.ImageDesc and (1 shl 4)) > 0) then begin
+          Counter.X.low  := Header.Height-1;;
+          Counter.X.high := 0;
+          Counter.X.dir  := -1;
+        end else begin
+          Counter.X.low  := 0;
+          Counter.X.high := Header.Height-1;
+          Counter.X.dir  := 1;
+        end;
+
         // Row direction
-        if (Header.ImageDes and $20 > 0) then begin
-          YStart := 0;
-          YEnd := Header.Height -1;
-          YInc := 1;
+        if ((Header.ImageDesc and (1 shl 5)) > 0) then begin
+          Counter.Y.low  := 0;
+          Counter.Y.high := Header.Height-1;
+          Counter.Y.dir  := 1;
         end else begin
-          YStart := Header.Height -1;
-          YEnd := 0;
-          YInc := -1;
+          Counter.Y.low  := Header.Height-1;;
+          Counter.Y.high := 0;
+          Counter.Y.dir  := -1;
         end;
 
         // Read Image
@@ -6501,97 +6868,106 @@ begin
             ReadCompressed;
         end;
 
-        SetDataPointer(NewImage, Format, Header.Width, Header.Height);
+        SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height);
         result := true;
       except
-        FreeMem(NewImage);
+        FreeMem(ImageData);
         raise;
       end;
-    end
-      else aStream.Position := StreamPos;
+    finally
+      aStream.Position := StartPosition;
+    end;
   end
-    else aStream.Position := StreamPos;
+    else aStream.Position := StartPosition;
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.SaveTGA(const aStream: TStream);
 var
   Header: TTGAHeader;
-  Size: Integer;
-  pTemp: pByte;
+  LineSize, Size, x, y: Integer;
+  Pixel: TglBitmapPixelData;
+  LineBuf, SourceData, DestData: PByte;
+  SourceMD, DestMD: Pointer;
   FormatDesc: TFormatDescriptor;
-
-  procedure ConvertData(pTemp: pByte);
-  var
-    Idx, PixelSize: Integer;
-    Temp: byte;
-  begin
-    PixelSize := fPixelSize;
-    for Idx := 1 to Height * Width do begin
-      Temp := pByteArray(pTemp)^[2];
-      pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0];
-      pByteArray(pTemp)^[0] := Temp;
-      Inc(pTemp, PixelSize);
-    end;
-  end;
-
+  Converter: TFormatDescriptor;
 begin
   if not (ftTGA in FormatGetSupportedFiles(Format)) then
     raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
 
+  //prepare header
   FillChar(Header, SizeOf(Header), 0);
-  case Format of
-    //TODO ifAlpha8, ifLuminance8, ifDepth8: begin
-    tfLuminance8: begin
-      Header.ImageType := TGA_UNCOMPRESSED_GRAY;
-      Header.Bpp := 8;
-    end;
-    tfLuminance8Alpha8: begin
-      Header.ImageType := TGA_UNCOMPRESSED_GRAY;
-      Header.Bpp := 16;
-    end;
-    tfRGB8, tfBGR8: begin
-      Header.ImageType := TGA_UNCOMPRESSED_RGB;
-      Header.Bpp := 24;
-    end;
-    tfRGBA8, tfBGRA8: begin
-      Header.ImageType := TGA_UNCOMPRESSED_RGB;
-      Header.Bpp := 32;
-    end;
-  else
-    raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
-  end;
 
-  Header.Width    := Width;
-  Header.Height   := Height;
-  Header.ImageDes := $20;
-  FormatDesc      := TFormatDescriptor.Get(Format);
+  //set ImageType
+  if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8,
+                 tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then
+    Header.ImageType := TGA_UNCOMPRESSED_GRAY
+  else
+    Header.ImageType := TGA_UNCOMPRESSED_RGB;
+
+  //set BitsPerPixel
+  if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then
+    Header.Bpp := 8
+  else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8,
+                      tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then
+    Header.Bpp := 16
+  else if (Format in [tfBGR8, tfRGB8]) then
+    Header.Bpp := 24
+  else
+    Header.Bpp := 32;
 
-  if FormatDesc.HasAlpha then
-    Header.ImageDes := Header.ImageDes or $08;
+  //set AlphaBitCount
+  case Format of
+    tfRGB5A1, tfBGR5A1:
+      Header.ImageDesc := 1 and $F;
+    tfRGB10A2, tfBGR10A2:
+      Header.ImageDesc := 2 and $F;
+    tfRGBA4, tfBGRA4:
+      Header.ImageDesc := 4 and $F;
+    tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8:
+      Header.ImageDesc := 8 and $F;
+  end;
+
+  Header.Width     := Width;
+  Header.Height    := Height;
+  Header.ImageDesc := Header.ImageDesc or $20; //flip y
   aStream.Write(Header, SizeOf(Header));
 
   // convert RGB(A) to BGR(A)
-  Size := FormatDesc.GetSize(Dimension);
-  if Format in [tfRGB8, tfRGBA8] then begin
-    GetMem(pTemp, Size);
-  end else
-    pTemp := Data;
-
-  try
-    // convert data
-    if Format in [tfRGB8, tfRGBA8] then begin
-      Move(Data^, pTemp^, Size);
-      ConvertData(pTemp);
+  Converter  := nil;
+  FormatDesc := TFormatDescriptor.Get(Format);
+  Size       := FormatDesc.GetSize(Dimension);
+  if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin
+    if (FormatDesc.RGBInverted = tfEmpty) then
+      raise EglBitmapException.Create('inverted RGB format is empty');
+    Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted);
+    if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or
+       (Converter.PixelSize <> FormatDesc.PixelSize) then
+      raise EglBitmapException.Create('invalid inverted RGB format');
+  end;
+
+  if Assigned(Converter) then begin
+    LineSize := FormatDesc.GetSize(Width, 1);
+    LineBuf  := GetMem(LineSize);
+    SourceMD := FormatDesc.CreateMappingData;
+    DestMD   := Converter.CreateMappingData;
+    try
+      SourceData := Data;
+      for y := 0 to Height-1 do begin
+        DestData := LineBuf;
+        for x := 0 to Width-1 do begin
+          FormatDesc.Unmap(SourceData, Pixel, SourceMD);
+          Converter.Map(Pixel, DestData, DestMD);
+        end;
+        aStream.Write(LineBuf^, LineSize);
+      end;
+    finally
+      FreeMem(LineBuf);
+      FormatDesc.FreeMappingData(SourceMD);
+      FormatDesc.FreeMappingData(DestMD);
     end;
-
-    // write data
-    aStream.Write(pTemp^, Size);
-  finally
-    // free tempdata
-    if Format in [tfRGB8, tfRGBA8] then
-      FreeMem(pTemp);
-  end;
+  end else
+    aStream.Write(Data^, Size);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -6615,6 +6991,7 @@ const
   DDPF_FOURCC                 = $00000004;
   DDPF_INDEXED                = $00000020;
   DDPF_RGB                    = $00000040;
+  DDPF_LUMINANCE              = $00020000;
 
   // DDS_header.sCaps.dwCaps1
   DDSCAPS_COMPLEX             = $00000008;
@@ -6673,84 +7050,70 @@ type
 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
 var
   Header: TDDSHeader;
-  StreamPos: Int64;
-  Y, LineSize: Cardinal;
-  RowSize: Cardinal;
-  NewImage, pData: pByte;
-  ddsFormat: TglBitmapFormat;
-
-  function RaiseEx : Exception;
-  begin
-    result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
-  end;
 
   function GetDDSFormat: TglBitmapFormat;
   begin
+    result := tfEmpty;
     with Header.PixelFormat do begin
       // Compresses
-      if (dwFlags and DDPF_FOURCC) > 0 then begin
-        (* TODO
+      if ((dwFlags and DDPF_FOURCC) > 0) then begin
         case Header.PixelFormat.dwFourCC of
-          D3DFMT_DXT1: result := ifDXT1;
-          D3DFMT_DXT3: result := ifDXT3;
-          D3DFMT_DXT5: result := ifDXT5;
-        else
-          raise RaiseEx;
+          D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
+          D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
+          D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
         end;
-        *)
-        raise RaiseEx;
       end else
 
       // RGB
-      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
+      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
         case dwRGBBitCount of
           8: begin
-            (* TODO if dwFlags and DDPF_ALPHAPIXELS > 0 then
-              result := tfAlpha
-            else
-            *)
+            if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then
+              result := tfAlpha8
+            else if ((dwFlags and DDPF_LUMINANCE) > 0) then
               result := tfLuminance8;
           end;
+
           16: begin
-            if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
-              // Alpha
+            if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then begin
               case CountSetBits(dwRBitMask) of
                 5: result := tfRGB5A1;
-                //TODO 4: result := tfRGBA4;
+                4: result := tfRGBA4;
               else
                 result := tfLuminance8Alpha8;
               end;
-            end else begin
-              // no Alpha
-              //TODO result := ifR5G6B5;
-              raise RaiseEx;
-            end;
+            end else if (CountSetBits(dwGBitMask) = 6) then
+              result := tfR5G6B5
+            else
+              result := tfRGB5;
           end;
+
           24: begin
-            if dwRBitMask > dwBBitMask then
-              result := tfBGR8
-            else
-              result := tfRGB8;
+            result := tfRGB8;
           end;
-        32: begin
-            if CountSetBits(dwRBitMask) = 10 then
-              //TODO result := tfRGB10A2
-              raise RaiseEx
-            else
 
-            if dwRBitMask > dwBBitMask then
-              result := tfBGRA8
+          32: begin
+            if CountSetBits(dwRBitMask) = 10 then
+              result := tfRGB10A2
             else
               result := tfRGBA8;
           end;
-        else
-          raise RaiseEx;
         end;
-      end else
-        raise RaiseEx;
+
+        if (dwRBitMask <> 0) and (dwBBitMask <> 0) and (dwRBitMask > dwBBitMask) then
+          result := TFormatDescriptor.Get(result).RGBInverted;
+      end;
     end;
   end;
 
+var
+  StreamPos: Int64;
+  Y, LineSize: Cardinal;
+  RowSize: Cardinal;
+  NewImage, TmpData: PByte;
+  ddsFormat: TglBitmapFormat;
+  FormatDesc: TFormatDescriptor;
+
 begin
   result := false;
 
@@ -6758,37 +7121,45 @@ begin
   StreamPos := aStream.Position;
   aStream.Read(Header, sizeof(Header));
 
-  if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
-     ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
+  if (Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
+     ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
+        (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
+  begin
     aStream.Position := StreamPos;
     exit;
   end;
 
+  if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
+    raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
+
   ddsFormat := GetDDSFormat;
-  LineSize  := Trunc(Header.dwWidth * TFormatDescriptor.Get(ddsFormat).PixelSize);
+  if (ddsFormat = tfEmpty) then
+    raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
+
+  FormatDesc := TFormatDescriptor.Get(ddsFormat);
+  LineSize   := Trunc(Header.dwWidth * FormatDesc.PixelSize);
   GetMem(NewImage, Header.dwHeight * LineSize);
   try
-    pData := NewImage;
+    TmpData := NewImage;
 
     // Compressed
-    if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
+    if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
       RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
-      for Y := 0 to Header.dwHeight -1 do begin
-        aStream.Read(pData^, RowSize);
-        Inc(pData, LineSize);
+      for Y := 0 to Header.dwHeight-1 do begin
+        aStream.Read(TmpData^, RowSize);
+        Inc(TmpData, LineSize);
       end;
     end else
 
-    // RGB(A)
-    if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
-      RowSize := Header.dwPitchOrLinearSize;
-
-      for Y := 0 to Header.dwHeight -1 do begin
-        aStream.Read(pData^, RowSize);
-        Inc(pData, LineSize);
+    // Uncompressed
+    if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
+      RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
+      for Y := 0 to Header.dwHeight-1 do begin
+        aStream.Read(TmpData^, RowSize);
+        Inc(TmpData, LineSize);
       end;
     end else
-      raise RaiseEx;
+      raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
 
     SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
     result := true;
@@ -6874,8 +7245,7 @@ var
 begin
   inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
 
-  //TODO compression
-  if {FormatIsUncompressed(Format)} true then begin
+  if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
     (* TODO PixelFuncs
     fGetPixelFunc := GetPixel2DUnmap;
     fSetPixelFunc := SetPixel2DUnmap;
@@ -6892,9 +7262,8 @@ begin
     end
       else SetLength(fLines, 0);
   end else begin
-    (*
     SetLength(fLines, 0);
-
+    (*
     fSetPixelFunc := nil;
 
     case Format of
@@ -6918,19 +7287,16 @@ var
 begin
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-  (* TODO compression
-  if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
-    glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
-  else
-  *)
-
   FormatDesc := TFormatDescriptor.Get(Format);
-  if aBuildWithGlu then
+  if FormatDesc.IsCompressed then begin
+    glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
+  end else if aBuildWithGlu then begin
     gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
       FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
-  else
+  end else begin
     glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
       FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
+  end;
 
   // Freigeben
   if (FreeDataAfterGenTexture) then
@@ -6951,15 +7317,13 @@ var
   Size, w, h: Integer;
   FormatDesc: TFormatDescriptor;
 begin
-  (* TODO compression
-  if not FormatIsUncompressed(Format) then
+  FormatDesc := TFormatDescriptor.Get(Format);
+  if FormatDesc.IsCompressed then
     raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
-  *)
 
-  w := aRight  - aLeft;
-  h := aBottom - aTop;
-  FormatDesc   := TFormatDescriptor.Get(Format);
-  Size         := FormatDesc.GetSize(w, h);
+  w    := aRight  - aLeft;
+  h    := aBottom - aTop;
+  Size := FormatDesc.GetSize(w, h);
   GetMem(Temp, Size);
   try
     glPixelStorei(GL_PACK_ALIGNMENT, 1);
@@ -6999,12 +7363,10 @@ begin
   FormatDesc := TFormatDescriptor.Get(IntFormat);
   GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
   try
-    (* TODO Compression
-    if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
+    if FormatDesc.IsCompressed then
       glGetCompressedTexImage(Target, 0, Temp)
     else
-    *)
-    glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
+     glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
     SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
   except
     FreeMem(Temp);
@@ -7702,3 +8064,4 @@ finalization
   TFormatDescriptor.Finalize;
 
 end.
+