* refactored FormatDescriptor
[LazOpenGLCore.git] / glBitmap.pas
index 1a21c20..b2a1476 100644 (file)
@@ -168,9 +168,9 @@ History
 - function MoveMemory replaced with function Move (little speed change)
 - several calculations stored in variables (little speed change)
 29-09-2003
-- property BuildMipsMaps added (default = True)
+- property BuildMipsMaps added (default = true)
   if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps
-- property FreeDataAfterGenTexture added (default = True)
+- property FreeDataAfterGenTexture added (default = true)
   if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated.
 - parameter DisableOtherTextureUnits of Bind removed
 - parameter FreeDataAfterGeneration of GenTextures removed
@@ -583,31 +583,104 @@ var
 *)
 
 type
-  EglBitmapException                 = class(Exception);
-  EglBitmapSizeToLargeException      = class(EglBitmapException);
-  EglBitmapNonPowerOfTwoException    = class(EglBitmapException);
-  EglBitmapUnsupportedInternalFormat = class(EglBitmapException);
+////////////////////////////////////////////////////////////////////////////////////////////////////
+  EglBitmapException               = class(Exception);
+  EglBitmapSizeToLargeException    = class(EglBitmapException);
+  EglBitmapNonPowerOfTwoException  = class(EglBitmapException);
+  EglBitmapUnsupportedFormatFormat = class(EglBitmapException);
 
-  TglBitmapPixelDesc = packed record
-    RedRange: Cardinal;
-    GreenRange: Cardinal;
-    BlueRange: Cardinal;
-    AlphaRange: Cardinal;
+////////////////////////////////////////////////////////////////////////////////////////////////////
+  TglBitmapFormat = (
+    tfEmpty = 0,
+
+    //tfAlpha4,
+    tfAlpha8,
+    //tfAlpha12,
+    tfAlpha16,
+
+    //tfLuminance4,
+    tfLuminance8,
+    //tfLuminance12,
+    tfLuminance16,
+
+    tfLuminance4Alpha4,
+    tfLuminance6Alpha2,
+    tfLuminance8Alpha8,
+    tfLuminance12Alpha4,
+    //tfLuminance12Alpha12,
+    tfLuminance16Alpha16,
+
+    tfR3G3B2,
+    tfRGB4,
+    tfR5G6B5,
+    tfRGB5,
+    tfRGB8,
+    tfRGB10,
+    //tfRGB12,
+    tfRGB16,
+
+    tfRGBA2,
+    tfRGBA4,
+    tfRGB5A1,
+    tfRGBA8,
+    tfRGB10A2,
+    //tfRGBA12,
+    tfRGBA16,
+
+    tfBGR4,
+    tfB5G6R5,
+    tfBGR5,
+    tfBGR8,
+    tfBGR10,
+    //tfBGR12,
+    tfBGR16,
+
+    tfBGRA2,
+    tfBGRA4,
+    tfBGR5A1,
+    tfBGRA8,
+    tfBGR10A2,
+    //tfBGRA12,
+    tfBGRA16
+
+    //tfDepth16,
+    //tfDepth24,
+    //tfDepth32
+  );
 
-    RedShift: Shortint;
-    GreenShift: Shortint;
-    BlueShift: Shortint;
-    AlphaShift: Shortint;
+  TglBitmapFileType = (
+     {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG,  {$ENDIF}
+     {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
+     ftDDS,
+     ftTGA,
+     ftBMP);
+   TglBitmapFileTypes = set of TglBitmapFileType;
+
+   TglBitmapMipMap = (
+     mmNone,
+     mmMipmap,
+     mmMipmapGlu);
+
+   TglBitmapNormalMapFunc = (
+     nm4Samples,
+     nmSobel,
+     nm3x3,
+     nm5x5);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+  TglBitmapColorRec = packed record
+  case Integer of
+    0: (r, g, b, a: Cardinal);
+    1: (arr: array[0..3] of Cardinal);
   end;
 
   TglBitmapPixelData = packed record
-    Red: Cardinal;
-    Green: Cardinal;
-    Blue: Cardinal;
-    Alpha: Cardinal;
-    PixelDesc: TglBitmapPixelDesc;
+    Data, Range: TglBitmapColorRec;
+    Format: TglBitmapFormat;
   end;
+  PglBitmapPixelData = ^TglBitmapPixelData;
 
+////////////////////////////////////////////////////////////////////////////////////////////////////
   TglBitmapPixelPositionFields = set of (ffX, ffY);
   TglBitmapPixelPosition = record
     Fields : TglBitmapPixelPositionFields;
@@ -615,108 +688,23 @@ type
     Y : Word;
   end;
 
-const
-  NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
-
-type
+////////////////////////////////////////////////////////////////////////////////////////////////////
   TglBitmap = class;
-
   TglBitmapFunctionRec = record
-    Sender : TglBitmap;
-    Size: TglBitmapPixelPosition;
+    Sender:   TglBitmap;
+    Size:     TglBitmapPixelPosition;
     Position: TglBitmapPixelPosition;
-    Source: TglBitmapPixelData;
-    Dest: TglBitmapPixelData;
-    CustomData: Pointer;
+    Source:   TglBitmapPixelData;
+    Dest:     TglBitmapPixelData;
+    Args:     PtrInt;
   end;
-
   TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec);
 
-  TglBitmapGetPixel = procedure (
-    const Pos: TglBitmapPixelPosition;
-    var Pixel: TglBitmapPixelData) of object;
-
-  TglBitmapSetPixel = procedure (
-    const Pos: TglBitmapPixelPosition;
-    const Pixel: TglBitmapPixelData) of object;
-
-  TglBitmapFileType = (
-      {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG,  {$ENDIF}
-      {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
-      ftDDS,
-      ftTGA,
-      ftBMP);
-  TglBitmapFileTypes = set of TglBitmapFileType;
-
-  TglBitmapMipMap = (
-    mmNone,
-    mmMipmap,
-    mmMipmapGlu);
-  TglBitmapNormalMapFunc = (
-    nm4Samples,
-    nmSobel,
-    nm3x3,
-    nm5x5);
-  TglBitmapFormat = (
-    tfRed = GL_RED,
-    tfGreen = GL_GREEN,
-    tfBlue = GL_BLUE,
-    tfAlpha = GL_ALPHA,
-    tfRGB = GL_RGB,
-    tfBGR = GL_BGR,
-    tfRGBA = GL_RGBA,
-    tfBGRA = GL_BGRA,
-    tfLuminance = GL_LUMINANCE,
-    tfLuminanceAlpha = GL_LUMINANCE_ALPHA
-  );
-  TglBitmapInternalFormat = (
-    ifAlpha4 = GL_ALPHA4,
-    ifAlpha8 = GL_ALPHA8,
-    ifAlpha12 = GL_ALPHA12,
-    ifAlpha16 = GL_ALPHA16,
-
-    ifLuminance4 = GL_LUMINANCE4,
-    ifLuminance8 = GL_LUMINANCE8,
-    ifLuminance12 = GL_LUMINANCE12,
-    ifLuminance16 = GL_LUMINANCE16,
-
-    ifLuminance4Alpha4 = GL_LUMINANCE4_ALPHA4,
-    ifLuminance6Alpha2 = GL_LUMINANCE6_ALPHA2,
-    ifLuminance8Alpha8 = GL_LUMINANCE8_ALPHA8,
-    ifLuminance12Alpha4 = GL_LUMINANCE12_ALPHA4,
-    ifLuminance12Alpha12 = GL_LUMINANCE12_ALPHA12,
-    ifLuminance16Alpha16 = GL_LUMINANCE16_ALPHA16,
-
-    ifR3G3B2 = GL_R3_G3_B2,
-    ifRGB4 = GL_RGB4,
-    ifRGB5 = GL_RGB5,
-    ifRGB8 = GL_RGB8,
-    ifRGB10 = GL_RGB10,
-    ifRGB12 = GL_RGB12,
-    ifRGB16 = GL_RGB16,
-
-    ifRGBA2 = GL_RGBA2,
-    ifRGBA4 = GL_RGBA4,
-    ifRGB5A1 = GL_RGB5_A1,
-    ifRGBA8 = GL_RGBA8,
-    ifRGB10A2 = GL_RGB10_A2,
-    ifRGBA12 = GL_RGBA12,
-    ifRGBA16 = GL_RGBA16,
-
-    ifDepth16 = GL_DEPTH_COMPONENT16,
-    ifDepth24 = GL_DEPTH_COMPONENT24,
-    ifDepth32 = GL_DEPTH_COMPONENT32
-  );
-
-  // Pixelmapping
-  TglBitmapMapFunc   = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-  TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData);
-
-  // Base Class
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   TglBitmap = class
   protected
-    fID: Cardinal;
-    fTarget: Cardinal;
+    fID: GLuint;
+    fTarget: GLuint;
     fAnisotropic: Integer;
     fDeleteTextureOnFree: Boolean;
     fFreeDataAfterGenTexture: Boolean;
@@ -727,13 +715,10 @@ type
     fDimension: TglBitmapPixelPosition;
     fMipMap: TglBitmapMipMap;
     fFormat: TglBitmapFormat;
-    fInternalFormat: TglBitmapInternalFormat;
 
     // Mapping
     fPixelSize: Integer;
     fRowSize: Integer;
-    fUnmapFunc: TglBitmapUnMapFunc;
-    fMapFunc: TglBitmapMapFunc;
 
     // Filtering
     fFilterMin: Cardinal;
@@ -744,9 +729,6 @@ type
     fWrapT: Cardinal;
     fWrapR: Cardinal;
 
-    fGetPixelFunc: TglBitmapGetPixel;
-    fSetPixelFunc: TglBitmapSetPixel;
-
     // CustomData
     fFilename: String;
     fCustomName: String;
@@ -754,8 +736,11 @@ type
     fCustomData: Pointer;
 
     //Getter
-    function GetHeight: Integer; virtual;
     function GetWidth:  Integer; virtual;
+    function GetHeight: Integer; virtual;
+
+    function GetFileWidth:  Integer; virtual;
+    function GetFileHeight: Integer; virtual;
 
     //Setter
     procedure SetCustomData(const aValue: Pointer);
@@ -768,49 +753,28 @@ type
     procedure SetMipMap(const aValue: TglBitmapMipMap);
     procedure SetTarget(const aValue: Cardinal);
     procedure SetAnisotropic(const aValue: Integer);
-    procedure SetInternalFormat(const aValue: TglBitmapInternalFormat);
-
-    //Load
-    {$IFDEF GLB_SUPPORT_PNG_READ}
-    function LoadPNG(Stream: TStream): Boolean; virtual;
-    {$ENDIF}
-    {$IFDEF GLB_SUPPORT_JPEG_READ}
-    function LoadJPEG(Stream: TStream): Boolean; virtual;
-    {$ENDIF}
-    function LoadDDS(Stream: TStream): Boolean; virtual;
-    function LoadTGA(Stream: TStream): Boolean; virtual;
-    function LoadBMP(Stream: TStream): Boolean; virtual;
-
-    //Save
-    {$IFDEF GLB_SUPPORT_PNG_WRITE}
-    procedure SavePNG(Stream: TStream); virtual;
-    {$ENDIF}
-    {$IFDEF GLB_SUPPORT_JPEG_WRITE}
-    procedure SaveJPEG(Stream: TStream); virtual;
-    {$ENDIF}
-    procedure SaveDDS(Stream: TStream); virtual;
-    procedure SaveTGA(Stream: TStream); virtual;
-    procedure SaveBMP(Stream: TStream); virtual;
 
     procedure CreateID;
-    procedure SetupParameters(var BuildWithGlu: Boolean);
-    procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
-
-    procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual;
-    procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract;
+    procedure SetupParameters(var aBuildWithGlu: Boolean);
+    procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
+      const aWidth: Integer = -1; const aHeight: Integer = -1); virtual;
+    procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract;
 
     function FlipHorz: Boolean; virtual;
     function FlipVert: Boolean; virtual;
 
     property Width:  Integer read GetWidth;
     property Height: Integer read GetHeight;
+
+    property FileWidth:  Integer read GetFileWidth;
+    property FileHeight: Integer read GetFileHeight;
   public
-    property ID:             Cardinal                read fID             write SetID;
-    property Target:         Cardinal                read fTarget         write SetTarget;
-    property Format:         TglBitmapFormat         read fFormat         write SetFormat;
-    property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat;
-    property MipMap:         TglBitmapMipMap         read fMipMap      write SetMipMap;
-    property Anisotropic:    Integer                 read fAnisotropic write SetAnisotropic;
+    //Properties
+    property ID:           Cardinal        read fID          write SetID;
+    property Target:       Cardinal        read fTarget      write SetTarget;
+    property Format:       TglBitmapFormat read fFormat      write SetFormat;
+    property MipMap:       TglBitmapMipMap read fMipMap      write SetMipMap;
+    property Anisotropic:  Integer         read fAnisotropic write SetAnisotropic;
 
     property Filename:    String     read fFilename;
     property CustomName:  String     read fCustomName  write SetCustomName;
@@ -820,30 +784,33 @@ type
     property DeleteTextureOnFree:     Boolean read fDeleteTextureOnFree     write SetDeleteTextureOnFree;
     property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
 
-    property Dimension:      TglBitmapPixelPosition  read fDimension;
-    property Data:           PByte                   read fData;
-    property IsResident:     Boolean                 read fIsResident;
+    property Dimension:  TglBitmapPixelPosition  read fDimension;
+    property Data:       PByte                   read fData;
+    property IsResident: Boolean                 read fIsResident;
 
     procedure AfterConstruction; override;
     procedure BeforeDestruction; override;
 
-    //Loading
-    procedure LoadFromFile(const aFileName: String);
+    //Load
+    procedure LoadFromFile(const aFilename: String);
     procedure LoadFromStream(const aStream: TStream); virtual;
     procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
-      const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat;
-      const aArgs: PtrInt = 0);
+      const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0);
     {$IFDEF GLB_DELPHI}
-    procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil);
-    procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
+    procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
+    procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
     {$ENDIF}
 
+    //Save
     procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
     procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual;
 
-    //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload;
-    //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload;
-(* TODO
+    //Convert
+    function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload;
+    function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
+      const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload;
+  public
+    //Alpha & Co
     {$IFDEF GLB_SDL}
     function AssignToSurface(out aSurface: PSDL_Surface): Boolean;
     function AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
@@ -858,19 +825,17 @@ type
     function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
     function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil;
       const aArgs: PtrInt = 0): Boolean;
-    {$ENDIF}
-
-    function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
-    function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
-    function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
-    function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
-    {$IFDEF GLB_DELPHI}
     function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil;
       const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
     function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
       const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
     {$ENDIF}
 
+    function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual;
+    function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
+    function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
+    function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean;
+
     function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean;
     function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean;
     function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean;
@@ -880,71 +845,96 @@ type
     function AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
 
     function RemoveAlpha: Boolean; virtual;
+  public
+    //Common
     function Clone: TglBitmap;
-    function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat): Boolean; virtual;
-    procedure SetBorderColor(Red, Green, Blue, Alpha: Single);
-    procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false);
+    function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual;
+    procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false);
+    procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
     procedure FreeData;
 
-    procedure FillWithColor(const aRed, aGreen, aBlue: aByte; Alpha: Byte = 255);
+    //ColorFill
+    procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255);
     procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF);
     procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1);
-*)
+
+    //TexParameters
     procedure SetFilter(const aMin, aMag: Cardinal);
     procedure SetWrap(
       const S: Cardinal = GL_CLAMP_TO_EDGE;
       const T: Cardinal = GL_CLAMP_TO_EDGE;
       const R: Cardinal = GL_CLAMP_TO_EDGE);
 
-    procedure GetPixel(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);   virtual;
-    procedure SetPixel(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual;
+    procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData);   virtual;
+    procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual;
 
-    procedure Unbind(DisableTextureUnit: Boolean = True); virtual;
-    procedure Bind(EnableTextureUnit: Boolean = True); virtual;
+    procedure Bind(const aEnableTextureUnit: Boolean = true); virtual;
+    procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual;
 
+    //Constructors
     constructor Create; overload;
-    constructor Create(FileName: String); overload;
-    constructor Create(Stream: TStream); overload;
+    constructor Create(const aFileName: String); overload;
+    constructor Create(const aStream: TStream); overload;
+    constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload;
+    constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload;
     {$IFDEF GLB_DELPHI}
-    constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil);
-    constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload;
-    constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload;
+    constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload;
+    constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload;
     {$ENDIF}
-    constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload;
-    constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload;
-  end;
+  private
+    {$IFDEF GLB_SUPPORT_PNG_READ}
+    function LoadPNG(const aStream: TStream): Boolean; virtual;
+    procedure SavePNG(const aStream: TStream); virtual;
+    {$ENDIF}
+    {$IFDEF GLB_SUPPORT_JPEG_READ}
+    function LoadJPEG(const aStream: TStream): Boolean; virtual;
+    procedure SaveJPEG(const aStream: TStream); virtual;
+    {$ENDIF}
+    function LoadBMP(const aStream: TStream): Boolean; virtual;
+    procedure SaveBMP(const aStream: TStream); virtual;
 
+    function LoadTGA(const aStream: TStream): Boolean; virtual;
+    procedure SaveTGA(const aStream: TStream); virtual;
+
+    function LoadDDS(const aStream: TStream): Boolean; virtual;
+    procedure SaveDDS(const aStream: TStream); virtual;
+  end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   TglBitmap2D = class(TglBitmap)
   protected
     // Bildeinstellungen
     fLines: array of PByte;
 
+    (* TODO
     procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
     procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
     procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
     procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
     procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
-    function GetScanline(Index: Integer): Pointer;
-
     procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
+    *)
 
-    procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override;
-    procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
+    function GetScanline(const aIndex: Integer): Pointer;
+    procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
+      const aWidth: Integer = - 1; const aHeight: Integer = - 1); override;
+    procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
   public
     property Width;
     property Height;
-    property Scanline[Index: Integer]: Pointer read GetScanline;
+    property Scanline[const aIndex: Integer]: Pointer read GetScanline;
 
     procedure AfterConstruction; override;
 
-    procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat);
+    procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
     procedure GetDataFromTexture;
-    procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False);
-    procedure GenTexture(TestTextureSize: Boolean = True); override;
+    procedure GenTexture(const aTestTextureSize: Boolean = true); override;
 
     function FlipHorz: Boolean; override;
     function FlipVert: Boolean; override;
+
+    procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3;
+      const aScale: Single = 2; const aUseAlpha: Boolean = false);
   end;
 
 (* TODO
@@ -953,14 +943,14 @@ type
     fGenMode: Integer;
 
     // Hide GenTexture
-    procedure GenTexture(TestTextureSize: Boolean = True); reintroduce;
+    procedure GenTexture(TestTextureSize: Boolean = true); reintroduce;
   public
     procedure AfterConstruction; override;
 
     procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true);
 
-    procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual;
-    procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual;
+    procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual;
+    procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual;
   end;
 
 
@@ -988,14 +978,17 @@ type
     function FlipHorz: Boolean; override;
 
     // Generation
-    procedure GenTexture(TestTextureSize: Boolean = True); override;
+    procedure GenTexture(TestTextureSize: Boolean = true); override;
   end;
 *)
 
+const
+  NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0);
+
 procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
 procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
+procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
 procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
-procedure glBitmapSetDefaultInternalFormat(const aInternalFormat: TglBitmapInternalFormat);
 procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
 procedure glBitmapSetDefaultWrap(
   const S: Cardinal = GL_CLAMP_TO_EDGE;
@@ -1004,37 +997,19 @@ procedure glBitmapSetDefaultWrap(
 
 function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
 function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
+function glBitmapGetDefaultMipmap: TglBitmapMipMap;
 function glBitmapGetDefaultFormat: TglBitmapFormat;
-function glBitmapGetDefaultInternalFormat: TglBitmapInternalFormat;
 procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
 procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
 
-// position / size
 function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition;
-
-// Formatfunctions
-function FormatGetSize(Format: TglBitmapInternalFormat): Single;
-function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
-function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
-function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
-function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
-procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
-function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
-function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
-function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
-
-
-(* TODO
-function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
-function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
-function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
-*)
+function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
 
 var
   glBitmapDefaultDeleteTextureOnFree: Boolean;
   glBitmapDefaultFreeDataAfterGenTextures: Boolean;
   glBitmapDefaultFormat: TglBitmapFormat;
-  glBitmapDefaultInternalFormat: TglBitmapInternalFormat;
+  glBitmapDefaultMipmap: TglBitmapMipMap;
   glBitmapDefaultFilterMin: Cardinal;
   glBitmapDefaultFilterMag: Cardinal;
   glBitmapDefaultWrapS: Cardinal;
@@ -1047,10 +1022,480 @@ function CreateGrayPalette: HPALETTE;
 
 implementation
 
+
+    (* TODO
+    function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
+    function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
+    function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
+    function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean;
+    function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
+    *)
+
 uses
-  Math;
+  Math, syncobjs;
 
-(* TODO
+type
+////////////////////////////////////////////////////////////////////////////////////////////////////
+  TShiftRec = packed record
+  case Integer of
+    0: (r, g, b, a: Byte);
+    1: (arr: array[0..3] of Byte);
+  end;
+
+  TFormatDescriptor = class(TObject)
+  private
+    function GetRedMask: UInt64;
+    function GetGreenMask: UInt64;
+    function GetBlueMask: UInt64;
+    function GetAlphaMask: UInt64;
+  protected
+    fFormat: TglBitmapFormat;
+    fWithAlpha: TglBitmapFormat;
+    fWithoutAlpha: TglBitmapFormat;
+    fPixelSize: Single;
+
+    fRange: TglBitmapColorRec;
+    fShift: TShiftRec;
+
+    fglFormat:         Cardinal;
+    fglInternalFormat: Cardinal;
+    fglDataFormat:     Cardinal;
+
+    function GetComponents: Integer; virtual;
+  public
+    property Format:       TglBitmapFormat read fFormat;
+    property WithAlpha:    TglBitmapFormat read fWithAlpha;
+    property WithoutAlpha: TglBitmapFormat read fWithoutAlpha;
+    property Components:   Integer         read GetComponents;
+    property PixelSize:    Single          read fPixelSize;
+
+    property glFormat:         Cardinal read fglFormat;
+    property glInternalFormat: Cardinal read fglInternalFormat;
+    property glDataFormat:     Cardinal read fglDataFormat;
+
+    property Range: TglBitmapColorRec read fRange;
+    property Shift: TShiftRec         read fShift;
+
+    property RedMask:   UInt64 read GetRedMask;
+    property GreenMask: UInt64 read GetGreenMask;
+    property BlueMask:  UInt64 read GetBlueMask;
+    property AlphaMask: UInt64 read GetAlphaMask;
+
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
+
+    function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload;
+    function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload;
+
+    function CreateMappingData: Pointer; virtual;
+    procedure FreeMappingData(var aMappingData: Pointer); virtual;
+
+    function IsEmpty:  Boolean; virtual;
+    function HasAlpha: Boolean; virtual;
+    function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual;
+
+    procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual;
+
+    constructor Create; virtual;
+  public
+    class procedure Init;
+    class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
+    class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
+    class procedure Clear;
+    class procedure Finalize;
+  end;
+  TFormatDescriptorClass = class of TFormatDescriptor;
+
+  TfdEmpty = class(TFormatDescriptor);
+
+  TfdAlpha8 = 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;
+
+  TfdAlpha16 = 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;
+
+  TfdLuminance8 = 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;
+
+  TfdLuminance16 = 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;
+
+  TfdLuminance4Alpha4 = 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;
+
+  TfdLuminance6Alpha2 = class(TfdLuminance4Alpha4)
+    constructor Create; override;
+  end;
+
+  TfdLuminance8Alpha8 = 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;
+
+  TfdLuminance12Alpha4 = class(TfdLuminance8Alpha8)
+    constructor Create; override;
+  end;
+
+  TfdLuminance16Alpha16 = 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;
+
+  TfdR3G3B2 = 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;
+
+  TfdRGB4 = 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;
+
+  TfdR5G6B5 = class(TfdRGB4)
+    constructor Create; override;
+  end;
+
+  TfdRGB5 = class(TfdRGB4)
+    constructor Create; override;
+  end;
+
+  TfdRGB8 = 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;
+
+  TfdRGB10 = 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;
+
+  TfdRGB16 = 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;
+
+  TfdRGBA2 = class(TfdR3G3B2)
+    constructor Create; override;
+  end;
+
+  TfdRGBA4 = class(TfdRGB4)
+    constructor Create; override;
+  end;
+
+  TfdRGB5A1 = class(TfdRGB5)
+    constructor Create; override;
+  end;
+
+  TfdRGBA8 = class(TfdRGB8)
+    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;
+
+  TfdRGB10A2 = class(TfdRGB10)
+    constructor Create; override;
+  end;
+
+  TfdRGBA16 = class(TfdRGB16)
+    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;
+
+  TfdBGR4 = class(TfdRGB4)
+    constructor Create; override;
+  end;
+
+  TfdB5G6R5 = class(TfdRGB4)
+    constructor Create; override;
+  end;
+
+  TfdBGR5 = class(TfdRGB5)
+    constructor Create; override;
+  end;
+
+  TfdBGR8 = 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;
+
+  TfdBGR10 = class(TfdRGB10)
+    constructor Create; override;
+  end;
+
+  TfdBGR16 = 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;
+
+  TfdBGRA2 = class(TfdRGBA2)
+    constructor Create; override;
+  end;
+
+  TfdBGRA4 = class(TfdRGBA4)
+    constructor Create; override;
+  end;
+
+  TfdBGR5A1 = class(TfdRGB5A1)
+    constructor Create; override;
+  end;
+
+  TfdBGRA8 = class(TfdBGR8)
+    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;
+
+  TfdBGR10A2 = class(TfdRGB10A2)
+    constructor Create; override;
+  end;
+
+  TfdBGRA16 = class(TfdBGR16)
+    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)
+  private
+    procedure SetRedMask  (const aValue: UInt64);
+    procedure SetGreenMask(const aValue: UInt64);
+    procedure SetBlueMask (const aValue: UInt64);
+    procedure SetAlphaMask(const aValue: UInt64);
+
+    procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte);
+  public
+    property RedMask:   UInt64 read GetRedMask   write SetRedMask;
+    property GreenMask: UInt64 read GetGreenMask write SetGreenMask;
+    property BlueMask:  UInt64 read GetBlueMask  write SetBlueMask;
+    property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask;
+
+    property PixelSize: Single read fPixelSize write fPixelSize;
+
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+  end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+  TColorTableEnty = packed record
+    b, g, r, a: Byte;
+  end;
+  TColorTable = array of TColorTableEnty;
+  TColorTableFormat = class(TFormatDescriptor)
+  private
+    fColorTable: TColorTable;
+  public
+    property PixelSize:  Single            read fPixelSize  write fPixelSize;
+    property ColorTable: TColorTable       read fColorTable write fColorTable;
+    property Range:      TglBitmapColorRec read fRange      write fRange;
+
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    destructor Destroy; override;
+  end;
+
+const
+  LUMINANCE_WEIGHT_R = 0.30;
+  LUMINANCE_WEIGHT_G = 0.59;
+  LUMINANCE_WEIGHT_B = 0.11;
+
+  ALPHA_WEIGHT_R = 0.30;
+  ALPHA_WEIGHT_G = 0.59;
+  ALPHA_WEIGHT_B = 0.11;
+
+  UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.';
+
+  FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = (
+    TfdEmpty,
+
+    //TfdAlpha4,
+    TfdAlpha8,
+    //TfdAlpha12,
+    TfdAlpha16,
+
+    //TfdLuminance4,
+    TfdLuminance8,
+    //TfdLuminance12,
+    TfdLuminance16,
+
+    TfdLuminance4Alpha4,
+    TfdLuminance6Alpha2,
+    TfdLuminance8Alpha8,
+    TfdLuminance12Alpha4,
+    //TfdLuminance12Alpha12,
+    TfdLuminance16Alpha16,
+
+    TfdR3G3B2,
+    TfdRGB4,
+    TfdR5G6B5,
+    TfdRGB5,
+    TfdRGB8,
+    TfdRGB10,
+    //TfdRGB12,
+    TfdRGB16,
+
+    TfdRGBA2,
+    TfdRGBA4,
+    TfdRGB5A1,
+    TfdRGBA8,
+    TfdRGB10A2,
+    //TfdRGBA12,
+    TfdRGBA16,
+
+    TfdBGR4,
+    TfdB5G6R5,
+    TfdBGR5,
+    TfdBGR8,
+    TfdBGR10,
+    //TfdBGR12,
+    TfdBGR16,
+
+    TfdBGRA2,
+    TfdBGRA4,
+    TfdBGR5A1,
+    TfdBGRA8,
+    TfdBGR10A2,
+    //TfdBGRA12,
+    TfdBGRA16
+
+    //TfdDepth16,
+    //TfdDepth24,
+    //TfdDepth32
+  );
+
+var
+  FormatDescriptorCS: TCriticalSection;
+  FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
+begin
+  result.Fields := [];
+
+  if X >= 0 then
+    result.Fields := result.Fields + [ffX];
+  if Y >= 0 then
+    result.Fields := result.Fields + [ffY];
+
+  result.X := Max(0, X);
+  result.Y := Max(0, Y);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec;
+begin
+  result.r := r;
+  result.g := g;
+  result.b := b;
+  result.a := a;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes;
+begin
+  //TODO Supported File Formats!
+  result := [ftDDS, ftTGA, ftBMP];
+  (*
+  {$IFDEF GLB_SUPPORT_PNG_WRITE}
+  if aFormat in [
+    tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
+    tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
+    tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
+    tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
+    tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
+    tfDepth16, tfDepth24, tfDepth32]
+  then
+    result := result + [ftPNG];
+  {$ENDIF}
+
+  {$IFDEF GLB_SUPPORT_JPEG_WRITE}
+  if Format in [
+    tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
+    tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
+    tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
+    tfDepth16, tfDepth24, tfDepth32]
+  then
+    result := result + [ftJPEG];
+  {$ENDIF}
+
+  if aFormat in [
+    tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16,
+    tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16,
+    tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16,
+    tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16,
+    tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16,
+    tfDepth16, tfDepth24, tfDepth32]
+  then
+    result := result + [ftDDS, ftTGA, ftBMP];
+  *)
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function IsPowerOfTwo(aNumber: Integer): Boolean;
+begin
+  while (aNumber and 1) = 0 do
+    aNumber := aNumber shr 1;
+  result := aNumber = 1;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function GetTopMostBit(aBitSet: UInt64): Integer;
+begin
+  result := 0;
+  while aBitSet > 0 do begin
+    inc(result);
+    aBitSet := aBitSet shr 1;
+  end;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function CountSetBits(aBitSet: UInt64): Integer;
+begin
+  result := 0;
+  while aBitSet > 0 do begin
+    if (aBitSet and 1) = 1 then
+      inc(result);
+    aBitSet := aBitSet shr 1;
+  end;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal;
+begin
+  result := Trunc(
+    LUMINANCE_WEIGHT_R * aPixel.Data.r +
+    LUMINANCE_WEIGHT_G * aPixel.Data.g +
+    LUMINANCE_WEIGHT_B * aPixel.Data.b);
+end;
+
+//TODO check _ARB functions and constants
+
+(* GLB_NO_NATIVE_GL
 {$IFNDEF GLB_NO_NATIVE_GL}
 procedure ReadOpenGLExtensions;
 var
@@ -1098,19 +1543,19 @@ var
     ExtPos: Integer;
   begin
     ExtPos := Pos(Extension, Buffer);
-    Result := ExtPos > 0;
+    result := ExtPos > 0;
 
-    if Result then
-      Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
+    if result then
+      result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']);
   end;
 
 
   function glLoad (aFunc: pAnsiChar): pointer;
   begin
     {$IFDEF LINUX}
-      Result := glXGetProcAddress(aFunc);
+      result := glXGetProcAddress(aFunc);
     {$else}
-      Result := wglGetProcAddress(aFunc);
+      result := wglGetProcAddress(aFunc);
     {$ENDIF}
   end;
 
@@ -1127,29 +1572,29 @@ begin
     Buffer := glGetString(GL_VERSION);
     TrimVersionString(Buffer, MajorVersion, MinorVersion);
 
-    GL_VERSION_1_2 := False;
-    GL_VERSION_1_3 := False;
-    GL_VERSION_1_4 := False;
-    GL_VERSION_2_0 := False;
+    GL_VERSION_1_2 := false;
+    GL_VERSION_1_3 := false;
+    GL_VERSION_1_4 := false;
+    GL_VERSION_2_0 := false;
 
     if MajorVersion = 1 then begin
       if MinorVersion >= 1 then begin
         if MinorVersion >= 2 then
-          GL_VERSION_1_2 := True;
+          GL_VERSION_1_2 := true;
 
         if MinorVersion >= 3 then
-          GL_VERSION_1_3 := True;
+          GL_VERSION_1_3 := true;
 
         if MinorVersion >= 4 then
-          GL_VERSION_1_4 := True;
+          GL_VERSION_1_4 := true;
       end;
     end;
 
     if MajorVersion >= 2 then begin
-      GL_VERSION_1_2 := True;
-      GL_VERSION_1_3 := True;
-      GL_VERSION_1_4 := True;
-      GL_VERSION_2_0 := True;
+      GL_VERSION_1_2 := true;
+      GL_VERSION_1_3 := true;
+      GL_VERSION_1_4 := true;
+      GL_VERSION_2_0 := true;
     end;
 
     // Extensions
 {$ENDIF}
 *)
 
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition;
+(* TODO GLB_DELPHI
+{$IFDEF GLB_DELPHI}
+function CreateGrayPalette: HPALETTE;
+var
+  Idx: Integer;
+  Pal: PLogPalette;
 begin
-  Result.Fields := [];
-
-  if X >= 0 then
-    Result.Fields := Result.Fields + [ffX];
-  if Y >= 0 then
-    Result.Fields := Result.Fields + [ffY];
+  GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
 
-  Result.X := Max(0, X);
-  Result.Y := Max(0, Y);
-end;
+  Pal.palVersion := $300;
+  Pal.palNumEntries := 256;
 
+  {$IFOPT R+}
+    {$DEFINE GLB_TEMPRANGECHECK}
+    {$R-}
+  {$ENDIF}
 
-const
-  LUMINANCE_WEIGHT_R = 0.30;
-  LUMINANCE_WEIGHT_G = 0.59;
-  LUMINANCE_WEIGHT_B = 0.11;
-  UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.';
+  for Idx := 0 to 256 - 1 do begin
+    Pal.palPalEntry[Idx].peRed   := Idx;
+    Pal.palPalEntry[Idx].peGreen := Idx;
+    Pal.palPalEntry[Idx].peBlue  := Idx;
+    Pal.palPalEntry[Idx].peFlags := 0;
+  end;
 
-{$REGION PixelDescription}
-const
-  //ifAlpha4////////////////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_ALPHA4: TglBitmapPixelDesc = (
-    RedRange:   $00000000; RedShift:   0;
-    GreenRange: $00000000; GreenShift: 0;
-    BlueRange:  $00000000; BlueShift:  0;
-    AlphaRange: $0000000F; AlphaShift: 0);
-
-  //ifAlpha8
-  PIXEL_DESC_ALPHA8: TglBitmapPixelDesc = (
-    RedRange:   $00000000; RedShift:   0;
-    GreenRange: $00000000; GreenShift: 0;
-    BlueRange:  $00000000; BlueShift:  0;
-    AlphaRange: $000000FF; AlphaShift: 0);
-
-  //ifAlpha12
-  PIXEL_DESC_ALPHA12: TglBitmapPixelDesc = (
-    RedRange:   $00000000; RedShift:   0;
-    GreenRange: $00000000; GreenShift: 0;
-    BlueRange:  $00000000; BlueShift:  0;
-    AlphaRange: $00000FFF; AlphaShift: 0);
-
-  //ifAlpha16
-  PIXEL_DESC_ALPHA16: TglBitmapPixelDesc = (
-    RedRange:   $00000000; RedShift:   0;
-    GreenRange: $00000000; GreenShift: 0;
-    BlueRange:  $00000000; BlueShift:  0;
-    AlphaRange: $0000FFFF; AlphaShift: 0);
-
-  //ifLuminance4////////////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_LUMINANCE4: TglBitmapPixelDesc = (
-    RedRange:   $0000000F; RedShift:   0;
-    GreenRange: $0000000F; GreenShift: 0;
-    BlueRange:  $0000000F; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifLuminance8
-  PIXEL_DESC_LUMINANCE8: TglBitmapPixelDesc = (
-    RedRange:   $000000FF; RedShift:   0;
-    GreenRange: $000000FF; GreenShift: 0;
-    BlueRange:  $000000FF; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifLuminance12
-  PIXEL_DESC_LUMINANCE12: TglBitmapPixelDesc = (
-    RedRange:   $00000FFF; RedShift:   0;
-    GreenRange: $00000FFF; GreenShift: 0;
-    BlueRange:  $00000FFF; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifLuminance16
-  PIXEL_DESC_LUMINANCE16: TglBitmapPixelDesc = (
-    RedRange:   $0000FFFF; RedShift:   0;
-    GreenRange: $0000FFFF; GreenShift: 0;
-    BlueRange:  $0000FFFF; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifLuminance4Alpha4//////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_LUMINANCE4_ALPHA4: TglBitmapPixelDesc = (
-    RedRange:   $0000000F; RedShift:   0;
-    GreenRange: $0000000F; GreenShift: 0;
-    BlueRange:  $0000000F; BlueShift:  0;
-    AlphaRange: $0000000F; AlphaShift: 4);
-  //ifLuminance6Alpha2
-  PIXEL_DESC_LUMINANCE6_ALPHA2: TglBitmapPixelDesc = (
-    RedRange:   $0000003F; RedShift:   0;
-    GreenRange: $0000003F; GreenShift: 0;
-    BlueRange:  $0000003F; BlueShift:  0;
-    AlphaRange: $00000003; AlphaShift: 6);
-
-  //ifLuminance8Alpha8
-  PIXEL_DESC_LUMINANCE8_ALPHA8: TglBitmapPixelDesc = (
-    RedRange:   $000000FF; RedShift:   0;
-    GreenRange: $000000FF; GreenShift: 0;
-    BlueRange:  $000000FF; BlueShift:  0;
-    AlphaRange: $000000FF; AlphaShift: 8);
-
-  //ifLuminance12Alpha4
-  PIXEL_DESC_LUMINANCE12_ALPHA4: TglBitmapPixelDesc = (
-    RedRange:   $00000FFF; RedShift:   0;
-    GreenRange: $00000FFF; GreenShift: 0;
-    BlueRange:  $00000FFF; BlueShift:  0;
-    AlphaRange: $0000000F; AlphaShift: 12);
-
-  //ifLuminance12Alpha12
-  PIXEL_DESC_LUMINANCE12_ALPHA12: TglBitmapPixelDesc = (
-    RedRange:   $00000FFF; RedShift:   0;
-    GreenRange: $00000FFF; GreenShift: 0;
-    BlueRange:  $00000FFF; BlueShift:  0;
-    AlphaRange: $00000FFF; AlphaShift: 12);
-
-  //ifLuminance16Alpha16
-  PIXEL_DESC_LUMINANCE16_ALPHA16: TglBitmapPixelDesc = (
-    RedRange:   $0000FFFF; RedShift:   0;
-    GreenRange: $0000FFFF; GreenShift: 0;
-    BlueRange:  $0000FFFF; BlueShift:  0;
-    AlphaRange: $0000FFFF; AlphaShift: 16);
-
-  //ifR3G3B2////////////////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_R3_G3_B2: TglBitmapPixelDesc = (
-    RedRange:   $00000007; RedShift:   0;
-    GreenRange: $00000007; GreenShift: 3;
-    BlueRange:  $00000003; BlueShift:  6;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifRGB4
-  PIXEL_DESC_RGB4: TglBitmapPixelDesc = (
-    RedRange:   $0000000F; RedShift:   0;
-    GreenRange: $0000000F; GreenShift: 4;
-    BlueRange:  $0000000F; BlueShift:  8;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifRGB5
-  PIXEL_DESC_RGB5: TglBitmapPixelDesc = (
-    RedRange:   $0000001F; RedShift:   0;
-    GreenRange: $0000001F; GreenShift: 5;
-    BlueRange:  $0000001F; BlueShift:  10;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifRGB8
-  PIXEL_DESC_RGB8: TglBitmapPixelDesc = (
-    RedRange:   $000000FF; RedShift:   0;
-    GreenRange: $000000FF; GreenShift: 8;
-    BlueRange:  $000000FF; BlueShift:  16;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifRGB10
-  PIXEL_DESC_RGB10: TglBitmapPixelDesc = (
-    RedRange:   $000003FF; RedShift:   0;
-    GreenRange: $000003FF; GreenShift: 10;
-    BlueRange:  $000003FF; BlueShift:  20;
-    AlphaRange: $000003FF; AlphaShift: 0);
-
-  //ifRGB12
-  PIXEL_DESC_RGB12: TglBitmapPixelDesc = (
-    RedRange:   $00000000; RedShift:   0;
-    GreenRange: $00000000; GreenShift: 0;
-    BlueRange:  $00000000; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-
-  //ifRGB16
-  PIXEL_DESC_RGB16: TglBitmapPixelDesc = (
-    RedRange:   $0000FFFF; RedShift:   0;
-    GreenRange: $0000FFFF; GreenShift: 16;
-    BlueRange:  $0000FFFF; BlueShift:  32;
-    AlphaRange: $0000FFFF; AlphaShift: 0);
-
-  //ifRGBA2/////////////////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_RGBA2: TglBitmapPixelDesc = (
-    RedRange:   $00000003; RedShift:   0;
-    GreenRange: $00000003; GreenShift: 2;
-    BlueRange:  $00000003; BlueShift:  4;
-    AlphaRange: $00000003; AlphaShift: 6);
-
-  //ifRGBA4
-  PIXEL_DESC_RGBA4: TglBitmapPixelDesc = (
-    RedRange:   $0000000F; RedShift:   0;
-    GreenRange: $0000000F; GreenShift: 4;
-    BlueRange:  $0000000F; BlueShift:  8;
-    AlphaRange: $0000000F; AlphaShift: 12);
-
-  //ifRGB5A1
-  PIXEL_DESC_RGB5_A1: TglBitmapPixelDesc = (
-    RedRange:   $0000001F; RedShift:   0;
-    GreenRange: $0000001F; GreenShift: 5;
-    BlueRange:  $0000001F; BlueShift:  10;
-    AlphaRange: $00000001; AlphaShift: 11);
-
-  //ifRGBA8
-  PIXEL_DESC_RGBA8: TglBitmapPixelDesc = (
-    RedRange:   $000000FF; RedShift:   0;
-    GreenRange: $000000FF; GreenShift: 8;
-    BlueRange:  $000000FF; BlueShift:  16;
-    AlphaRange: $000000FF; AlphaShift: 24);
-
-  //ifRGB10A2
-  PIXEL_DESC_RGB10_A2: TglBitmapPixelDesc = (
-    RedRange:   $000003FF; RedShift:   0;
-    GreenRange: $000003FF; GreenShift: 10;
-    BlueRange:  $000003FF; BlueShift:  20;
-    AlphaRange: $00000003; AlphaShift: 22);
-
-  //ifRGBA12
-  PIXEL_DESC_RGBA12: TglBitmapPixelDesc = (
-    RedRange:   $00000FFF; RedShift:   0;
-    GreenRange: $00000FFF; GreenShift: 12;
-    BlueRange:  $00000FFF; BlueShift:  24;
-    AlphaRange: $00000FFF; AlphaShift: 36);
-
-  //ifRGBA16
-  PIXEL_DESC_RGBA16: TglBitmapPixelDesc = (
-    RedRange:   $0000FFFF; RedShift:   0;
-    GreenRange: $0000FFFF; GreenShift: 16;
-    BlueRange:  $0000FFFF; BlueShift:  32;
-    AlphaRange: $0000FFFF; AlphaShift: 48);
-
-  //ifDepthComponent16//////////////////////////////////////////////////////////////////////////////
-  PIXEL_DESC_DEPTH16: TglBitmapPixelDesc = (
-    RedRange:   $0000FFFF; RedShift:   0;
-    GreenRange: $0000FFFF; GreenShift: 0;
-    BlueRange:  $0000FFFF; BlueShift:  0;
-    AlphaRange: $0000FFFF; AlphaShift: 0);
-
-  //ifDepthComponent24
-  PIXEL_DESC_DEPTH24: TglBitmapPixelDesc = (
-    RedRange:   $00FFFFFF; RedShift:   0;
-    GreenRange: $00FFFFFF; GreenShift: 0;
-    BlueRange:  $00FFFFFF; BlueShift:  0;
-    AlphaRange: $00FFFFFF; AlphaShift: 0);
-
-  //ifDepthComponent32
-  PIXEL_DESC_DEPTH32: TglBitmapPixelDesc = (
-    RedRange:   $FFFFFFFF; RedShift:   0;
-    GreenRange: $FFFFFFFF; GreenShift: 0;
-    BlueRange:  $FFFFFFFF; BlueShift:  0;
-    AlphaRange: $00000000; AlphaShift: 0);
-{$ENDREGION}
-
-{$REGION MapFunctions}
-//ALPHA/////////////////////////////////////////////////////////////////////////////////////////////
-procedure MapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  //TODO
-end;
-
-procedure MapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  aData^ := aPixel.Alpha;
-  inc(aData);
-end;
+  {$IFDEF GLB_TEMPRANGECHECK}
+    {$UNDEF GLB_TEMPRANGECHECK}
+    {$R+}
+  {$ENDIF}
 
-procedure MapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  //TODO
-end;
+  result := CreatePalette(Pal^);
 
-procedure MapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  PWord(aData)^ := aPixel.Alpha;
-  inc(aData, 2);
+  FreeMem(Pal);
 end;
+{$ENDIF}
+*)
 
-//LUMINANCE/////////////////////////////////////////////////////////////////////////////////////////
-procedure MapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+(* TODO GLB_SDL_IMAGE
+{$IFDEF GLB_SDL_IMAGE}
+function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
 begin
-  //TODO
+  result := TStream(context^.unknown.data1).Seek(offset, whence);
 end;
 
-procedure MapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
 begin
-  aData^ := Trunc(
-    aPixel.Red   * LUMINANCE_WEIGHT_R +
-    aPixel.Green * LUMINANCE_WEIGHT_G +
-    aPixel.Blue  * LUMINANCE_WEIGHT_B);
-  inc(aData);
+  result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
 end;
 
-procedure MapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
 begin
-  //TODO
+  result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
 end;
 
-procedure MapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
 begin
-  PWord(aData)^ := Trunc(
-    aPixel.Red   * LUMINANCE_WEIGHT_R +
-    aPixel.Green * LUMINANCE_WEIGHT_G +
-    aPixel.Blue  * LUMINANCE_WEIGHT_B);
-  inc(aData, 2);
+  result := 0;
 end;
 
-//LUMINANCE_ALPHA///////////////////////////////////////////////////////////////////////////////////
-procedure MapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
 begin
-  aData^ :=
-    ((Trunc(aPixel.Red   * LUMINANCE_WEIGHT_R +
-            aPixel.Green * LUMINANCE_WEIGHT_G +
-            aPixel.Blue  * LUMINANCE_WEIGHT_B) and
-      aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
-  inc(aData);
-end;
+  result := SDL_AllocRW;
 
-procedure MapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  MapLuminance4Alpha4(aPixel, aData, aBitOffset);
-end;
+  if result = nil then
+    raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
 
-procedure MapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
-  PWord(aData)^ :=
-    ((Trunc(aPixel.Red   * LUMINANCE_WEIGHT_R +
-            aPixel.Green * LUMINANCE_WEIGHT_G +
-            aPixel.Blue  * LUMINANCE_WEIGHT_B) and
-      aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
-  inc(aData, 2);
+  result^.seek := glBitmapRWseek;
+  result^.read := glBitmapRWread;
+  result^.write := glBitmapRWwrite;
+  result^.close := glBitmapRWclose;
+  result^.unknown.data1 := Stream;
 end;
+{$ENDIF}
+*)
 
-procedure MapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+(* TODO LoadFuncs
+function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
+var
+  glBitmap: TglBitmap2D;
 begin
-  MapLuminance8Alpha8(aPixel, aData, aBitOffset);
+  result := false;
+  Texture := 0;
+
+  {$IFDEF GLB_DELPHI}
+  if Instance = 0 then
+    Instance := HInstance;
+
+  if (LoadFromRes) then
+    glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
+  else
+  {$ENDIF}
+    glBitmap := TglBitmap2D.Create(FileName);
+
+  try
+    glBitmap.DeleteTextureOnFree := false;
+    glBitmap.FreeDataAfterGenTexture := false;
+    glBitmap.GenTexture(true);
+    if (glBitmap.ID > 0) then begin
+      Texture := glBitmap.ID;
+      result := true;
+    end;
+  finally
+    glBitmap.Free;
+  end;
 end;
 
-procedure MapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
+var
+  CM: TglBitmapCubeMap;
 begin
-  //TODO
+  Texture := 0;
+
+  {$IFDEF GLB_DELPHI}
+  if Instance = 0 then
+    Instance := HInstance;
+  {$ENDIF}
+
+  CM := TglBitmapCubeMap.Create;
+  try
+    CM.DeleteTextureOnFree := false;
+
+    // Maps
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, PositiveX)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(PositiveX);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, NegativeX)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(NegativeX);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
+
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, PositiveY)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(PositiveY);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
+
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, NegativeY)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(NegativeY);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
+
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, PositiveZ)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(PositiveZ);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
+
+    {$IFDEF GLB_DELPHI}
+    if (LoadFromRes) then
+      CM.LoadFromResource(Instance, NegativeZ)
+    else
+    {$ENDIF}
+      CM.LoadFromFile(NegativeZ);
+    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+
+    Texture := CM.ID;
+    result := true;
+  finally
+    CM.Free;
+  end;
 end;
 
-procedure MapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
+var
+  NM: TglBitmapNormalMap;
 begin
-  PCardinal(aData)^ :=
-    ((Trunc(aPixel.Red   * LUMINANCE_WEIGHT_R +
-            aPixel.Green * LUMINANCE_WEIGHT_G +
-            aPixel.Blue  * LUMINANCE_WEIGHT_B) and
-      aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift;
-  inc(aData, 4);
+  Texture := 0;
+
+  NM := TglBitmapNormalMap.Create;
+  try
+    NM.DeleteTextureOnFree := false;
+    NM.GenerateNormalMap(Size);
+
+    Texture := NM.ID;
+    result := true;
+  finally
+    NM.Free;
+  end;
 end;
+*)
 
-//RGB///////////////////////////////////////////////////////////////////////////////////////////////
-procedure MapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean);
 begin
-  aData^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift);
-  inc(aData);
+  glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree;
 end;
 
-procedure MapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean);
 begin
-  //TODO
+  glBitmapDefaultFreeDataAfterGenTextures := aFreeData;
 end;
 
-procedure MapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap);
 begin
-  //TODO
+  glBitmapDefaultMipmap := aValue;
 end;
 
-procedure MapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat);
 begin
-  PCardinal(aData)^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift);
-  inc(aData, 3);
+  glBitmapDefaultFormat := aFormat;
 end;
 
-procedure MapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer);
 begin
-  //TODO
+  glBitmapDefaultFilterMin := aMin;
+  glBitmapDefaultFilterMag := aMag;
 end;
 
-procedure MapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE);
 begin
-  //TODO
+  glBitmapDefaultWrapS := S;
+  glBitmapDefaultWrapT := T;
+  glBitmapDefaultWrapR := R;
 end;
 
-procedure MapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
 begin
-  PWord(aData)^ := aPixel.Red;
-  inc(aData, 2);
-  PWord(aData)^ := aPixel.Green;
-  inc(aData, 2);
-  PWord(aData)^ := aPixel.Blue;
-  inc(aData, 2);
+  result := glBitmapDefaultDeleteTextureOnFree;
 end;
 
-//RGBA//////////////////////////////////////////////////////////////////////////////////////////////
-procedure MapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
 begin
-  aData^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift)  or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
-  inc(aData);
+  result := glBitmapDefaultFreeDataAfterGenTextures;
 end;
 
-procedure MapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapGetDefaultMipmap: TglBitmapMipMap;
 begin
-  PWord(aData)^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift)  or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
-  inc(aData, 2);
+  result := glBitmapDefaultMipmap;
 end;
 
-procedure MapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapGetDefaultFormat: TglBitmapFormat;
 begin
-  PWord(aData)^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift)  or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
-  inc(aData, 2);
+  result := glBitmapDefaultFormat;
 end;
 
-procedure MapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal);
 begin
-  PCardinal(aData)^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift)  or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
-  inc(aData, 4);
+  aMin := glBitmapDefaultFilterMin;
+  aMag := glBitmapDefaultFilterMag;
 end;
 
-procedure MapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal);
 begin
-  PCardinal(aData)^ :=
-    ((aPixel.Red   and aPixel.PixelDesc.RedRange)   shl aPixel.PixelDesc.RedShift)   or
-    ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or
-    ((aPixel.Blue  and aPixel.PixelDesc.BlueRange)  shl aPixel.PixelDesc.BlueShift)  or
-    ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift);
-  inc(aData, 4);
+  S := glBitmapDefaultWrapS;
+  T := glBitmapDefaultWrapT;
+  R := glBitmapDefaultWrapR;
 end;
 
-procedure MapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetRedMask: UInt64;
 begin
-  //TODO
+  result := fRange.r shl fShift.r;
 end;
 
-procedure MapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetGreenMask: UInt64;
 begin
-  PWord(aData)^ := aPixel.Red;
-  inc(aData, 2);
-  PWord(aData)^ := aPixel.Green;
-  inc(aData, 2);
-  PWord(aData)^ := aPixel.Blue;
-  inc(aData, 2);
-  PWord(aData)^ := aPixel.Alpha;
-  inc(aData, 2);
+  result := fRange.g shl fShift.g;
 end;
 
-//DEPTH/////////////////////////////////////////////////////////////////////////////////////////////
-procedure MapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetBlueMask: UInt64;
 begin
-  PWord(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3;
-  inc(aData, 2);
+  result := fRange.b shl fShift.b;
 end;
 
-procedure MapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetAlphaMask: UInt64;
 begin
-  //TODO
+  result := fRange.a shl fShift.a;
 end;
 
-procedure MapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetComponents: Integer;
+var
+  i: Integer;
 begin
-  PCardinal(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3;
-  inc(aData, 4);
+  result := 0;
+  for i := 0 to 3 do
+    if (fRange.arr[i] > 0) then
+      inc(result);
 end;
 
-function FormatGetMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapMapFunc;
-begin
-  case aInternalFormat of
-    ifAlpha4:  result := MapAlpha4;
-    ifAlpha8:  result := MapAlpha8;
-    ifAlpha12: result := MapAlpha12;
-    ifAlpha16: result := MapAlpha16;
-
-    ifLuminance4:  result := MapLuminance4;
-    ifLuminance8:  result := MapLuminance8;
-    ifLuminance12: result := MapLuminance8;
-    ifLuminance16: result := MapLuminance8;
-
-    ifLuminance4Alpha4:   result := MapLuminance4Alpha4;
-    ifLuminance6Alpha2:   result := MapLuminance6Alpha2;
-    ifLuminance8Alpha8:   result := MapLuminance8Alpha8;
-    ifLuminance12Alpha4:  result := MapLuminance12Alpha4;
-    ifLuminance12Alpha12: result := MapLuminance12Alpha12;
-    ifLuminance16Alpha16: result := MapLuminance16Alpha16;
-
-    ifR3G3B2: result := MapR3G3B2;
-    ifRGB4:   result := MapRGB4;
-    ifRGB5:   result := MapRGB5;
-    ifRGB8:   result := MapRGB8;
-    ifRGB10:  result := MapRGB10;
-    ifRGB12:  result := MapRGB12;
-    ifRGB16:  result := MapRGB16;
-
-    ifRGBA2:   result := MapRGBA2;
-    ifRGBA4:   result := MapRGBA4;
-    ifRGB5A1:  result := MapRGB5A1;
-    ifRGBA8:   result := MapRGBA8;
-    ifRGB10A2: result := MapRGB10A2;
-    ifRGBA12:  result := MapRGBA12;
-    ifRGBA16:  result := MapRGBA16;
-
-    ifDepth16: result := MapDepth16;
-    ifDepth24: result := MapDepth24;
-    ifDepth32: result := MapDepth32;
-  else
-    raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
-  end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer;
+var
+  w, h: Integer;
+begin
+  if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin
+    w := Max(1, aSize.X);
+    h := Max(1, aSize.Y);
+    result := GetSize(w, h);
+  end else
+    result := 0;
 end;
-{$ENDREGION}
 
-{$REGION UnmapFunctions}
-//ALPHA/////////////////////////////////////////////////////////////////////////////////////////////
-procedure UnmapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer;
 begin
-  //TODO
+  result := 0;
+  if (aWidth <= 0) or (aHeight <= 0) then
+    exit;
+  result := Ceil(aWidth * aHeight * fPixelSize);
 end;
 
-procedure UnmapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.CreateMappingData: Pointer;
 begin
-
+  result := nil;
 end;
 
-procedure UnmapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer);
 begin
-  //TODO
+  //DUMMY
 end;
 
-procedure UnmapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.IsEmpty: Boolean;
 begin
-
+  result := (fFormat = tfEmpty);
 end;
 
-//LUMINANCE/////////////////////////////////////////////////////////////////////////////////////////
-procedure UnmapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.HasAlpha: Boolean;
 begin
-  //TODO
+  result := (fRange.a > 0);
 end;
 
-procedure UnmapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean;
 begin
+  result := false;
 
+  if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then
+    raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
+
+  if (aRedMask   <> RedMask) then
+    exit;
+  if (aGreenMask <> GreenMask) then
+    exit;
+  if (aBlueMask  <> BlueMask) then
+    exit;
+  if (aAlphaMask <> AlphaMask) then
+    exit;
+  result := true;
 end;
 
-procedure UnmapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData);
 begin
-  //TODO
+  FillChar(aPixel, SizeOf(aPixel), 0);
+  aPixel.Data   := fRange;
+  aPixel.Range  := fRange;
+  aPixel.Format := fFormat;
 end;
 
-procedure UnmapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TFormatDescriptor.Create;
 begin
+  inherited Create;
 
-end;
+  fFormat       := tfEmpty;
+  fWithAlpha    := tfEmpty;
+  fWithoutAlpha := tfEmpty;
+  fPixelSize    := 0.0;
 
-//LUMINANCE_ALPHA///////////////////////////////////////////////////////////////////////////////////
-procedure UnmapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
-begin
+  fglFormat         := 0;
+  fglInternalFormat := 0;
+  fglDataFormat     := 0;
 
+  FillChar(fRange, 0, SizeOf(fRange));
+  FillChar(fShift, 0, SizeOf(fShift));
 end;
 
-procedure UnmapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdAlpha8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdAlpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 begin
-
+  aData^ := aPixel.Data.a;
+  inc(aData);
 end;
 
-procedure UnmapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdAlpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-
+  aPixel.Data.r := 0;
+  aPixel.Data.g := 0;
+  aPixel.Data.b := 0;
+  aPixel.Data.a := aData^;
+  inc(aData^);
 end;
 
-procedure UnmapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdAlpha8.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 1.0;
+  fFormat           := tfAlpha8;
+  fRange.a          := $FF;
+  fglFormat         := GL_ALPHA;
+  fglInternalFormat := GL_ALPHA8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
 end;
 
-procedure UnmapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdAlpha16//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdAlpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 begin
-  //TODO
+  PWord(aData)^ := aPixel.Data.a;
+  inc(aData, 2);
 end;
 
-procedure UnmapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdAlpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-
+  aPixel.Data.r := 0;
+  aPixel.Data.g := 0;
+  aPixel.Data.b := 0;
+  aPixel.Data.a := PWord(aData)^;
+  inc(aData, 2);
 end;
 
-//RGB///////////////////////////////////////////////////////////////////////////////////////////////
-procedure UnmapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdAlpha16.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfAlpha16;
+  fRange.a          := $FFFF;
+  fglFormat         := GL_ALPHA;
+  fglInternalFormat := GL_ALPHA16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
 end;
 
-procedure UnmapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 begin
-  //TODO
+  aData^ := LuminanceWeight(aPixel);
+  inc(aData);
 end;
 
-procedure UnmapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  //TODO
+  aPixel.Data.r := aData^;
+  aPixel.Data.g := aData^;
+  aPixel.Data.b := aData^;
+  aPixel.Data.a := 0;
+  inc(aData);
 end;
 
-procedure UnmapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdLuminance8.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 1.0;
+  fFormat           := tfLuminance8;
+  fWithAlpha        := tfLuminance8Alpha8;
+  fWithoutAlpha     := tfLuminance8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdLuminance16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  PWord(aData)^ := LuminanceWeight(aPixel);
+  inc(aData, 2);
 end;
 
-procedure UnmapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdLuminance16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  //TODO
+  aPixel.Data.r := PWord(aData)^;
+  aPixel.Data.g := PWord(aData)^;
+  aPixel.Data.b := PWord(aData)^;
+  aPixel.Data.a := 0;
+  inc(aData, 2);
 end;
 
-procedure UnmapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdLuminance16.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfLuminance16;
+  fWithAlpha        := tfLuminance16Alpha16;
+  fWithoutAlpha     := tfLuminance16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdLuminance4Alpha4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 begin
-  //TODO
+  aData^ :=
+    ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or
+    ((aPixel.Data.a           and fRange.a) shl fShift.a);
+  inc(aData);
 end;
 
-procedure UnmapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdLuminance4Alpha4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData);
 end;
 
-//RGBA//////////////////////////////////////////////////////////////////////////////////////////////
-procedure UnmapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdLuminance4Alpha4.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 1.0;
+  fFormat           := tfLuminance4Alpha4;
+  fWithAlpha        := tfLuminance4Alpha4;
+  fWithoutAlpha     := tfLuminance8;
+  fRange.r          := $F;
+  fRange.g          := $F;
+  fRange.b          := $F;
+  fRange.a          := $F;
+  fShift.a          :=  4;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE4_ALPHA4;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdLuminance6Alpha2.Create;
+begin
+  inherited Create;
+  fFormat           := tfLuminance6Alpha2;
+  fWithAlpha        := tfLuminance6Alpha2;
+  fWithoutAlpha     := tfLuminance8;
+  fRange.r          := $3F;
+  fRange.g          := $3F;
+  fRange.b          := $3F;
+  fRange.a          := $03;
+  fShift.a          :=   6;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE6_ALPHA2;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  PWord(aData)^ :=
+    ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or
+    ((aPixel.Data.a           and fRange.a) shl fShift.a);
+  inc(aData, 2);
 end;
 
-procedure UnmapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData, 2);
 end;
 
-procedure UnmapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdLuminance8Alpha8.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfLuminance8Alpha8;
+  fWithAlpha        := tfLuminance8Alpha8;
+  fWithoutAlpha     := tfLuminance8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fRange.a          := $FF;
+  fShift.a          :=   8;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE8_ALPHA8;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdLuminance12Alpha4.Create;
+begin
+  inherited Create;
+  fFormat           := tfLuminance12Alpha4;
+  fWithAlpha        := tfLuminance12Alpha4;
+  fWithoutAlpha     := tfLuminance16;
+  fRange.r          := $FFF;
+  fRange.g          := $FFF;
+  fRange.b          := $FFF;
+  fRange.a          := $00F;
+  fShift.a          :=   12;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE12_ALPHA4;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdLuminance16Alpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  PCardinal(aData)^ :=
+    ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or
+    ((aPixel.Data.a           and fRange.a) shl fShift.a);
+  inc(aData, 4);
 end;
 
-procedure UnmapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdLuminance16Alpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData, 4);
 end;
 
-procedure UnmapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdLuminance16Alpha16.Create;
 begin
-
+  inherited Create;
+  fFormat           := tfLuminance16Alpha16;
+  fWithAlpha        := tfLuminance16Alpha16;
+  fWithoutAlpha     := tfLuminance16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fRange.a          := $FFFF;
+  fShift.a          :=    16;
+  fglFormat         := GL_LUMINANCE;
+  fglInternalFormat := GL_LUMINANCE16_ALPHA16;
+  fglDataFormat     := GL_UNSIGNED_INT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdR3G3B2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+var
+  i: Integer;
+begin
+  aData^ := 0;
+  for i := 0 to 3 do
+    if (fRange.arr[i] > 0) then
+      aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
+  inc(aData);
 end;
 
-procedure UnmapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdR3G3B2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-  //TODO
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData);
 end;
 
-procedure UnmapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdR3G3B2.Create;
 begin
-
+  inherited Create;
+  fPixelSize        := 1.0;
+  fFormat           := tfR3G3B2;
+  fWithAlpha        := tfRGBA2;
+  fWithoutAlpha     := tfR3G3B2;
+  fRange.r          := $7;
+  fRange.g          := $7;
+  fRange.b          := $3;
+  fShift.r          :=  0;
+  fShift.g          :=  3;
+  fShift.b          :=  5;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_R3_G3_B2;
+  fglDataFormat     := GL_UNSIGNED_BYTE_2_3_3_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+var
+  i: Integer;
+begin
+  PWord(aData)^ := 0;
+  for i := 0 to 3 do
+    if (fRange.arr[i] > 0) then
+      PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
+  inc(aData, 2);
 end;
 
-//DEPTH/////////////////////////////////////////////////////////////////////////////////////////////
-procedure UnmapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdRGB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData, 2);
 end;
 
-procedure UnmapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+constructor TfdRGB4.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfRGB4;
+  fWithAlpha        := tfRGBA4;
+  fWithoutAlpha     := tfRGB4;
+  fRange.r          := $F;
+  fRange.g          := $F;
+  fRange.b          := $F;
+  fShift.r          :=  0;
+  fShift.g          :=  4;
+  fShift.b          :=  8;
+  fglFormat         := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
+  fglInternalFormat := GL_RGB4;
+  fglDataFormat     := GL_UNSIGNED_SHORT_4_4_4_4_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdR5G6B5.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfR5G6B5;
+  fWithAlpha        := tfRGBA4;
+  fWithoutAlpha     := tfR5G6B5;
+  fRange.r          := $1F;
+  fRange.g          := $3F;
+  fRange.b          := $1F;
+  fShift.r          :=   0;
+  fShift.g          :=   5;
+  fShift.b          :=  11;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_RGB8;
+  fglDataFormat     := GL_UNSIGNED_SHORT_5_6_5_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdRGB5.Create;
 begin
-  //TODO
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfRGB5;
+  fWithAlpha        := tfRGB5A1;
+  fWithoutAlpha     := tfRGB5;
+  fRange.r          := $1F;
+  fRange.g          := $1F;
+  fRange.b          := $1F;
+  fShift.r          :=   0;
+  fShift.g          :=   5;
+  fShift.b          :=  10;
+  fglFormat         := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
+  fglInternalFormat := GL_RGB5;
+  fglDataFormat     := GL_UNSIGNED_SHORT_1_5_5_5_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  aData^ := aPixel.Data.r;
+  inc(aData);
+  aData^ := aPixel.Data.g;
+  inc(aData);
+  aData^ := aPixel.Data.b;
+  inc(aData);
 end;
 
-procedure UnmapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte);
+procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-
+  aPixel.Data.r := aData^;
+  inc(aData);
+  aPixel.Data.g := aData^;
+  inc(aData);
+  aPixel.Data.b := aData^;
+  inc(aData);
+  aPixel.Data.a := 0;
 end;
 
-
-
-
-procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
+constructor TfdRGB8.Create;
 begin
-  Pixel.Alpha := pData^;
-  Pixel.Red   := Pixel.PixelDesc.RedRange;
-  Pixel.Green := Pixel.PixelDesc.GreenRange;
-  Pixel.Blue  := Pixel.PixelDesc.BlueRange;
-
-  Inc(pData);
+  inherited Create;
+  fPixelSize        := 3.0;
+  fFormat           := tfRGB8;
+  fWithAlpha        := tfRGBA8;
+  fWithoutAlpha     := tfRGB8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fShift.r          :=   0;
+  fShift.g          :=   8;
+  fShift.b          :=  16;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_RGB8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGB10.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+var
+  i: Integer;
+begin
+  PCardinal(aData)^ := 0;
+  for i := 0 to 3 do
+    if (fRange.arr[i] > 0) then
+      PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]);
+  inc(aData, 4);
 end;
 
-
-procedure UnMapLuminance(var pData: pByte; var Pixel: TglBitmapPixelData);
+procedure TfdRGB10.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  i: Integer;
 begin
-  Pixel.Alpha := 255;
-  Pixel.Red   := pData^;
-  Pixel.Green := pData^;
-  Pixel.Blue  := pData^;
-
-  Inc(pData);
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData, 4);
 end;
 
-
-procedure UnMapDepth8(var pData: pByte; var Pixel: TglBitmapPixelData);
+constructor TfdRGB10.Create;
 begin
-  Pixel.Alpha := 255;
-  Pixel.Red   := pData^;
-  Pixel.Green := pData^;
-  Pixel.Blue  := pData^;
-
-  Inc(pData);
+  inherited Create;
+  fPixelSize        := 4.0;
+  fFormat           := tfRGB10;
+  fWithAlpha        := tfRGB10A2;
+  fWithoutAlpha     := tfRGB10;
+  fRange.r          := $3FF;
+  fRange.g          := $3FF;
+  fRange.b          := $3FF;
+  fShift.r          :=    0;
+  fShift.g          :=   10;
+  fShift.b          :=   20;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_RGB10;
+  fglDataFormat     := GL_UNSIGNED_INT_2_10_10_10_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGB16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  PWord(aData)^ := aPixel.Data.r;
+  inc(aData, 2);
+  PWord(aData)^ := aPixel.Data.g;
+  inc(aData, 2);
+  PWord(aData)^ := aPixel.Data.b;
+  inc(aData, 2);
 end;
 
-
-procedure UnMapLuminanceAlpha(var pData: pByte; var Pixel: TglBitmapPixelData);
+procedure TfdRGB16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  Pixel.Red   := pData^;
-  Pixel.Green := pData^;
-  Pixel.Blue  := pData^;
-  Inc(pData);
-
-  Pixel.Alpha := pData^;
-  Inc(pData);
+  aPixel.Data.r := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.g := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.b := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.a := 0;
 end;
 
-
-procedure UnMapRGBA4(var pData: pByte; var Pixel: TglBitmapPixelData);
-var
-  Temp: Word;
+constructor TfdRGB16.Create;
 begin
-  Temp := pWord(pData)^;
-
-  Pixel.Alpha := Temp shr PIXEL_DESC_RGBA4.AlphaShift and PIXEL_DESC_RGBA4.AlphaRange;
-  Pixel.Red   := Temp shr PIXEL_DESC_RGBA4.RedShift   and PIXEL_DESC_RGBA4.RedRange;
-  Pixel.Green := Temp shr PIXEL_DESC_RGBA4.GreenShift and PIXEL_DESC_RGBA4.GreenRange;
-  Pixel.Blue  := Temp                                 and PIXEL_DESC_RGBA4.BlueRange;
-
-  Inc(pData, 2);
+  inherited Create;
+  fPixelSize        := 6.0;
+  fFormat           := tfRGB16;
+  fWithAlpha        := tfRGBA16;
+  fWithoutAlpha     := tfRGB16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fShift.r          :=     0;
+  fShift.g          :=    16;
+  fShift.b          :=    32;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_RGB16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdRGBA2.Create;
+begin
+  inherited Create;
+  fFormat           := tfRGBA2;
+  fWithAlpha        := tfRGBA2;
+  fWithoutAlpha     := tfR3G3B2;
+  fRange.r          := $3;
+  fRange.g          := $3;
+  fRange.b          := $3;
+  fRange.a          := $3;
+  fShift.r          :=  0;
+  fShift.g          :=  2;
+  fShift.b          :=  4;
+  fShift.a          :=  6;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGBA2;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdRGBA4.Create;
+begin
+  inherited Create;
+  fFormat           := tfRGBA4;
+  fWithAlpha        := tfRGBA4;
+  fWithoutAlpha     := tfRGB4;
+  fRange.r          := $F;
+  fRange.g          := $F;
+  fRange.b          := $F;
+  fRange.a          := $F;
+  fShift.r          :=  0;
+  fShift.g          :=  4;
+  fShift.b          :=  8;
+  fShift.a          := 12;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGBA4;
+  fglDataFormat     := GL_UNSIGNED_SHORT_4_4_4_4_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdRGB5A1.Create;
+begin
+  inherited Create;
+  fFormat           := tfRGB5A1;
+  fWithAlpha        := tfRGB5A1;
+  fWithoutAlpha     := tfRGB5;
+  fRange.r          := $1F;
+  fRange.g          := $1F;
+  fRange.b          := $1F;
+  fRange.a          := $01;
+  fShift.r          :=   0;
+  fShift.g          :=   5;
+  fShift.b          :=  10;
+  fShift.a          :=  15;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGB5_A1;
+  fglDataFormat     := GL_UNSIGNED_SHORT_1_5_5_5_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  inherited Map(aPixel, aData, aMapData);
+  aData^ := aPixel.Data.a;
+  inc(aData);
 end;
 
-
-procedure UnMapR5G6B5(var pData: pByte; var Pixel: TglBitmapPixelData);
-var
-  Temp: Word;
+procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  Temp := pWord(pData)^;
-
-  Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
-  Pixel.Red   := Temp shr PIXEL_DESC_R5G6B5.RedShift   and PIXEL_DESC_R5G6B5.RedRange;
-  Pixel.Green := Temp shr PIXEL_DESC_R5G6B5.GreenShift and PIXEL_DESC_R5G6B5.GreenRange;
-  Pixel.Blue  := Temp                                  and PIXEL_DESC_R5G6B5.BlueRange;
-
-  Inc(pData, 2);
+  inherited Unmap(aData, aPixel, aMapData);
+  aPixel.Data.a := aData^;
+  inc(aData);
 end;
 
-
-procedure UnMapRGB5A1(var pData: pByte; var Pixel: TglBitmapPixelData);
-var
-  Temp: Word;
+constructor TfdRGBA8.Create;
 begin
-  Temp := pWord(pData)^;
-
-  Pixel.Alpha := Temp shr PIXEL_DESC_RGB5A1.AlphaShift and PIXEL_DESC_RGB5A1.AlphaRange;
-  Pixel.Red   := Temp shr PIXEL_DESC_RGB5A1.RedShift   and PIXEL_DESC_RGB5A1.RedRange;
-  Pixel.Green := Temp shr PIXEL_DESC_RGB5A1.GreenShift and PIXEL_DESC_RGB5A1.GreenRange;
-  Pixel.Blue  := Temp                                  and PIXEL_DESC_RGB5A1.BlueRange;
-
-  Inc(pData, 2);
+  inherited Create;
+  fPixelSize        := 4.0;
+  fFormat           := tfRGBA8;
+  fWithAlpha        := tfRGBA8;
+  fWithoutAlpha     := tfRGB8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fRange.a          := $FF;
+  fShift.r          :=   0;
+  fShift.g          :=   8;
+  fShift.b          :=  16;
+  fShift.a          :=  24;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGBA8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdRGB10A2.Create;
+begin
+  inherited Create;
+  fFormat           := tfRGB10A2;
+  fWithAlpha        := tfRGB10A2;
+  fWithoutAlpha     := tfRGB10;
+  fRange.r          := $3FF;
+  fRange.g          := $3FF;
+  fRange.b          := $3FF;
+  fRange.a          := $003;
+  fShift.r          :=    0;
+  fShift.g          :=   10;
+  fShift.b          :=   20;
+  fShift.a          :=   30;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGB10_A2;
+  fglDataFormat     := GL_UNSIGNED_INT_2_10_10_10_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdRGBA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  inherited Map(aPixel, aData, aMapData);
+  PWord(aData)^ := aPixel.Data.a;
+  inc(aData, 2);
 end;
 
-
-procedure UnMapRGB8(var pData: pByte; var Pixel: TglBitmapPixelData);
+procedure TfdRGBA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
-
-  Pixel.Red   := pData^;
-  Inc(pData);
-
-  Pixel.Green := pData^;
-  Inc(pData);
-
-  Pixel.Blue  := pData^;
-  Inc(pData);
+  inherited Unmap(aData, aPixel, aMapData);
+  aPixel.Data.a := PWord(aData)^;
+  inc(aData, 2);
 end;
 
-
-procedure UnMapBGR8(var pData: pByte; var Pixel: TglBitmapPixelData);
+constructor TfdRGBA16.Create;
 begin
-  Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
-
-  Pixel.Blue  := pData^;
-  Inc(pData);
-
-  Pixel.Green := pData^;
-  Inc(pData);
-
-  Pixel.Red   := pData^;
-  Inc(pData);
+  inherited Create;
+  fPixelSize        := 8.0;
+  fFormat           := tfRGBA16;
+  fWithAlpha        := tfRGBA16;
+  fWithoutAlpha     := tfRGB16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fRange.a          := $FFFF;
+  fShift.r          :=     0;
+  fShift.g          :=    16;
+  fShift.b          :=    32;
+  fShift.a          :=    48;
+  fglFormat         := GL_RGBA;
+  fglInternalFormat := GL_RGBA16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGR4.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfBGR4;
+  fWithAlpha        := tfBGRA4;
+  fWithoutAlpha     := tfBGR4;
+  fRange.r          := $F;
+  fRange.g          := $F;
+  fRange.b          := $F;
+  fRange.a          := $0;
+  fShift.r          :=  8;
+  fShift.g          :=  4;
+  fShift.b          :=  0;
+  fShift.a          :=  0;
+  fglFormat         := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
+  fglInternalFormat := GL_RGB4;
+  fglDataFormat     := GL_UNSIGNED_SHORT_4_4_4_4_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdB5G6R5.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfB5G6R5;
+  fWithAlpha        := tfBGRA4;
+  fWithoutAlpha     := tfB5G6R5;
+  fRange.r          := $1F;
+  fRange.g          := $3F;
+  fRange.b          := $1F;
+  fShift.r          :=  11;
+  fShift.g          :=   5;
+  fShift.b          :=   0;
+  fglFormat         := GL_RGB;
+  fglInternalFormat := GL_RGB8;
+  fglDataFormat     := GL_UNSIGNED_SHORT_5_6_5;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGR5.Create;
+begin
+  inherited Create;
+  fPixelSize        := 2.0;
+  fFormat           := tfBGR5;
+  fWithAlpha        := tfBGR5A1;
+  fWithoutAlpha     := tfBGR5;
+  fRange.r          := $1F;
+  fRange.g          := $1F;
+  fRange.b          := $1F;
+  fRange.a          := $00;
+  fShift.r          :=  10;
+  fShift.g          :=   5;
+  fShift.b          :=   0;
+  fShift.a          :=   0;
+  fglFormat         := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA
+  fglInternalFormat := GL_RGB5;
+  fglDataFormat     := GL_UNSIGNED_SHORT_1_5_5_5_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  aData^ := aPixel.Data.b;
+  inc(aData);
+  aData^ := aPixel.Data.g;
+  inc(aData);
+  aData^ := aPixel.Data.r;
+  inc(aData);
 end;
 
-
-procedure UnMapRGBA8(var pData: pByte; var Pixel: TglBitmapPixelData);
+procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
 begin
-  Pixel.Red   := pData^;
-  Inc(pData);
-
-  Pixel.Green := pData^;
-  Inc(pData);
-
-  Pixel.Blue  := pData^;
-  Inc(pData);
-
-  Pixel.Alpha := pData^;
-  Inc(pData);
+  aPixel.Data.b := aData^;
+  inc(aData);
+  aPixel.Data.g := aData^;
+  inc(aData);
+  aPixel.Data.r := aData^;
+  inc(aData);
+  aPixel.Data.a := 0;
 end;
 
-
-procedure UnMapBGRA8(var pData: pByte; var Pixel: TglBitmapPixelData);
+constructor TfdBGR8.Create;
+begin
+  inherited Create;
+  fPixelSize        := 3.0;
+  fFormat           := tfBGR8;
+  fWithAlpha        := tfBGRA8;
+  fWithoutAlpha     := tfBGR8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fRange.a          := $00;
+  fShift.r          :=  16;
+  fShift.g          :=   8;
+  fShift.b          :=   0;
+  fShift.a          :=   0;
+  fglFormat         := GL_BGR;
+  fglInternalFormat := GL_RGB8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGR10.Create;
 begin
-  Pixel.Blue  := pData^;
-  Inc(pData);
+  inherited Create;
+  fFormat           := tfBGR10;
+  fWithAlpha        := tfBGR10A2;
+  fWithoutAlpha     := tfBGR10;
+  fRange.r          := $3FF;
+  fRange.g          := $3FF;
+  fRange.b          := $3FF;
+  fRange.a          := $000;
+  fShift.r          :=   20;
+  fShift.g          :=   10;
+  fShift.b          :=    0;
+  fShift.a          :=    0;
+  fglFormat         := GL_BGR;
+  fglInternalFormat := GL_RGB10;
+  fglDataFormat     := GL_UNSIGNED_INT_2_10_10_10_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdBGR16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  PWord(aData)^ := aPixel.Data.b;
+  inc(aData, 2);
+  PWord(aData)^ := aPixel.Data.g;
+  inc(aData, 2);
+  PWord(aData)^ := aPixel.Data.r;
+  inc(aData, 2);
+end;
 
-  Pixel.Green := pData^;
-  Inc(pData);
+procedure TfdBGR16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  aPixel.Data.b := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.g := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.r := PWord(aData)^;
+  inc(aData, 2);
+  aPixel.Data.a := 0;
+end;
 
-  Pixel.Red   := pData^;
-  Inc(pData);
+constructor TfdBGR16.Create;
+begin
+  inherited Create;
+  fPixelSize        := 6.0;
+  fFormat           := tfBGR16;
+  fWithAlpha        := tfBGRA16;
+  fWithoutAlpha     := tfBGR16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fRange.a          := $0000;
+  fShift.r          :=    32;
+  fShift.g          :=    16;
+  fShift.b          :=     0;
+  fShift.a          :=     0;
+  fglFormat         := GL_BGR;
+  fglInternalFormat := GL_RGB16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGRA2.Create;
+begin
+  inherited Create;
+  fFormat           := tfBGRA2;
+  fWithAlpha        := tfBGRA4;
+  fWithoutAlpha     := tfBGR4;
+  fRange.r          := $3;
+  fRange.g          := $3;
+  fRange.b          := $3;
+  fRange.a          := $3;
+  fShift.r          :=  4;
+  fShift.g          :=  2;
+  fShift.b          :=  0;
+  fShift.a          :=  6;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGBA2;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGRA4.Create;
+begin
+  inherited Create;
+  fFormat           := tfBGRA4;
+  fWithAlpha        := tfBGRA4;
+  fWithoutAlpha     := tfBGR4;
+  fRange.r          := $F;
+  fRange.g          := $F;
+  fRange.b          := $F;
+  fRange.a          := $F;
+  fShift.r          :=  8;
+  fShift.g          :=  4;
+  fShift.b          :=  0;
+  fShift.a          := 12;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGBA4;
+  fglDataFormat     := GL_UNSIGNED_SHORT_4_4_4_4_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGR5A1.Create;
+begin
+  inherited Create;
+  fFormat           := tfBGR5A1;
+  fWithAlpha        := tfBGR5A1;
+  fWithoutAlpha     := tfBGR5;
+  fRange.r          := $1F;
+  fRange.g          := $1F;
+  fRange.b          := $1F;
+  fRange.a          := $01;
+  fShift.r          :=  10;
+  fShift.g          :=   5;
+  fShift.b          :=   0;
+  fShift.a          :=  15;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGB5_A1;
+  fglDataFormat     := GL_UNSIGNED_SHORT_1_5_5_5_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////s
+procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  inherited Map(aPixel, aData, aMapData);
+  aData^ := aPixel.Data.a;
+  inc(aData);
+end;
 
-  Pixel.Alpha := pData^;
-  Inc(pData);
+procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  inherited Unmap(aData, aPixel, aMapData);
+  aPixel.Data.a := aData^;
+  inc(aData);
 end;
 
+constructor TfdBGRA8.Create;
+begin
+  inherited Create;
+  fPixelSize        := 4.0;
+  fFormat           := tfBGRA8;
+  fWithAlpha        := tfBGRA8;
+  fWithoutAlpha     := tfBGR8;
+  fRange.r          := $FF;
+  fRange.g          := $FF;
+  fRange.b          := $FF;
+  fRange.a          := $FF;
+  fShift.r          :=  16;
+  fShift.g          :=   8;
+  fShift.b          :=   0;
+  fShift.a          :=  24;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGBA8;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TfdBGR10A2.Create;
+begin
+  inherited Create;
+  fFormat           := tfBGR10A2;
+  fWithAlpha        := tfBGR10A2;
+  fWithoutAlpha     := tfBGR10;
+  fRange.r          := $3FF;
+  fRange.g          := $3FF;
+  fRange.b          := $3FF;
+  fRange.a          := $003;
+  fShift.r          :=   20;
+  fShift.g          :=   10;
+  fShift.b          :=    0;
+  fShift.a          :=   30;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGB10_A2;
+  fglDataFormat     := GL_UNSIGNED_INT_2_10_10_10_REV;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdBGRA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  inherited Map(aPixel, aData, aMapData);
+  PWord(aData)^ := aPixel.Data.a;
+  inc(aData, 2);
+end;
 
-procedure UnMapRGB10A2(var pData: pByte; var Pixel: TglBitmapPixelData);
-var
-  Temp: DWord;
-begin
-  Temp := pDWord(pData)^;
-
-  Pixel.Alpha := Temp shr PIXEL_DESC_RGB10A2.AlphaShift and PIXEL_DESC_RGB10A2.AlphaRange;
-  Pixel.Red   := Temp shr PIXEL_DESC_RGB10A2.RedShift   and PIXEL_DESC_RGB10A2.RedRange;
-  Pixel.Green := Temp shr PIXEL_DESC_RGB10A2.GreenShift and PIXEL_DESC_RGB10A2.GreenRange;
-  Pixel.Blue  := Temp                                   and PIXEL_DESC_RGB10A2.BlueRange;
-
-  Inc(pData, 4);
-end;
-
-
-function FormatGetUnMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapUnMapFunc;
-begin
-  case aInternalFormat of
-    ifAlpha4:  result := UnmapAlpha4;
-    ifAlpha8:  result := UnmapAlpha8;
-    ifAlpha12: result := UnmapAlpha12;
-    ifAlpha16: result := UnmapAlpha16;
-
-    ifLuminance4:  result := UnmapLuminance4;
-    ifLuminance8:  result := UnmapLuminance8;
-    ifLuminance12: result := UnmapLuminance8;
-    ifLuminance16: result := UnmapLuminance8;
-
-    ifLuminance4Alpha4:   result := UnmapLuminance4Alpha4;
-    ifLuminance6Alpha2:   result := UnmapLuminance6Alpha2;
-    ifLuminance8Alpha8:   result := UnmapLuminance8Alpha8;
-    ifLuminance12Alpha4:  result := UnmapLuminance12Alpha4;
-    ifLuminance12Alpha12: result := UnmapLuminance12Alpha12;
-    ifLuminance16Alpha16: result := UnmapLuminance16Alpha16;
-
-    ifR3G3B2: result := UnmapR3G3B2;
-    ifRGB4:   result := UnmapRGB4;
-    ifRGB5:   result := UnmapRGB5;
-    ifRGB8:   result := UnmapRGB8;
-    ifRGB10:  result := UnmapRGB10;
-    ifRGB12:  result := UnmapRGB12;
-    ifRGB16:  result := UnmapRGB16;
-
-    ifRGBA2:   result := UnmapRGBA2;
-    ifRGBA4:   result := UnmapRGBA4;
-    ifRGB5A1:  result := UnmapRGB5A1;
-    ifRGBA8:   result := UnmapRGBA8;
-    ifRGB10A2: result := UnmapRGB10A2;
-    ifRGBA12:  result := UnmapRGBA12;
-    ifRGBA16:  result := UnmapRGBA16;
-
-    ifDepth16: result := UnmapDepth16;
-    ifDepth24: result := UnmapDepth24;
-    ifDepth32: result := UnmapDepth32;
-  else
-    raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
-  end;
+procedure TfdBGRA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  inherited Unmap(aData, aPixel, aMapData);
+  aPixel.Data.a := PWord(aData)^;
+  inc(aData, 2);
 end;
-{$ENDREGION}
 
-{*
-** Tools
-*}
-function FormatGetSize (Format: TglBitmapInternalFormat): Single;
+constructor TfdBGRA16.Create;
 begin
-  case Format of
-    ifEmpty:
-      Result := 0;
-    ifDXT1:
-      Result := 0.5;
-    ifAlpha, ifLuminance, ifDepth8, ifDXT3, ifDXT5:
-      Result := 1;
-    ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5:
-      Result := 2;
-    ifBGR8, ifRGB8:
-      Result := 3;
-    ifBGRA8, ifRGBA8, ifRGB10A2:
-      Result := 4;
-    else
-      raise EglBitmapUnsupportedInternalFormat.Create('FormatGetSize - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  inherited Create;
+  fPixelSize        := 8.0;
+  fFormat           := tfBGRA16;
+  fWithAlpha        := tfBGRA16;
+  fWithoutAlpha     := tfBGR16;
+  fRange.r          := $FFFF;
+  fRange.g          := $FFFF;
+  fRange.b          := $FFFF;
+  fRange.a          := $FFFF;
+  fShift.r          :=    32;
+  fShift.g          :=    16;
+  fShift.b          :=     0;
+  fShift.a          :=    48;
+  fglFormat         := GL_BGRA;
+  fglInternalFormat := GL_RGBA16;
+  fglDataFormat     := GL_UNSIGNED_SHORT;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class procedure TFormatDescriptor.Init;
+begin
+  if not Assigned(FormatDescriptorCS) then
+    FormatDescriptorCS := TCriticalSection.Create;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
+begin
+  FormatDescriptorCS.Enter;
+  try
+    result := FormatDescriptors[aFormat];
+    if not Assigned(result) then begin
+      result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create;
+      FormatDescriptors[aFormat] := result;
+    end;
+  finally
+    FormatDescriptorCS.Leave;
   end;
 end;
 
-
-function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
 begin
-  Result := Format in [ifDXT1, ifDXT3, ifDXT5];
+  result := Get(Get(aFormat).WithAlpha);
 end;
 
-
-function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class procedure TFormatDescriptor.Clear;
+var
+  f: TglBitmapFormat;
 begin
-  Result := Format in [ifAlpha, ifLuminance, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8, ifRGB10A2];
+  FormatDescriptorCS.Enter;
+  try
+    for f := low(FormatDescriptors) to high(FormatDescriptors) do
+      FreeAndNil(FormatDescriptors[f]);
+  finally
+    FormatDescriptorCS.Leave;
+  end;
 end;
 
-
-function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class procedure TFormatDescriptor.Finalize;
 begin
-  Result := Format = ifEmpty;
+  Clear;
+  FreeAndNil(FormatDescriptorCS);
 end;
 
-
-function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TBitfieldFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.SetRedMask(const aValue: UInt64);
 begin
-  Result := Format in [ifDXT1, ifDXT3, ifDXT5 ,ifAlpha, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifBGRA8, ifRGBA8, ifRGB10A2];
+  Update(aValue, fRange.r, fShift.r);
 end;
 
-
-procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.SetGreenMask(const aValue: UInt64);
 begin
-  FillChar(Pixel, SizeOf(Pixel), #0);
+  Update(aValue, fRange.g, fShift.g);
+end;
 
-  case Format of
-    ifAlpha:
-      Pixel.PixelDesc := PIXEL_DESC_ALPHA;
-    ifLuminance:
-      Pixel.PixelDesc := PIXEL_DESC_LUMINANCE;
-    ifDepth8:
-      Pixel.PixelDesc := PIXEL_DESC_DEPTH8;
-    ifLuminanceAlpha:
-      Pixel.PixelDesc := PIXEL_DESC_LUMINANCEALPHA;
-    ifRGBA4:
-      Pixel.PixelDesc := PIXEL_DESC_RGBA4;
-    ifR5G6B5:
-      Pixel.PixelDesc := PIXEL_DESC_R5G6B5;
-    ifRGB5A1:
-      Pixel.PixelDesc := PIXEL_DESC_RGB5A1;
-    ifDXT1, ifDXT3, ifDXT5, ifBGRA8:
-      Pixel.PixelDesc := PIXEL_DESC_BGRA8;
-    ifBGR8:
-      Pixel.PixelDesc := PIXEL_DESC_BGR8;
-    ifRGB8:
-      Pixel.PixelDesc := PIXEL_DESC_RGB8;
-    ifRGBA8:
-      Pixel.PixelDesc := PIXEL_DESC_RGBA8;
-    ifRGB10A2:
-      Pixel.PixelDesc := PIXEL_DESC_RGB10A2;
-  end;
-
-  Pixel.Red   := Pixel.PixelDesc.RedRange;
-  Pixel.Green := Pixel.PixelDesc.GreenRange;
-  Pixel.Blue  := Pixel.PixelDesc.BlueRange;
-  Pixel.Alpha := Pixel.PixelDesc.AlphaRange;
-end;
-
-
-function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.SetBlueMask(const aValue: UInt64);
 begin
-  case Format of
-    ifAlpha:
-      Result := ifLuminance;
-    ifLuminanceAlpha:
-      Result := ifLuminance;
-    ifRGBA4:
-      Result := ifR5G6B5;
-    ifRGB5A1:
-      Result := ifR5G6B5;
-    ifBGRA8:
-      Result := ifBGR8;
-    ifRGBA8:
-      Result := ifRGB8;
-    ifRGB10A2:
-      Result := ifRGB8;
-    else
-      Result := Format;
-  end;
+  Update(aValue, fRange.b, fShift.b);
 end;
 
-
-function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.SetAlphaMask(const aValue: UInt64);
 begin
-  case Format of
-    ifLuminance:
-      Result := ifLuminanceAlpha;
-    ifR5G6B5:
-      Result := ifRGB5A1;
-    ifBGR8:
-      Result := ifBGRA8;
-    ifRGB8:
-      Result := ifRGBA8;
-    else
-      Result := Format;
-  end;
+  Update(aValue, fRange.a, fShift.a);
 end;
 
-
-function FormatGetUncompressed(Format: TglBitmapInternalFormat): TglBitmapInternalFormat;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out
+  aShift: Byte);
 begin
-  case Format of
-    ifDXT1:
-      Result := ifRGB5A1;
-    ifDXT3:
-      Result := ifRGBA8;
-    ifDXT5:
-      Result := ifRGBA8;
-    else
-      Result := Format;
+  aShift := 0;
+  aRange := 0;
+  if (aMask = 0) then
+    exit;
+  while (aMask > 0) and ((aMask and 1) = 0) do begin
+    inc(aShift);
+    aMask := aMask shr 1;
   end;
-end;
+  aRange := 1;
+  while (aMask > 0) do begin
+    aRange := aRange shl 1;
+    aMask  := aMask  shr 1;
+  end;
+  dec(aRange);
 
+  fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8);
+end;
 
-function FormatGetImageSize(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat): Integer;
-begin
-  if (Size.X = 0) and (Size.Y = 0) then
-    Result := 0
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+var
+  data: UInt64;
+  s: Integer;
+type
+  PUInt64 = ^UInt64;
+begin
+  data :=
+    ((aPixel.Data.r and fRange.r) shl fShift.r) or
+    ((aPixel.Data.g and fRange.g) shl fShift.g) or
+    ((aPixel.Data.b and fRange.b) shl fShift.b) or
+    ((aPixel.Data.a and fRange.a) shl fShift.a);
+  s := Round(fPixelSize);
+  case s of
+    1:           aData^  := data;
+    2:     PWord(aData)^ := data;
+    4: PCardinal(aData)^ := data;
+    8:   PUInt64(aData)^ := data;
   else
-    Result := Trunc(Max(Size.Y, 1) * Max(Size.X, 1) * FormatGetSize(Format));
+    raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
+  end;
+  inc(aData, s);
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+var
+  data: UInt64;
+  s, i: Integer;
+type
+  PUInt64 = ^UInt64;
+begin
+  s := Round(fPixelSize);
+  case s of
+    1: data :=           aData^;
+    2: data :=     PWord(aData)^;
+    4: data := PCardinal(aData)^;
+    8: data :=   PUInt64(aData)^;
+  else
+    raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]);
+  end;
+  for i := 0 to 3 do
+    aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i];
+  inc(aData, s);
+end;
 
-function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFileTypes;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TColorTableFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
 begin
-  Result := [];
-
-  {$IFDEF GLB_SUPPORT_PNG_WRITE}
-  if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then
-    Result := Result + [ftPNG];
-  {$ENDIF}
-
-  {$IFDEF GLB_SUPPORT_JPEG_WRITE}
-  if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then
-    Result := Result + [ftJPEG];
-  {$ENDIF}
-
-  Result := Result + [ftDDS];
+  raise EglBitmapException.Create('mapping of color table formats is not supported');
+end;
 
-  if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8] then
-    Result := Result + [ftTGA];
+procedure TColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+type
+  PUInt64 = ^UInt64;
+var
+  idx: UInt64;
+  s: Integer;
+  bits: Byte;
+  f: Single;
+begin
+  s    := Trunc(fPixelSize);
+  f    := fPixelSize - s;
+  bits := Round(8 * f);
+  case s of
+    0: idx :=          (aData^ shr (8 - bits - PtrInt(aMapData))) and ((1 shl bits) - 1);
+    1: idx :=           aData^;
+    2: idx :=     PWord(aData)^;
+    4: idx := PCardinal(aData)^;
+    8: idx :=   PUInt64(aData)^;
+  else
+    raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]);
+  end;
+  if (idx >= Length(fColorTable)) then
+    raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]);
+  with fColorTable[idx] do begin
+    aPixel.Data.r := r;
+    aPixel.Data.g := g;
+    aPixel.Data.b := b;
+    aPixel.Data.a := a;
+  end;
+  inc(aMapData, bits);
+  if (PtrInt(aMapData) >= 8) then begin
+    inc(aData, 1);
+    dec(aMapData, 8);
+  end;
+  inc(aData, s);
+end;
 
-  if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifRGB8, ifBGR8, ifRGBA8, ifBGRA8, ifRGB10A2] then
-    Result := Result + [ftBMP];
+destructor TColorTableFormat.Destroy;
+begin
+  SetLength(fColorTable, 0);
+  inherited Destroy;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmap - Helper//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec);
+begin
+  with aFuncRec do begin
+    if (Source.Range.r   > 0) then
+      Dest.Data.r := Source.Data.r;
+    if (Source.Range.g > 0) then
+      Dest.Data.g := Source.Data.g;
+    if (Source.Range.b  > 0) then
+      Dest.Data.b := Source.Data.b;
+    if (Source.Range.a > 0) then
+      Dest.Data.a := Source.Data.a;
+  end;
+end;
 
-function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
 var
-  Pix: TglBitmapPixelData;
+  i: Integer;
 begin
-  Result := False;
-
-  if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) and (AlphaMask = 0) then
-    raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0');
-
-  FormatPreparePixel(Pix, Format);
-
-  with Pix.PixelDesc do begin
-    if RedMask <> 0 then
-      if (RedMask <> (RedRange shl RedShift)) then
-        Exit;
-
-    if GreenMask <> 0 then
-      if (GreenMask <> (GreenRange shl GreenShift)) then
-        Exit;
-
-    if BlueMask <> 0 then
-      if (BlueMask <> (BlueRange shl BlueShift)) then
-        Exit;
+  with aFuncRec do begin
+    for i := 0 to 3 do
+      if (Source.Range.arr[i] > 0) then
+        Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]);
+  end;
+end;
 
-    if AlphaMask <> 0 then
-      if (AlphaMask <> (AlphaRange shl AlphaShift)) then
-        Exit;
+type
+  TShiftData = packed record
+    case Integer of
+      0: (r, g, b, a: SmallInt);
+      1: (arr: array[0..3] of SmallInt);
+  end;
+  PShiftData = ^TShiftData;
 
-    Result := True;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec);
+var
+  i: Integer;
+begin
+  with aFuncRec do
+    for i := 0 to 3 do
+      if (Source.Range.arr[i] > 0) then
+        Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i];
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec);
+begin
+  with aFuncRec do begin
+    Dest.Data.r := Source.Data.r;
+    Dest.Data.g := Source.Data.g;
+    Dest.Data.b := Source.Data.b;
+    Dest.Data.a := Source.Data.a;
+    if (Args and $1 > 0) then begin
+      Dest.Data.r := Dest.Data.r xor Dest.Range.r;
+      Dest.Data.g := Dest.Data.g xor Dest.Range.g;
+      Dest.Data.b := Dest.Data.b xor Dest.Range.b;
+    end;
+    if (Args and $2 > 0) then begin
+      Dest.Data.a := Dest.Data.a xor Dest.Range.a;
+    end;
   end;
 end;
 
-
-function IsPowerOfTwo(Number: Integer): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec);
+var
+  i: Integer;
 begin
-  while Number and 1 = 0 do
-    Number := Number shr 1;
-
-  Result := Number = 1;
+  with aFuncRec do begin
+    for i := 0 to 3 do
+      Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i];
+  end;
 end;
 
-
-function GetBitSize(BitSet: Cardinal): Integer;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
+var
+  Temp: Single;
 begin
-  Result := 0;
-
-  while BitSet > 0 do begin
-    if (BitSet and $1) = 1 then
-      Inc(Result);
+  with FuncRec do begin
+    if (FuncRec.Args = 0) then begin //source has no alpha
+      Temp :=
+        Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R +
+        Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G +
+        Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B;
+      Dest.Data.a := Round(Dest.Range.a * Temp);
+    end else
+      Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a);
+  end;
+end;
 
-    BitSet := BitSet shr 1;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
+type
+  PglBitmapPixelData = ^TglBitmapPixelData;
+begin
+  with FuncRec do begin
+    Dest.Data.r := Source.Data.r;
+    Dest.Data.g := Source.Data.g;
+    Dest.Data.b := Source.Data.b;
+
+    with PglBitmapPixelData(Args)^ do
+      if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and
+          (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and
+          (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then
+        Dest.Data.a := 0
+      else
+        Dest.Data.a := Dest.Range.a;
   end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
+type
+  PglBitmapPixelData = ^TglBitmapPixelData;
+begin
+  with FuncRec do begin
+    Dest.Data.r := Source.Data.r;
+    Dest.Data.g := Source.Data.g;
+    Dest.Data.b := Source.Data.b;
+    Dest.Data.a := PCardinal(Args)^;
+  end;
+end;
 
-procedure SwapRGB(pData: pByte; Width: Integer; HasAlpha: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean);
 type
   PRGBPix = ^TRGBPix;
   TRGBPix = array [0..2] of byte;
 var
   Temp: Byte;
 begin
-  while Width > 0 do begin
-    Temp := pRGBPIX(pData)^[0];
-    pRGBPIX(pData)^[0] := pRGBPIX(pData)^[2];
-    pRGBPIX(pData)^[2] := Temp;
+  while aWidth > 0 do begin
+    Temp := PRGBPix(aData)^[0];
+    PRGBPix(aData)^[0] := PRGBPix(aData)^[2];
+    PRGBPix(aData)^[2] := Temp;
 
-    if HasAlpha then
-      Inc(pData, 4)
+    if aHasAlpha then
+      Inc(aData, 4)
     else
-      Inc(pData, 3);
-
-    Dec(Width);
+      Inc(aData, 3);
+    dec(aWidth);
   end;
 end;
 
-
-{$IFDEF GLB_DELPHI}
-function CreateGrayPalette: HPALETTE;
-var
-  Idx: Integer;
-  Pal: PLogPalette;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmap - PROTECTED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.GetWidth: Integer;
 begin
-  GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256));
-
-  Pal.palVersion := $300;
-  Pal.palNumEntries := 256;
-
-  {$IFOPT R+}
-    {$DEFINE GLB_TEMPRANGECHECK}
-    {$R-}
-  {$ENDIF}
-
-  for Idx := 0 to 256 - 1 do begin
-    Pal.palPalEntry[Idx].peRed   := Idx;
-    Pal.palPalEntry[Idx].peGreen := Idx;
-    Pal.palPalEntry[Idx].peBlue  := Idx;
-    Pal.palPalEntry[Idx].peFlags := 0;
-  end;
-
-  {$IFDEF GLB_TEMPRANGECHECK}
-    {$UNDEF GLB_TEMPRANGECHECK}
-    {$R+}
-  {$ENDIF}
-
-  Result := CreatePalette(Pal^);
-
-  FreeMem(Pal);
+  if (ffX in fDimension.Fields) then
+    result := fDimension.X
+  else
+    result := -1;
 end;
-{$ENDIF}
 
-
-{$IFDEF GLB_SDL_IMAGE}
-function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.GetHeight: Integer;
 begin
-  Result := TStream(context^.unknown.data1).Seek(offset, whence);
+  if (ffY in fDimension.Fields) then
+    result := fDimension.Y
+  else
+    result := -1;
 end;
 
-
-function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.GetFileWidth: Integer;
 begin
-  Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum);
+  result := Max(1, Width);
 end;
 
-
-function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.GetFileHeight: Integer;
 begin
-  Result := TStream(context^.unknown.data1).Write(Ptr^, size * num);
+  result := Max(1, Height);
 end;
 
-
-function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetCustomData(const aValue: Pointer);
 begin
-  Result := 0;
+  if fCustomData = aValue then
+    exit;
+  fCustomData := aValue;
 end;
 
-
-function glBitmapCreateRWops(Stream: TStream): PSDL_RWops;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetCustomName(const aValue: String);
 begin
-  Result := SDL_AllocRW;
-
-  if Result = nil then
-    raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.');
-
-  Result^.seek := glBitmapRWseek;
-  Result^.read := glBitmapRWread;
-  Result^.write := glBitmapRWwrite;
-  Result^.close := glBitmapRWclose;
-  Result^.unknown.data1 := Stream;
+  if fCustomName = aValue then
+    exit;
+  fCustomName := aValue;
 end;
-{$ENDIF}
-
 
-{*
-** Helper functions
-*}
-function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
-var
-  glBitmap: TglBitmap2D;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetCustomNameW(const aValue: WideString);
 begin
-  Result := false;
-  Texture := 0;
-
-  {$IFDEF GLB_DELPHI}
-  if Instance = 0 then
-    Instance := HInstance;
-
-  if (LoadFromRes) then
-    glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName)
-  else
-  {$ENDIF}
-    glBitmap := TglBitmap2D.Create(FileName);
-
-  try
-    glBitmap.DeleteTextureOnFree := False;
-    glBitmap.FreeDataAfterGenTexture := False;
-    glBitmap.GenTexture(True);
-    if (glBitmap.ID > 0) then begin
-      Texture := glBitmap.ID;
-      Result := True;
-    end;
-  finally
-    glBitmap.Free;
-  end;
+  if fCustomNameW = aValue then
+    exit;
+  fCustomNameW := aValue;
 end;
 
-
-function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean;
-var
-  CM: TglBitmapCubeMap;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
 begin
-  Texture := 0;
-
-  {$IFDEF GLB_DELPHI}
-  if Instance = 0 then
-    Instance := HInstance;
-  {$ENDIF}
-
-  CM := TglBitmapCubeMap.Create;
-  try
-    CM.DeleteTextureOnFree := False;
-
-    // Maps
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, PositiveX)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(PositiveX);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
-
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, NegativeX)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(NegativeX);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
-
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, PositiveY)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(PositiveY);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
-
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, NegativeY)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(NegativeY);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
-
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, PositiveZ)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(PositiveZ);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
-
-    {$IFDEF GLB_DELPHI}
-    if (LoadFromRes) then
-      CM.LoadFromResource(Instance, NegativeZ)
-    else
-    {$ENDIF}
-      CM.LoadFromFile(NegativeZ);
-    CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
-
-    Texture := CM.ID;
-    Result := True;
-  finally
-    CM.Free;
-  end;
+  if fDeleteTextureOnFree = aValue then
+    exit;
+  fDeleteTextureOnFree := aValue;
 end;
 
-
-function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean;
-var
-  NM: TglBitmapNormalMap;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
 begin
-  Texture := 0;
-
-  NM := TglBitmapNormalMap.Create;
-  try
-    NM.DeleteTextureOnFree := False;
-    NM.GenerateNormalMap(Size);
-
-    Texture := NM.ID;
-    Result := True;
-  finally
-    NM.Free;
-  end;
+  if fFormat = aValue then
+    exit;
+  if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then
+    raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT);
+  SetDataPointer(Data, aValue, Width, Height);
 end;
 
-
-procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
 begin
-  glBitmapDefaultFormat := Format;
+  if fFreeDataAfterGenTexture = aValue then
+    exit;
+  fFreeDataAfterGenTexture := aValue;
 end;
 
-
-procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetID(const aValue: Cardinal);
 begin
-  glBitmapDefaultDeleteTextureOnFree := DeleteTextureOnFree;
+  if fID = aValue then
+    exit;
+  fID := aValue;
 end;
 
-
-procedure glBitmapSetDefaultFilter(Min, Mag: Integer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
 begin
-  glBitmapDefaultFilterMin := Min;
-  glBitmapDefaultFilterMag := Mag;
+  if fMipMap = aValue then
+    exit;
+  fMipMap := aValue;
 end;
 
-
-procedure glBitmapSetDefaultWrap(S: Integer; T: Integer; R: Integer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetTarget(const aValue: Cardinal);
 begin
-  glBitmapDefaultWrapS := S;
-  glBitmapDefaultWrapT := T;
-  glBitmapDefaultWrapR := R;
+  if fTarget = aValue then
+    exit;
+  fTarget := aValue;
 end;
 
-
-procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetAnisotropic(const aValue: Integer);
+var
+  MaxAnisotropic: Integer;
 begin
-  glBitmapDefaultFreeDataAfterGenTextures := FreeData;
+  fAnisotropic := aValue;
+  if (ID > 0) then begin
+    if GL_EXT_texture_filter_anisotropic then begin
+      if fAnisotropic > 0 then begin
+        Bind(false);
+        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic);
+        if aValue > MaxAnisotropic then
+          fAnisotropic := MaxAnisotropic;
+        glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
+      end;
+    end else begin
+      fAnisotropic := 0;
+    end;
+  end;
 end;
 
-
-function glBitmapGetDefaultFormat: TglBitmapFormat;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.CreateID;
 begin
-  Result := glBitmapDefaultFormat;
+  if (ID <> 0) then
+    glDeleteTextures(1, @fID);
+  glGenTextures(1, @fID);
+  Bind(false);
 end;
 
-
-function glBitmapGetDefaultDeleteTextureOnFree: Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean);
 begin
-  Result := glBitmapDefaultDeleteTextureOnFree;
-end;
+  // Set Up Parameters
+  SetWrap(fWrapS, fWrapT, fWrapR);
+  SetFilter(fFilterMin, fFilterMag);
+  SetAnisotropic(fAnisotropic);
+  SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
 
+  // Mip Maps Generation Mode
+  aBuildWithGlu := false;
+  if (MipMap = mmMipmap) then begin
+    if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
+      glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
+    else
+      aBuildWithGlu := true;
+  end else if (MipMap = mmMipmapGlu) then
+    aBuildWithGlu := true;
+end;
 
-procedure glBitmapGetDefaultFilter(var Min, Mag: Integer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
+  const aWidth: Integer; const aHeight: Integer);
+var
+  s: Single;
 begin
-  Min := glBitmapDefaultFilterMin;
-  Mag := glBitmapDefaultFilterMag;
-end;
+  if (Data <> aData) then begin
+    if (Assigned(Data)) then
+      FreeMem(Data);
+    fData := aData;
+  end;
 
+  FillChar(fDimension, SizeOf(fDimension), 0);
+  if not Assigned(fData) then begin
+    fFormat    := tfEmpty;
+    fPixelSize := 0;
+    fRowSize   := 0;
+  end else begin
+    if aWidth <> -1 then begin
+      fDimension.Fields := fDimension.Fields + [ffX];
+      fDimension.X := aWidth;
+    end;
 
-procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer);
-begin
-  S := glBitmapDefaultWrapS;
-  T := glBitmapDefaultWrapT;
-  R := glBitmapDefaultWrapR;
-end;
+    if aHeight <> -1 then begin
+      fDimension.Fields := fDimension.Fields + [ffY];
+      fDimension.Y := aHeight;
+    end;
 
+    s := TFormatDescriptor.Get(aFormat).PixelSize;
+    fFormat    := aFormat;
+    fPixelSize := Ceil(s);
+    fRowSize   := Ceil(s * aWidth);
+  end;
+end;
 
-function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.FlipHorz: Boolean;
 begin
-  Result := glBitmapDefaultFreeDataAfterGenTextures;
+  result := false;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.FlipVert: Boolean;
+begin
+  result := false;
+end;
 
-{ TglBitmap }
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmap - PUBLIC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.AfterConstruction;
 begin
-  inherited;
+  inherited AfterConstruction;
 
-  fID := 0;
-  fTarget := 0;
-  fMipMap := mmMipmap;
-  fIsResident := False;
+  fID         := 0;
+  fTarget     := 0;
+  fIsResident := false;
 
-  // get defaults
+  fFormat                  := glBitmapGetDefaultFormat;
+  fMipMap                  := glBitmapDefaultMipmap;
   fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
-  fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree;
-
-  fFormat := glBitmapGetDefaultFormat;
+  fDeleteTextureOnFree     := glBitmapGetDefaultDeleteTextureOnFree;
 
-  glBitmapGetDefaultFilter(fFilterMin, fFilterMag);
+  glBitmapGetDefaultFilter     (fFilterMin, fFilterMag);
   glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR);
 end;
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.BeforeDestruction;
 begin
-  SetDataPointer(nil, ifEmpty);
-
-  if ((ID > 0) and (fDeleteTextureOnFree)) then
-    glDeleteTextures(1, @ID);
-
-  inherited;
+  SetDataPointer(nil, tfEmpty);
+  if (fID > 0) and fDeleteTextureOnFree then
+    glDeleteTextures(1, @fID);
+  inherited BeforeDestruction;
 end;
 
-
-constructor TglBitmap.Create;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.LoadFromFile(const aFilename: String);
+var
+  fs: TFileStream;
 begin
-  {$IFNDEF GLB_NO_NATIVE_GL}
-    ReadOpenGLExtensions;
-  {$ENDIF}
-
-  if (ClassType = TglBitmap) then
-    raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
-
-  inherited Create;
+  fFilename := aFilename;
+  fs := TFileStream.Create(fFilename, fmOpenRead);
+  try
+    fs.Position := 0;
+    LoadFromStream(fs);
+  finally
+    fs.Free;
+  end;
 end;
 
-
-constructor TglBitmap.Create(FileName: String);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.LoadFromStream(const aStream: TStream);
 begin
-  Create;
-  LoadFromFile(FileName);
+  {$IFDEF GLB_SUPPORT_PNG_READ}
+  if not LoadPNG(aStream) then
+  {$ENDIF}
+  {$IFDEF GLB_SUPPORT_JPEG_READ}
+  if not LoadJPEG(aStream) then
+  {$ENDIF}
+  if not LoadDDS(aStream) then
+  if not LoadTGA(aStream) then
+  if not LoadBMP(aStream) then
+    raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
 end;
 
-
-constructor TglBitmap.Create(Stream: TStream);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction;
+  const aFormat: TglBitmapFormat; const aArgs: PtrInt);
+var
+  tmpData: PByte;
+  size: Integer;
 begin
-  Create;
-  LoadFromStream(Stream);
+  size := TFormatDescriptor.Get(aFormat).GetSize(aSize);
+  GetMem(tmpData, size);
+  try
+    FillChar(tmpData^, size, #$FF);
+    SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y);
+  except
+    FreeMem(tmpData);
+    raise;
+  end;
+  AddFunc(Self, aFunc, false, Format, aArgs);
 end;
 
-
 {$IFDEF GLB_DELPHI}
-constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil);
+var
+  rs: TResourceStream;
+  TempPos: Integer;
+  ResTypeStr: String;
+  TempResType: PChar;
 begin
-  Create;
-  LoadFromResource(Instance, Resource, ResType);
-end;
-
+  if not Assigned(ResType) then begin
+    TempPos     := Pos('.', Resource);
+    ResTypeStr  := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
+    Resource    := UpperCase(Copy(Resource, 0, TempPos -1));
+    TempResType := PChar(ResTypeStr);
+  end else
+    TempResType := ResType
 
-constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar);
-begin
-  Create;
-  LoadFromResource(Instance, Resource, ResType);
+  rs := TResourceStream.Create(Instance, Resource, TempResType);
+  try
+    LoadFromStream(rs);
+  finally
+    rs.Free;
+  end;
 end;
 
-
-
-constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
+var
+  rs: TResourceStream;
 begin
-  Create;
-  LoadFromResourceID(Instance, ResourceID, ResType);
+  rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
+  try
+    LoadFromStream(rs);
+  finally
+    rs.Free;
+  end;
 end;
 {$ENDIF}
 
-
-constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
-  Format: TglBitmapInternalFormat);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType);
 var
-  Image: pByte;
-  ImageSize: Integer;
+  fs: TFileStream;
 begin
-  Create;
-
-  ImageSize := FormatGetImageSize(Size, Format);
-  GetMem(Image, ImageSize);
+  fs := TFileStream.Create(aFileName, fmCreate);
   try
-    FillChar(Image^, ImageSize, #$FF);
-
-    SetDataPointer(Image, Format, Size.X, Size.Y);
-  except
-    FreeMem(Image);
-    raise;
+    fs.Position := 0;
+    SaveToStream(fs, aFileType);
+  finally
+    fs.Free;
   end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType);
+begin
+  case aFileType of
+    {$IFDEF GLB_SUPPORT_PNG_WRITE}
+    ftPNG:  SavePng(aStream);
+    {$ENDIF}
+    {$IFDEF GLB_SUPPORT_JPEG_WRITE}
+    ftJPEG: SaveJPEG(aStream);
+    {$ENDIF}
+    ftDDS:  SaveDDS(aStream);
+    ftTGA:  SaveTGA(aStream);
+    ftBMP:  SaveBMP(aStream);
+  end;
+end;
 
-constructor TglBitmap.Create(Size: TglBitmapPixelPosition;
-  Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean;
 begin
-  Create;
-  LoadFromFunc(Size, Func, Format, CustomData);
+  result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs);
 end;
 
-
-function TglBitmap.Clone: TglBitmap;
-var
-  Temp: TglBitmap;
-  TempPtr: pByte;
-  Size: Integer;
-begin
-  Temp := ClassType.Create as TglBitmap;
-  try
-    // copy texture data if assigned
-    if Assigned(Data) then begin
-      Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
-
-      GetMem(TempPtr, Size);
-      try
-        Move(Data^, TempPtr^, Size);
-        Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height);
-      except
-        FreeMem(TempPtr);
-        raise;
-      end;
-    end else
-      Temp.SetDataPointer(nil, InternalFormat, Width, Height);
-
-       // copy properties
-    Temp.fID := ID;
-    Temp.fTarget := Target;
-    Temp.fFormat := Format;
-    Temp.fMipMap := MipMap;
-    Temp.fAnisotropic := Anisotropic;
-    Temp.fBorderColor := fBorderColor;
-    Temp.fDeleteTextureOnFree := DeleteTextureOnFree;
-    Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
-    Temp.fFilterMin := fFilterMin;
-    Temp.fFilterMag := fFilterMag;
-    Temp.fWrapS := fWrapS;
-    Temp.fWrapT := fWrapT;
-    Temp.fWrapR := fWrapR;
-    Temp.fFilename := fFilename;
-    Temp.fCustomName := fCustomName;
-    Temp.fCustomNameW := fCustomNameW;
-    Temp.fCustomDataPointer := fCustomDataPointer;
-
-    Result := Temp;
-  except
-    FreeAndNil(Temp);
-    raise;
-  end;
-end;
-
-
-procedure TglBitmap.LoadFromFile(FileName: String);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean;
+  const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean;
 var
-  FS: TFileStream;
-begin
-  fFilename := FileName;
-
-  FS := TFileStream.Create(FileName, fmOpenRead);
-  try
-    FS.Position := 0;
-    
-    LoadFromStream(FS);
-  finally
-    FS.Free;
-  end;
-end;
-
-
-procedure TglBitmap.LoadFromStream(Stream: TStream);
-begin
-  {$IFDEF GLB_SUPPORT_PNG_READ}
-  if not LoadPNG(Stream) then
-  {$ENDIF}
-  {$IFDEF GLB_SUPPORT_JPEG_READ}
-  if not LoadJPEG(Stream) then
-  {$ENDIF}
-  if not LoadDDS(Stream) then
-  if not LoadTGA(Stream) then
-  if not LoadBMP(Stream) then
-    raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
-end;
-
+  DestData, TmpData, SourceData: pByte;
+  TempHeight, TempWidth: Integer;
+  SourceFD, DestFD: TFormatDescriptor;
+  SourceMD, DestMD: Pointer;
 
-{$IFDEF GLB_DELPHI}
-procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar);
-var
-  RS: TResourceStream;
-  TempPos: Integer;
-  ResTypeStr: String;
-  TempResType: PChar;
+  FuncRec: TglBitmapFunctionRec;
 begin
-  if Assigned(ResType) then
-    TempResType := ResType
-  else
-    begin
-      TempPos := Pos('.', Resource);
-      ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos));
-      Resource   := UpperCase(Copy(Resource, 0, TempPos -1));
-      TempResType := PChar(ResTypeStr);
-    end;
-
-  RS := TResourceStream.Create(Instance, Resource, TempResType);
-  try
-    LoadFromStream(RS);
-  finally
-    RS.Free;
-  end;
-end;
+  Assert(Assigned(Data));
+  Assert(Assigned(aSource));
+  Assert(Assigned(aSource.Data));
 
+  result := false;
+  if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin
+    SourceFD := TFormatDescriptor.Get(aSource.Format);
+    DestFD   := TFormatDescriptor.Get(aFormat);
 
-procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar);
-var
-  RS: TResourceStream;
-begin
-  RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
-  try
-    LoadFromStream(RS);
-  finally
-    RS.Free;
-  end;
-end;
-{$ENDIF}
+    // inkompatible Formats so CreateTemp
+    if (SourceFD.PixelSize <> DestFD.PixelSize) then
+      aCreateTemp := true;
 
+    // Values
+    TempHeight := Max(1, aSource.Height);
+    TempWidth  := Max(1, aSource.Width);
 
+    FuncRec.Sender := Self;
+    FuncRec.Args   := aArgs;
 
-procedure TglBitmap.LoadFromFunc(Size: TglBitmapPixelPosition;
-  Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer);
-var
-  Image: pByte;
-  ImageSize: Integer;
-begin
-  ImageSize := FormatGetImageSize(Size, Format);
-  GetMem(Image, ImageSize);
-  try
-    FillChar(Image^, ImageSize, #$FF);
+    TmpData := nil;
+    if aCreateTemp then begin
+      GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight));
+      DestData := TmpData;
+    end else
+      DestData := Data;
 
-    SetDataPointer(Image, Format, Size.X, Size.Y);
-  except
-    FreeMem(Image);
-    raise;
-  end;
+    try
+      SourceFD.PreparePixel(FuncRec.Source);
+      DestFD.PreparePixel  (FuncRec.Dest);
 
-  AddFunc(Self, Func, False, Format, CustomData)
-end;
+      SourceMD := SourceFD.CreateMappingData;
+      DestMD   := DestFD.CreateMappingData;
 
+      FuncRec.Size            := aSource.Dimension;
+      FuncRec.Position.Fields := FuncRec.Size.Fields;
 
-procedure TglBitmap.SaveToFile(FileName: String; FileType: TglBitmapFileType);
-var
-  FS: TFileStream;
-begin
-  FS := TFileStream.Create(FileName, fmCreate);
-  try
-    FS.Position := 0;
-    SaveToStream(FS, FileType);
-  finally
-    FS.Free;
-  end;
-end;
+      try
+        SourceData := aSource.Data;
+        FuncRec.Position.Y := 0;
+        while FuncRec.Position.Y < TempHeight do begin
+          FuncRec.Position.X := 0;
+          while FuncRec.Position.X < TempWidth do begin
+            SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
+            aFunc(FuncRec);
+            DestFD.Map(FuncRec.Dest, DestData, DestMD);
+            inc(FuncRec.Position.X);
+          end;
+          inc(FuncRec.Position.Y);
+        end;
 
+        // Updating Image or InternalFormat
+        if aCreateTemp then
+          SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height)
+        else if (aFormat <> fFormat) then
+          Format := aFormat;
 
-procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType);
-begin
-  case FileType of
-    {$IFDEF GLB_SUPPORT_PNG_WRITE}
-    ftPNG:  SavePng(Stream);
-    {$ENDIF}
-    {$IFDEF GLB_SUPPORT_JPEG_WRITE}
-    ftJPEG: SaveJPEG(Stream);
-    {$ENDIF}
-    ftDDS:  SaveDDS(Stream);
-    ftTGA:  SaveTGA(Stream);
-    ftBMP:  SaveBMP(Stream);
+        result := true;
+      finally
+        SourceFD.FreeMappingData(SourceMD);
+        DestFD.FreeMappingData(DestMD);
+      end;
+    except
+      if aCreateTemp then
+        FreeMem(TmpData);
+      raise;
+    end;
   end;
 end;
 
-
 {$IFDEF GLB_SDL}
-function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean;
 var
   Row, RowSize: Integer;
-  pSource, pData: PByte;
+  SourceData, TmpData: PByte;
   TempDepth: Integer;
   Pix: TglBitmapPixelData;
+  FormatDesc: TglBitmapFormatDescriptor;
 
   function GetRowPointer(Row: Integer): pByte;
   begin
-    Result := Surface.pixels;
-    Inc(Result, Row * RowSize);
+    result := Surface.pixels;
+    Inc(result, Row * RowSize);
   end;
 
 begin
-  Result := False;
+  result := false;
 
-  if not FormatIsUncompressed(InternalFormat) then 
+  (* TODO
+  if not FormatIsUncompressed(InternalFormat) then
     raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  *)
 
+  FormatDesc := FORMAT_DESCRIPTORS[Format];
   if Assigned(Data) then begin
-    case Trunc(FormatGetSize(InternalFormat)) of
+    case Trunc(FormatDesc.GetSize) of
       1: TempDepth :=  8;
       2: TempDepth := 16;
       3: TempDepth := 24;
       4: TempDepth := 32;
-      else
-        raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
+    else
+      raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT);
     end;
-
-    FormatPreparePixel(Pix, InternalFormat);
-
+    FormatDesc.PreparePixel(Pix);
     with Pix.PixelDesc do
-      Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
+      Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth,
+        RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift);
 
-    pSource := Data;
-    RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat));
+    SourceData := Data;
+    RowSize    := Ceil(FileWidth * FormatDesc.GetSize);
 
     for Row := 0 to FileHeight -1 do begin
-      pData := GetRowPointer(Row);
-
-      if Assigned(pData) then begin
-        Move(pSource^, pData^, RowSize);
-        Inc(pSource, RowSize);
+      TmpData := GetRowPointer(Row);
+      if Assigned(TmpData) then begin
+        Move(SourceData^, TmpData^, RowSize);
+        inc(SourceData, RowSize);
       end;
     end;
-
-    Result := True;
+    result := true;
   end;
 end;
 
-
-function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean;
 var
   pSource, pData, pTempData: PByte;
   Row, RowSize, TempWidth, TempHeight: Integer;
-  IntFormat: TglBitmapInternalFormat;
+  IntFormat, f: TglBitmapInternalFormat;
+  FormatDesc: TglBitmapFormatDescriptor;
 
   function GetRowPointer(Row: Integer): pByte;
   begin
-    Result := Surface^.pixels;
-    Inc(Result, Row * RowSize);
+    result := Surface^.pixels;
+    Inc(result, Row * RowSize);
   end;
 
 begin
-  Result := False;
-
+  result := false;
   if (Assigned(Surface)) then begin
     with Surface^.format^ do begin
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then
-        IntFormat := ifLuminance
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then
-        IntFormat := ifLuminanceAlpha
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then
-        IntFormat := ifRGBA4
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then
-        IntFormat := ifR5G6B5
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then
-        IntFormat := ifRGB5A1
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then
-        IntFormat := ifBGR8
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then
-        IntFormat := ifRGB8
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then
-        IntFormat := ifBGRA8
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then
-        IntFormat := ifRGBA8
-      else
-
-      if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then
-        IntFormat := ifRGB10A2
-      else
+      IntFormat := tfEmpty;
+      for f := Low(f) to High(f) do begin
+        if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin
+          IntFormat := f;
+          break;
+        end;
+      end;
+      if (IntFormat = tfEmpty) then
         raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.');
     end;
 
-    TempWidth := Surface^.w;
+    FormatDesc := FORMAT_DESCRIPTORS[IntFormat];
+    TempWidth  := Surface^.w;
     TempHeight := Surface^.h;
-
-    RowSize := Trunc(TempWidth * FormatGetSize(IntFormat));
-
+    RowSize := Trunc(TempWidth * FormatDesc.GetSize);
     GetMem(pData, TempHeight * RowSize);
     try
       pTempData := pData;
-
       for Row := 0 to TempHeight -1 do begin
         pSource := GetRowPointer(Row);
-
         if (Assigned(pSource)) then begin
           Move(pSource^, pTempData^, RowSize);
           Inc(pTempData, RowSize);
         end;
       end;
-
       SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
-
-      Result := True;
+      result := true;
     except
       FreeMem(pData);
       raise;
@@ -3035,40 +3948,35 @@ begin
   end;
 end;
 
-
-function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean;
 var
   Row, Col, AlphaInterleave: Integer;
   pSource, pDest: PByte;
 
   function GetRowPointer(Row: Integer): pByte;
   begin
-    Result := Surface.pixels;
-    Inc(Result, Row * Width);
+    result := aSurface.pixels;
+    Inc(result, Row * Width);
   end;
 
 begin
-  Result := False;
-
+  result := false;
   if Assigned(Data) then begin
-    if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin
-      Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
+    if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin
+      aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0);
 
-      case InternalFormat of
-        ifLuminanceAlpha:
+      AlphaInterleave := 0;
+      case Format of
+        ifLuminance8Alpha8:
           AlphaInterleave := 1;
         ifBGRA8, ifRGBA8:
           AlphaInterleave := 3;
-        else
-          AlphaInterleave := 0;
       end;
 
-      // Copy Data
       pSource := Data;
-
       for Row := 0 to Height -1 do begin
         pDest := GetRowPointer(Row);
-
         if Assigned(pDest) then begin
           for Col := 0 to Width -1 do begin
             Inc(pSource, AlphaInterleave);
@@ -3078,37 +3986,83 @@ begin
           end;
         end;
       end;
-
-      Result := True;
+      result := true;
     end;
   end;
 end;
 
-
-function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
 var
-  glBitmap: TglBitmap2D;
+  bmp: TglBitmap2D;
 begin
-  glBitmap := TglBitmap2D.Create;
+  bmp := TglBitmap2D.Create;
   try
-    glBitmap.AssignFromSurface(Surface);
-
-    Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
+    bmp.AssignFromSurface(Surface);
+    result := AddAlphaFromGlBitmap(bmp, Func, CustomData);
   finally
-    glBitmap.Free;
+    bmp.Free;
   end;
 end;
 {$ENDIF}
 
-
 {$IFDEF GLB_DELPHI}
-function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean;
+//TODO rework & test
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean;
+var
+  Row: Integer;
+  pSource, pData: PByte;
+begin
+  result := false;
+  if Assigned(Data) then begin
+    if Assigned(aBitmap) then begin
+      aBitmap.Width  := Width;
+      aBitmap.Height := Height;
+
+      case Format of
+        tfAlpha8, ifLuminance, ifDepth8:
+          begin
+            Bitmap.PixelFormat := pf8bit;
+            Bitmap.Palette := CreateGrayPalette;
+          end;
+        ifRGB5A1:
+          Bitmap.PixelFormat := pf15bit;
+        ifR5G6B5:
+          Bitmap.PixelFormat := pf16bit;
+        ifRGB8, ifBGR8:
+          Bitmap.PixelFormat := pf24bit;
+        ifRGBA8, ifBGRA8:
+          Bitmap.PixelFormat := pf32bit;
+        else
+          raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
+      end;
+
+      pSource := Data;
+      for Row := 0 to FileHeight -1 do begin
+        pData := Bitmap.Scanline[Row];
+
+        Move(pSource^, pData^, fRowSize);
+        Inc(pSource, fRowSize);
+
+        // swap RGB(A) to BGR(A)
+        if InternalFormat in [ifRGB8, ifRGBA8] then
+          SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
+      end;
+
+      result := true;
+    end;
+  end;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean;
 var
   pSource, pData, pTempData: PByte;
   Row, RowSize, TempWidth, TempHeight: Integer;
   IntFormat: TglBitmapInternalFormat;
 begin
-  Result := False;
+  result := false;
 
   if (Assigned(Bitmap)) then begin
     case Bitmap.PixelFormat of
@@ -3146,7 +4100,7 @@ begin
 
       SetDataPointer(pData, IntFormat, TempWidth, TempHeight);
 
-      Result := True;
+      result := true;
     except
       FreeMem(pData);
       raise;
@@ -3154,61 +4108,13 @@ begin
   end;
 end;
 
-
-function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean;
-var
-  Row: Integer;
-  pSource, pData: PByte;
-begin
-  Result := False;
-
-  if Assigned(Data) then begin
-    if Assigned(Bitmap) then begin
-      Bitmap.Width := Width;
-      Bitmap.Height := Height;
-
-      case InternalFormat of
-        ifAlpha, ifLuminance, ifDepth8:
-          begin
-            Bitmap.PixelFormat := pf8bit;
-            Bitmap.Palette := CreateGrayPalette;
-          end;
-        ifRGB5A1:
-          Bitmap.PixelFormat := pf15bit;
-        ifR5G6B5:
-          Bitmap.PixelFormat := pf16bit;
-        ifRGB8, ifBGR8:
-          Bitmap.PixelFormat := pf24bit;
-        ifRGBA8, ifBGRA8:
-          Bitmap.PixelFormat := pf32bit;
-        else
-          raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
-      end;
-
-      pSource := Data;
-      for Row := 0 to FileHeight -1 do begin
-        pData := Bitmap.Scanline[Row];
-
-        Move(pSource^, pData^, fRowSize);
-        Inc(pSource, fRowSize);
-
-        // swap RGB(A) to BGR(A)
-        if InternalFormat in [ifRGB8, ifRGBA8] then
-          SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8);
-      end;
-
-      Result := True;
-    end;
-  end;
-end;
-
-
-function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean;
 var
   Row, Col, AlphaInterleave: Integer;
   pSource, pDest: PByte;
 begin
-  Result := False;
+  result := false;
 
   if Assigned(Data) then begin
     if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin
@@ -3243,58 +4149,29 @@ begin
           end;
         end;
 
-        Result := True;
+        result := true;
       end;
     end;
   end;
 end;
 
-
-function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
 var
-  glBitmap: TglBitmap2D;
-begin
-  glBitmap := TglBitmap2D.Create;
-  try
-    glBitmap.AssignFromBitmap(Bitmap);
-
-    Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
-  finally
-    glBitmap.Free;
-  end;
-end;
-{$ENDIF}
-
-
-function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean;
-var
-  FS: TFileStream;
-begin
-  FS := TFileStream.Create(FileName, fmOpenRead);
-  try
-    Result := AddAlphaFromStream(FS, Func, CustomData);
-  finally
-    FS.Free;
-  end;
-end;
-
-
-function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean;
-var
-  glBitmap: TglBitmap2D;
+  tex: TglBitmap2D;
 begin
-  glBitmap := TglBitmap2D.Create(Stream);
+  tex := TglBitmap2D.Create;
   try
-    Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData);
+    tex.AssignFromBitmap(Bitmap);
+    result := AddAlphaFromglBitmap(tex, Func, CustomData);
   finally
-    glBitmap.Free;
+    tex.Free;
   end;
 end;
 
-
-{$IFDEF GLB_DELPHI}
-function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String;
-  ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar;
+  const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
 var
   RS: TResourceStream;
   TempPos: Integer;
@@ -3313,167 +4190,385 @@ begin
 
   RS := TResourceStream.Create(Instance, Resource, TempResType);
   try
-    Result := AddAlphaFromStream(RS, Func, CustomData);
+    result := AddAlphaFromStream(RS, Func, CustomData);
   finally
     RS.Free;
   end;
 end;
 
-
-function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer;
-  ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar;
+  const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
 var
   RS: TResourceStream;
 begin
   RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType);
   try
-    Result := AddAlphaFromStream(RS, Func, CustomData);
+    result := AddAlphaFromStream(RS, Func, CustomData);
   finally
     RS.Free;
   end;
 end;
 {$ENDIF}
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
+begin
+  (* TODO
+  if not FormatIsUncompressed(InternalFormat) then
+    raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT);
+  *)
+  result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs);
+end;
 
-procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
+var
+  FS: TFileStream;
 begin
-  with FuncRec do begin
-    Dest.Red   := Source.Red;
-    Dest.Green := Source.Green;
-    Dest.Blue  := Source.Blue;
-
-    with TglBitmapPixelData(CustomData^) do
-      if ((Dest.Red   <= Red  ) and (Dest.Red   >= PixelDesc.RedRange  ) and
-          (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and
-          (Dest.Blue  <= Blue ) and (Dest.Blue  >= PixelDesc.BlueRange )) then
-        Dest.Alpha := 0
-      else
-        Dest.Alpha := Dest.PixelDesc.AlphaRange;
+  FS := TFileStream.Create(FileName, fmOpenRead);
+  try
+    result := AddAlphaFromStream(FS, aFunc, aArgs);
+  finally
+    FS.Free;
   end;
 end;
 
-
-function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte
-  ): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
+var
+  tex: TglBitmap2D;
 begin
-  Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF);
+  tex := TglBitmap2D.Create(aStream);
+  try
+    result := AddAlphaFromglBitmap(tex, aFunc, aArgs);
+  finally
+    tex.Free;
+  end;
 end;
 
-
-function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean;
 var
-  PixelData: TglBitmapPixelData;
+  DestData, DestData2, SourceData: pByte;
+  TempHeight, TempWidth: Integer;
+  SourceFD, DestFD: TFormatDescriptor;
+  SourceMD, DestMD, DestMD2: Pointer;
+
+  FuncRec: TglBitmapFunctionRec;
 begin
-  FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
+  result := false;
 
-  Result := AddAlphaFromColorKeyFloat(
-    Red   / PixelData.PixelDesc.RedRange,
-    Green / PixelData.PixelDesc.GreenRange,
-    Blue  / PixelData.PixelDesc.BlueRange,
-    Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange)));
-end;
+  Assert(Assigned(Data));
+  Assert(Assigned(aBitmap));
+  Assert(Assigned(aBitmap.Data));
 
+  if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin
+    result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha);
+    if not Assigned(aFunc) then
+      aFunc := glBitmapAlphaFunc;
 
-function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean;
-var
-  TempR, TempG, TempB: Cardinal;
-  PixelData: TglBitmapPixelData;
-begin
-  FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
+    SourceFD := TFormatDescriptor.Get(aBitmap.Format);
+    DestFD   := TFormatDescriptor.Get(Format);
+
+    // Values
+    TempHeight := aBitmap.FileHeight;
+    TempWidth  := aBitmap.FileWidth;
+
+    FuncRec.Sender          := Self;
+    FuncRec.Args            := aArgs;
+    FuncRec.Size            := Dimension;
+    FuncRec.Position.Fields := FuncRec.Size.Fields;
+    FuncRec.Args            := PtrInt(SourceFD.HasAlpha) and 1;
+
+    DestData   := Data;
+    DestData2  := Data;
+    SourceData := aBitmap.Data;
 
-  // Calculate Colorrange
-  with PixelData.PixelDesc do begin
-    TempR := Trunc(RedRange   * Deviation);
-    TempG := Trunc(GreenRange * Deviation);
-    TempB := Trunc(BlueRange  * Deviation);
+    // Mapping
+    SourceFD.PreparePixel(FuncRec.Source);
+    DestFD.PreparePixel  (FuncRec.Dest);
 
-    PixelData.Red   := Min(RedRange,   Trunc(RedRange   * Red)   + TempR);
-    RedRange        := Max(0,          Trunc(RedRange   * Red)   - TempR);
-    PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG);
-    GreenRange      := Max(0,          Trunc(GreenRange * Green) - TempG);
-    PixelData.Blue  := Min(BlueRange,  Trunc(BlueRange  * Blue)  + TempB);
-    BlueRange       := Max(0,          Trunc(BlueRange  * Blue)  - TempB);
-    PixelData.Alpha := 0;
-    AlphaRange      := 0;
+    SourceMD := SourceFD.CreateMappingData;
+    DestMD   := DestFD.CreateMappingData;
+    DestMD2  := DestFD.CreateMappingData;
+    try
+      FuncRec.Position.Y := 0;
+      while FuncRec.Position.Y < TempHeight do begin
+        FuncRec.Position.X := 0;
+        while FuncRec.Position.X < TempWidth do begin
+          SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD);
+          DestFD.Unmap  (DestData,   FuncRec.Dest,   DestMD);
+          aFunc(FuncRec);
+          DestFD.Map(FuncRec.Dest, DestData2, DestMD2);
+          inc(FuncRec.Position.X);
+        end;
+        inc(FuncRec.Position.Y);
+      end;
+    finally
+      SourceFD.FreeMappingData(SourceMD);
+      DestFD.FreeMappingData(DestMD);
+      DestFD.FreeMappingData(DestMD2);
+    end;
   end;
+end;
 
-  Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean;
+begin
+  result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF);
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean;
+var
+  PixelData: TglBitmapPixelData;
+begin
+  TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
+  result := AddAlphaFromColorKeyFloat(
+    aRed   / PixelData.Range.r,
+    aGreen / PixelData.Range.g,
+    aBlue  / PixelData.Range.b,
+    aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b)));
+end;
 
-procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean;
+var
+  values: array[0..2] of Single;
+  tmp: Cardinal;
+  i: Integer;
+  PixelData: TglBitmapPixelData;
 begin
-  with FuncRec do begin
-    Dest.Red   := Source.Red;
-    Dest.Green := Source.Green;
-    Dest.Blue  := Source.Blue;
+  TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
+  with PixelData do begin
+    values[0] := aRed;
+    values[1] := aGreen;
+    values[2] := aBlue;
 
-    with TglBitmapPixelData(CustomData^) do
-      Dest.Alpha := Alpha;
+    for i := 0 to 2 do begin
+      tmp          := Trunc(Range.arr[i] * aDeviation);
+      Data.arr[i]  := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp));
+      Range.arr[i] := Max(0,            Trunc(Range.arr[i] * values[i] - tmp));
+    end;
+    Data.a  := 0;
+    Range.a := 0;
   end;
+  result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData));
 end;
 
-
-function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean;
 begin
-  Result := AddAlphaFromValueFloat(Alpha / $FF);
+  result := AddAlphaFromValueFloat(aAlpha / $FF);
 end;
 
-
-function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean;
 var
   PixelData: TglBitmapPixelData;
 begin
-  FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
-
-  with PixelData.PixelDesc do
-    PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha)));
+  TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
+  result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a);
+end;
 
-  Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean;
+var
+  PixelData: TglBitmapPixelData;
+begin
+  TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
+  with PixelData do
+    Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha)));
+  result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData.Data.a));
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.RemoveAlpha: Boolean;
+var
+  FormatDesc: TFormatDescriptor;
+begin
+  result := false;
+  FormatDesc := TFormatDescriptor.Get(Format);
+  if Assigned(Data) then begin
+    if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then
+      raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT);
+    result := ConvertTo(FormatDesc.WithoutAlpha);
+  end;
+end;
 
-function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.Clone: TglBitmap;
 var
-  PixelData: TglBitmapPixelData;
+  Temp: TglBitmap;
+  TempPtr: PByte;
+  Size: Integer;
 begin
-  FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
+  result := nil;
+  Temp := (ClassType.Create as TglBitmap);
+  try
+    // copy texture data if assigned
+    if Assigned(Data) then begin
+      Size := TFormatDescriptor.Get(Format).GetSize(fDimension);
+      GetMem(TempPtr, Size);
+      try
+        Move(Data^, TempPtr^, Size);
+        Temp.SetDataPointer(TempPtr, Format, Width, Height);
+      except
+        FreeMem(TempPtr);
+        raise;
+      end;
+    end else
+      Temp.SetDataPointer(nil, Format, Width, Height);
 
-  Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange);
+       // copy properties
+    Temp.fID                      := ID;
+    Temp.fTarget                  := Target;
+    Temp.fFormat                  := Format;
+    Temp.fMipMap                  := MipMap;
+    Temp.fAnisotropic             := Anisotropic;
+    Temp.fBorderColor             := fBorderColor;
+    Temp.fDeleteTextureOnFree     := DeleteTextureOnFree;
+    Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture;
+    Temp.fFilterMin               := fFilterMin;
+    Temp.fFilterMag               := fFilterMag;
+    Temp.fWrapS                   := fWrapS;
+    Temp.fWrapT                   := fWrapT;
+    Temp.fWrapR                   := fWrapR;
+    Temp.fFilename                := fFilename;
+    Temp.fCustomName              := fCustomName;
+    Temp.fCustomNameW             := fCustomNameW;
+    Temp.fCustomData              := fCustomData;
+
+    result := Temp;
+  except
+    FreeAndNil(Temp);
+    raise;
+  end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean;
+var
+  SourceFD, DestFD: TFormatDescriptor;
+  SourcePD, DestPD: TglBitmapPixelData;
+  ShiftData: TShiftData;
+
+  function CanCopyDirect: Boolean;
+  begin
+    result :=
+      ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
+      ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
+      ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
+      ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
+  end;
 
-procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec);
-begin
-  with FuncRec do begin
-    Dest.Red   := Source.Red;
-    Dest.Green := Source.Green;
-    Dest.Blue  := Source.Blue;
-    Dest.Alpha := Source.Alpha;
-
-    if (Integer(CustomData) and $1 > 0) then begin
-      Dest.Red   := Dest.Red   xor Dest.PixelDesc.RedRange;
-      Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange;
-      Dest.Blue  := Dest.Blue  xor Dest.PixelDesc.BlueRange;
-    end;
+  function CanShift: Boolean;
+  begin
+    result :=
+      ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and
+      ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and
+      ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and
+      ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0));
+  end;
 
-    if (Integer(CustomData) and $2 > 0) then begin
-      Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange;
+  function GetShift(aSource, aDest: Cardinal) : ShortInt;
+  begin
+    result := 0;
+    while (aSource > aDest) and (aSource > 0) do begin
+      inc(result);
+      aSource := aSource shr 1;
     end;
   end;
+
+begin
+  if aFormat <> fFormat then begin
+    SourceFD := TFormatDescriptor.Get(Format);
+    DestFD   := TFormatDescriptor.Get(aFormat);
+
+    SourceFD.PreparePixel(SourcePD);
+    DestFD.PreparePixel  (DestPD);
+
+    if CanCopyDirect then
+      result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat)
+    else if CanShift then begin
+      ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r);
+      ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g);
+      ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b);
+      ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a);
+      result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@ShiftData));
+    end else
+      result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat);
+  end else
+    result := true;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
+begin
+  if aUseRGB or aUseAlpha then
+    AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1));
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single);
+begin
+  fBorderColor[0] := aRed;
+  fBorderColor[1] := aGreen;
+  fBorderColor[2] := aBlue;
+  fBorderColor[3] := aAlpha;
+  if (ID > 0) then begin
+    Bind(false);
+    glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
+  end;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.FreeData;
+begin
+  SetDataPointer(nil, tfEmpty);
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte;
+  const aAlpha: Byte);
+begin
+  FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF);
+end;
 
-procedure TglBitmap.Invert(UseRGB: Boolean; UseAlpha: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal);
+var
+  PixelData: TglBitmapPixelData;
 begin
-  if ((UseRGB) or (UseAlpha)) then
-    AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB)));
+  TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData);
+  FillWithColorFloat(
+    aRed   / PixelData.Range.r,
+    aGreen / PixelData.Range.g,
+    aBlue  / PixelData.Range.b,
+    aAlpha / PixelData.Range.a);
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single);
+var
+  PixelData: TglBitmapPixelData;
+begin
+  TFormatDescriptor.Get(Format).PreparePixel(PixelData);
+  with PixelData do begin
+    Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed)));
+    Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen)));
+    Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue)));
+    Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha)));
+  end;
+  AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData));
+end;
 
-procedure TglBitmap.SetFilter(Min, Mag: Integer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal);
 begin
-  case Min of
+  //check MIN filter
+  case aMin of
     GL_NEAREST:
       fFilterMin := GL_NEAREST;
     GL_LINEAR:
@@ -3487,25 +4582,25 @@ begin
     GL_LINEAR_MIPMAP_LINEAR:
       fFilterMin := GL_LINEAR_MIPMAP_LINEAR;
     else
-      raise EglBitmapException.Create('SetFilter - Unknow Minfilter.');
+      raise EglBitmapException.Create('SetFilter - Unknow MIN filter.');
   end;
 
-  case Mag of
+  //check MAG filter
+  case aMag of
     GL_NEAREST:
       fFilterMag := GL_NEAREST;
     GL_LINEAR:
       fFilterMag := GL_LINEAR;
     else
-      raise EglBitmapException.Create('SetFilter - Unknow Magfilter.');
+      raise EglBitmapException.Create('SetFilter - Unknow MAG filter.');
   end;
 
-  // If texture is created then assign filter
-  if ID > 0 then begin
-    Bind(False);
-
+  //apply filter
+  if (ID > 0) then begin
+    Bind(false);
     glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag);
 
-    if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin
+    if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin
       case fFilterMin of
         GL_NEAREST, GL_LINEAR:
           glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin);
@@ -3519,174 +4614,194 @@ begin
   end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal);
 
-procedure TglBitmap.SetWrap(S: Integer; T: Integer; R: Integer);
-begin
-  case S of
-    GL_CLAMP:
-      fWrapS := GL_CLAMP;
-    GL_REPEAT:
-      fWrapS := GL_REPEAT;
-    GL_CLAMP_TO_EDGE:
-      begin
+  procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal);
+  begin
+    case aValue of
+      GL_CLAMP:
+        aTarget := GL_CLAMP;
+
+      GL_REPEAT:
+        aTarget := GL_REPEAT;
+
+      GL_CLAMP_TO_EDGE: begin
         if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
-          fWrapS := GL_CLAMP_TO_EDGE
+          aTarget := GL_CLAMP_TO_EDGE
         else
-          fWrapS := GL_CLAMP;
+          aTarget := GL_CLAMP;
       end;
-    GL_CLAMP_TO_BORDER:
-      begin
+
+      GL_CLAMP_TO_BORDER: begin
         if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
-          fWrapS := GL_CLAMP_TO_BORDER
+          aTarget := GL_CLAMP_TO_BORDER
         else
-          fWrapS := GL_CLAMP;
+          aTarget := GL_CLAMP;
       end;
-    GL_MIRRORED_REPEAT:
-      begin
+
+      GL_MIRRORED_REPEAT: begin
         if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
-          fWrapS := GL_MIRRORED_REPEAT
+          aTarget := GL_MIRRORED_REPEAT
         else
           raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).');
       end;
     else
       raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).');
+    end;
   end;
 
-  case T of
-    GL_CLAMP:
-      fWrapT := GL_CLAMP;
-    GL_REPEAT:
-      fWrapT := GL_REPEAT;
-    GL_CLAMP_TO_EDGE:
-      begin
-        if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
-          fWrapT := GL_CLAMP_TO_EDGE
-        else
-          fWrapT := GL_CLAMP;
-      end;
-    GL_CLAMP_TO_BORDER:
-      begin
-        if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
-          fWrapT := GL_CLAMP_TO_BORDER
-        else
-          fWrapT := GL_CLAMP;
-      end;
-    GL_MIRRORED_REPEAT:
-      begin
-        if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
-          fWrapT := GL_MIRRORED_REPEAT
-        else
-          raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).');
-      end;
-    else
-      raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).');
-  end;
-
-  case R of
-    GL_CLAMP:
-      fWrapR := GL_CLAMP;
-    GL_REPEAT:
-      fWrapR := GL_REPEAT;
-    GL_CLAMP_TO_EDGE:
-      begin
-        if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then
-          fWrapR := GL_CLAMP_TO_EDGE
-        else
-          fWrapR := GL_CLAMP;
-      end;
-    GL_CLAMP_TO_BORDER:
-      begin
-        if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then
-          fWrapR := GL_CLAMP_TO_BORDER
-        else
-          fWrapR := GL_CLAMP;
-      end;
-    GL_MIRRORED_REPEAT:
-      begin
-        if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then
-          fWrapR := GL_MIRRORED_REPEAT
-        else
-          raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).');
-      end;
-    else
-      raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).');
-  end;
+begin
+  CheckAndSetWrap(S, fWrapS);
+  CheckAndSetWrap(T, fWrapT);
+  CheckAndSetWrap(R, fWrapR);
 
-  if ID > 0 then begin
-    Bind (False);
+  if (ID > 0) then begin
+    Bind(false);
     glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS);
     glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT);
     glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR);
   end;
 end;
 
-
-procedure TglBitmap.SetDataPointer(NewData: pByte;
-  Format: TglBitmapInternalFormat; Width: Integer; Height: Integer);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData);
 begin
-  // Data
-  if Data <> NewData then begin
-    if (Assigned(Data))
-      then FreeMem(Data);
+  { TODO delete?
+  if Assigned (fGetPixelFunc) then
+    fGetPixelFunc(aPos, aPixel);
+    }
+end;
 
-    fData := NewData;
-  end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData);
+begin
+  {TODO delete?
+  if Assigned (fSetPixelFunc) then
+    fSetPixelFuc(aPos, aPixel);
+    }
+end;
 
-  if Data = nil then begin
-    fInternalFormat := ifEmpty;
-    fPixelSize := 0;
-    fRowSize := 0;
-  end else begin
-    if Width <> -1 then begin
-      fDimension.Fields := fDimension.Fields + [ffX];
-      fDimension.X := Width;
-    end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean);
+begin
+  if aEnableTextureUnit then
+    glEnable(Target);
+  if (ID > 0) then
+    glBindTexture(Target, ID);
+end;
 
-    if Height <> -1 then begin
-      fDimension.Fields := fDimension.Fields + [ffY];
-      fDimension.Y := Height;
-    end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean);
+begin
+  if aDisableTextureUnit then
+    glDisable(Target);
+  glBindTexture(Target, 0);
+end;
 
-    fInternalFormat := Format;
-    fPixelSize := Trunc(FormatGetSize(InternalFormat));
-    fRowSize :=  Trunc(FormatGetSize(InternalFormat) * Self.Width);
-  end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create;
+begin
+{$IFNDEF GLB_NO_NATIVE_GL}
+  ReadOpenGLExtensions;
+{$ENDIF}
+  if (ClassType = TglBitmap) then
+    raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.');
+  inherited Create;
 end;
 
-{$IFDEF GLB_SUPPORT_PNG_READ}
-{$IFDEF GLB_LIB_PNG}
-procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aFileName: String);
 begin
-  TStream(png_get_io_ptr(png)).Read(buffer^, size);
+  Create;
+  LoadFromFile(FileName);
 end;
-{$ENDIF}
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aStream: TStream);
+begin
+  Create;
+  LoadFromStream(aStream);
+end;
 
-function TglBitmap.LoadPNG(Stream: TStream): Boolean;
-{$IFDEF GLB_SDL_IMAGE}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
 var
-  Surface: PSDL_Surface;
-  RWops: PSDL_RWops;
+  Image: PByte;
+  ImageSize: Integer;
 begin
-  Result := False;
-
-  RWops := glBitmapCreateRWops(Stream);
+  Create;
+  TFormatDescriptor.Get(aFormat).GetSize(aSize);
+  GetMem(Image, ImageSize);
   try
-    if IMG_isPNG(RWops) > 0 then begin
-      Surface := IMG_LoadPNG_RW(RWops);
-      try
-        AssignFromSurface(Surface);
-        Result := True;
-      finally
-        SDL_FreeSurface(Surface);
-      end;
-    end;
-  finally
-    SDL_FreeRW(RWops);
+    FillChar(Image^, ImageSize, #$FF);
+    SetDataPointer(Image, aFormat, aSize.X, aSize.Y);
+  except
+    FreeMem(Image);
+    raise;
   end;
 end;
-{$ENDIF}
-{$IFDEF GLB_LIB_PNG}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
+  const aFunc: TglBitmapFunction; const aArgs: PtrInt);
+begin
+  Create;
+  LoadFromFunc(aSize, aFunc, aFormat, aArgs);
+end;
+
+{$IFDEF GLB_DELPHI}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar);
+begin
+  Create;
+  LoadFromResource(aInstance, aResource, aResType);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar);
+begin
+  Create;
+  LoadFromResourceID(aInstance, aResourceID, aResType);
+end;
+{$ENDIF}
+
+{$IFDEF GLB_SUPPORT_PNG_READ}
+{$IF DEFINED(GLB_SDL_IMAGE)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
+var
+  Surface: PSDL_Surface;
+  RWops: PSDL_RWops;
+begin
+  result := false;
+  RWops := glBitmapCreateRWops(aStream);
+  try
+    if IMG_isPNG(RWops) > 0 then begin
+      Surface := IMG_LoadPNG_RW(RWops);
+      try
+        AssignFromSurface(Surface);
+        Rresult := true;
+      finally
+        SDL_FreeSurface(Surface);
+      end;
+    end;
+  finally
+    SDL_FreeRW(RWops);
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_LIB_PNG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
+begin
+  TStream(png_get_io_ptr(png)).Read(buffer^, size);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
 var
   StreamPos: Int64;
   signature: array [0..7] of byte;
@@ -3700,7 +4815,7 @@ var
   png_rows: array of pByte;
   Row, LineSize: Integer;
 begin
-  Result := False;
+  result := false;
 
   if not init_libPNG then
     raise Exception.Create('LoadPNG - unable to initialize libPNG.');
@@ -3737,13 +4852,13 @@ begin
       // format
       case png_get_color_type(png, png_info) of
         PNG_COLOR_TYPE_GRAY:
-          Format := ifLuminance;
+          Format := tfLuminance8;
         PNG_COLOR_TYPE_GRAY_ALPHA:
-          Format := ifLuminanceAlpha;
+          Format := tfLuminance8Alpha8;
         PNG_COLOR_TYPE_RGB:
-          Format := ifRGB8;
+          Format := tfRGB8;
         PNG_COLOR_TYPE_RGB_ALPHA:
-          Format := ifRGBA8;
+          Format := tfRGBA8;
         else
           raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
       end;
@@ -3780,7 +4895,7 @@ begin
         // set new data
         SetDataPointer(png_data, Format, TempWidth, TempHeight);
 
-        Result := True;
+        result := true;
       except
         FreeMem(png_data);
         raise;
@@ -3790,8 +4905,10 @@ begin
     quit_libPNG;
   end;
 end;
-{$ENDIF}
-{$IFDEF GLB_PNGIMAGE}
+
+{$ELSEIF DEFINED(GLB_PNGIMAGE)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
 var
   StreamPos: Int64;
   Png: TPNGObject;
@@ -3804,7 +4921,7 @@ const
   PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
 
 begin
-  Result := False;
+  result := false;
 
   StreamPos := Stream.Position;
   Stream.Read(Header[0], SizeOf(Header));
@@ -3869,7 +4986,7 @@ begin
 
         SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
 
-        Result := True;
+        result := true;
       except
         FreeMem(NewImage);
         raise;
@@ -3879,10 +4996,175 @@ begin
     end;
   end;
 end;
+{$IFEND}
 {$ENDIF}
+
+{$IFDEF GLB_SUPPORT_PNG_WRITE}
+{$IFDEF GLB_LIB_PNG}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
+begin
+  TStream(png_get_io_ptr(png)).Write(buffer^, size);
+end;
 {$ENDIF}
 
+{$IF DEFINED(GLB_LIB_PNG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SavePNG(const aStream: TStream);
+var
+  png: png_structp;
+  png_info: png_infop;
+  png_rows: array of pByte;
+  LineSize: Integer;
+  ColorType: Integer;
+  Row: Integer;
+begin
+  if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
+    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+
+  if not init_libPNG then
+    raise Exception.Create('SavePNG - unable to initialize libPNG.');
+
+  try
+    case FInternalFormat of
+      ifAlpha, ifLuminance, ifDepth8:
+        ColorType := PNG_COLOR_TYPE_GRAY;
+      ifLuminanceAlpha:
+        ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
+      ifBGR8, ifRGB8:
+        ColorType := PNG_COLOR_TYPE_RGB;
+      ifBGRA8, ifRGBA8:
+        ColorType := PNG_COLOR_TYPE_RGBA;
+      else
+        raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+    end;
+    LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
+
+    // creating array for scanline
+    SetLength(png_rows, Height);
+    try
+      for Row := 0 to Height - 1 do begin
+        png_rows[Row] := Data;
+        Inc(png_rows[Row], Row * LineSize)
+      end;
+
+      // write struct
+      png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
+      if png = nil then
+        raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
+
+      // create png info
+      png_info := png_create_info_struct(png);
+      if png_info = nil then begin
+        png_destroy_write_struct(@png, nil);
+        raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
+      end;
+
+      // set read callback
+      png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
+
+      // set compression
+      png_set_compression_level(png, 6);
+
+      if InternalFormat in [ifBGR8, ifBGRA8] then
+        png_set_bgr(png);
+
+      png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+      png_write_info(png, png_info);
+      png_write_image(png, @png_rows[0]);
+      png_write_end(png, png_info);
+      png_destroy_write_struct(@png, @png_info);
+    finally
+      SetLength(png_rows, 0);
+    end;
+  finally
+    quit_libPNG;
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_PNGIMAGE)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SavePNG(const aStream: TStream);
+var
+  Png: TPNGObject;
+
+  pSource, pDest: pByte;
+  X, Y, PixSize: Integer;
+  ColorType: Cardinal;
+  Alpha: Boolean;
+
+  pTemp: pByte;
+  Temp: Byte;
+begin
+  if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
+    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+
+  case FInternalFormat of
+    ifAlpha, ifLuminance, ifDepth8: begin
+      ColorType := COLOR_GRAYSCALE;
+      PixSize := 1;
+      Alpha := false;
+    end;
+    ifLuminanceAlpha: begin
+      ColorType := COLOR_GRAYSCALEALPHA;
+      PixSize := 1;
+      Alpha := true;
+    end;
+    ifBGR8, ifRGB8: begin
+      ColorType := COLOR_RGB;
+      PixSize := 3;
+      Alpha := false;
+    end;
+    ifBGRA8, ifRGBA8: begin
+      ColorType := COLOR_RGBALPHA;
+      PixSize := 3;
+      Alpha := true
+    end;
+  else
+    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  end;
+
+  Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
+  try
+    // Copy ImageData
+    pSource := Data;
+    for Y := 0 to Height -1 do begin
+      pDest := png.ScanLine[Y];
+      for X := 0 to Width -1 do begin
+        Move(pSource^, pDest^, PixSize);
+        Inc(pDest, PixSize);
+        Inc(pSource, PixSize);
+        if Alpha then begin
+          png.AlphaScanline[Y]^[X] := pSource^;
+          Inc(pSource);
+        end;
+      end;
+
+      // convert RGB line to BGR
+      if InternalFormat in [ifRGB8, ifRGBA8] then begin
+        pTemp := png.ScanLine[Y];
+        for X := 0 to Width -1 do begin
+          Temp := pByteArray(pTemp)^[0];
+          pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
+          pByteArray(pTemp)^[2] := Temp;
+          Inc(pTemp, 3);
+        end;
+      end;
+    end;
+
+    // Save to Stream
+    Png.CompressionLevel := 6;
+    Png.SaveToStream(Stream);
+  finally
+    FreeAndNil(Png);
+  end;
+end;
+{$IFEND}
+{$ENDIF}
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//JPEG////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 {$IFDEF GLB_LIB_JPEG}
 type
   glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr;
@@ -3893,7 +5175,6 @@ type
     SrcBuffer: array [1..4096] of byte;
   end;
 
-
   glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr;
   glBitmap_libJPEG_dest_mgr = record
     pub: jpeg_destination_mgr;
@@ -3902,41 +5183,41 @@ type
     DestBuffer: array [1..4096] of byte;
   end;
 
-
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{
 procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
-//var
-//  Msg: String;
+var
+  Msg: String;
 begin
-//  SetLength(Msg, 256);
-//  cinfo^.err^.format_message(cinfo, pChar(Msg));
-
-//  Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
-
-//  cinfo^.global_state := 0;
-
-//  jpeg_abort(cinfo);
+  SetLength(Msg, 256);
+  cinfo^.err^.format_message(cinfo, pChar(Msg));
+  Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
+  cinfo^.global_state := 0;
+  jpeg_abort(cinfo);
 end;
+}
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{
 procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
-//var
-//  Msg: String;
+var
+  Msg: String;
 begin
-//  SetLength(Msg, 256);
-//  cinfo^.err^.format_message(cinfo, pChar(Msg));
-
-//  Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
-
-//  cinfo^.global_state := 0;
+  SetLength(Msg, 256);
+  cinfo^.err^.format_message(cinfo, pChar(Msg));
+  Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg);
+  cinfo^.global_state := 0;
 end;
+}
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{
 procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
 begin
 end;
+}
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
 var
   src: glBitmap_libJPEG_source_mgr_ptr;
@@ -3957,7 +5238,7 @@ begin
   result := true;
 end;
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl;
 var
   src: glBitmap_libJPEG_source_mgr_ptr;
@@ -3977,17 +5258,21 @@ begin
   end;
 end;
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{
 procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
 begin
 end;
+}
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+{
 procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
 begin
 end;
+}
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl;
 var
   dest: glBitmap_libJPEG_dest_mgr_ptr;
@@ -4003,10 +5288,10 @@ begin
     dest^.pub.free_in_buffer := Length(dest^.DestBuffer);
   end;
 
-  Result := True;
+  result := true;
 end;
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl;
 var
   Idx: Integer;
@@ -4021,22 +5306,22 @@ begin
       dest^.DestStream.Write(dest^.DestBuffer[Idx], 2);
 
       // leave
-      Break;
+      break;
     end else
       dest^.DestStream.Write(dest^.DestBuffer[Idx], 1);
   end;
 end;
 {$ENDIF}
 
-
 {$IFDEF GLB_SUPPORT_JPEG_READ}
-function TglBitmap.LoadJPEG(Stream: TStream): Boolean;
-{$IFDEF GLB_SDL_IMAGE}
+{$IF DEFINED(GLB_SDL_IMAGE)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
 var
   Surface: PSDL_Surface;
   RWops: PSDL_RWops;
 begin
-  Result := False;
+  result := false;
 
   RWops := glBitmapCreateRWops(Stream);
   try
@@ -4044,7 +5329,7 @@ begin
       Surface := IMG_LoadJPG_RW(RWops);
       try
         AssignFromSurface(Surface);
-        Result := True;
+        result := true;
       finally
         SDL_FreeSurface(Surface);
       end;
@@ -4053,8 +5338,10 @@ begin
     SDL_FreeRW(RWops);
   end;
 end;
-{$ENDIF}
-{$IFDEF GLB_LIB_JPEG}
+
+{$ELSEIF DEFINED(GLB_LIB_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
 var
   StreamPos: Int64;
   Temp: array[0..1]of Byte;
@@ -4069,7 +5356,7 @@ var
   pTemp: pByte;
   Row: Integer;
 begin
-  Result := False;
+  result := false;
 
   if not init_libJPEG then
     raise Exception.Create('LoadJPG - unable to initialize libJPEG.');
@@ -4114,7 +5401,7 @@ begin
       jpeg.global_state := DSTATE_START;
 
       // read header of jpeg
-      jpeg_read_header(@jpeg, False);
+      jpeg_read_header(@jpeg, false);
 
       // setting output parameter
       case jpeg.jpeg_color_space of
@@ -4152,7 +5439,7 @@ begin
 
         SetDataPointer(pImage, IntFormat, TempWidth, TempHeight);
 
-        Result := True;
+        result := true;
       except
         FreeMem(pImage);
         raise;
@@ -4162,15 +5449,17 @@ begin
     quit_libJPEG;
   end;
 end;
-{$ENDIF}
-{$IFDEF GLB_DELPHI_JPEG}
+
+{$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
 var
   bmp: TBitmap;
   jpg: TJPEGImage;
   StreamPos: Int64;
   Temp: array[0..1]of Byte;
 begin
-  Result := False;
+  result := false;
 
   // reading first two bytes to test file and set cursor back to begin
   StreamPos := Stream.Position;
@@ -4185,7 +5474,7 @@ begin
       try
         jpg.LoadFromStream(Stream);
         bmp.Assign(jpg);
-        Result := AssignFromBitmap(bmp);
+        result := AssignFromBitmap(bmp);
       finally
         jpg.Free;
       end;
@@ -4194,2445 +5483,1381 @@ begin
     end;
   end;
 end;
+{$IFEND}
 {$ENDIF}
-{$ENDIF}
-
-
-const
-  BMP_MAGIC          = $4D42;
 
-  BMP_COMP_RGB       = 0;
-  BMP_COMP_RLE8      = 1;
-  BMP_COMP_RLE4      = 2;
-  BMP_COMP_BITFIELDS = 3;
+{$IFDEF GLB_SUPPORT_JPEG_WRITE}
+{$IF DEFEFINED(GLB_LIB_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveJPEG(Stream: TStream);
+var
+  jpeg: jpeg_compress_struct;
+  jpeg_err: jpeg_error_mgr;
+  Row: Integer;
+  pTemp, pTemp2: pByte;
 
-type
-  TBMPHeader = packed record
-    bfType: Word;
-    bfSize: Cardinal;
-    bfReserved1: Word;
-    bfReserved2: Word;
-    bfOffBits: Cardinal;
+  procedure CopyRow(pDest, pSource: pByte);
+  var
+    X: Integer;
+  begin
+    for X := 0 to Width - 1 do begin
+      pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
+      pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
+      pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
+      Inc(pDest, 3);
+      Inc(pSource, 3);
+    end;
   end;
 
-  TBMPInfo = packed record
-    biSize: Cardinal;
-    biWidth: Longint;
-    biHeight: Longint;
-    biPlanes: Word;
-    biBitCount: Word;
-    biCompression: Cardinal;
-    biSizeImage: Cardinal;
-    biXPelsPerMeter: Longint;
-    biYPelsPerMeter: Longint;
-    biClrUsed: Cardinal;
-    biClrImportant: Cardinal;
-  end;
-
-  TBMPInfoOS = packed record
-    biSize: Cardinal;
-    biWidth: Longint;
-    biHeight: Longint;
-    biPlanes: Word;
-    biBitCount: Word;
-  end;
-
-//  TBMPPalette = record
-//    case Boolean of
-//      True : (Colors: array[Byte] of TRGBQUAD);
-//      False: (redMask, greenMask, blueMask: Cardinal);
-//  end;
-
-function TglBitmap.LoadBMP(Stream: TStream): Boolean;
-var
-  StreamPos: Int64;
-  Header: TBMPHeader;
-  Info: TBMPInfo;
-  NewImage, pData: pByte;
-
-  Format: TglBitmapInternalFormat;
-  LineSize, Padding, LineIdx: Integer;
-  RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
-
-  PaddingBuff: Cardinal;
-
-
-  function GetLineWidth : Integer;
-  begin
-    Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
-  end;
-
-  
-begin
-  Result := False;
-
-  RedMask := 0;
-  GreenMask := 0;
-  BlueMask := 0;
-  Format := ifEmpty;
-
-  // Header
-  StreamPos := Stream.Position;
-  Stream.Read(Header, SizeOf(Header));
-
-  if Header.bfType = BMP_MAGIC then begin
-    Stream.Read(Info, SizeOf(Info));
-
-    // Check for Compression
-    if Info.biCompression <> BMP_COMP_RGB then begin
-      if Info.biCompression = BMP_COMP_BITFIELDS then begin
-        // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!)
-        if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin
-          Stream.Read(RedMask,   SizeOf(Cardinal));
-          Stream.Read(GreenMask, SizeOf(Cardinal));
-          Stream.Read(BlueMask,  SizeOf(Cardinal));
-          Stream.Read(AlphaMask, SizeOf(Cardinal));
-        end;
-      end else begin
-        // RLE compression is unsupported
-        Stream.Position := StreamPos;
-
-        Exit;
-      end;
-    end;
-
-    // Skip palette
-    if Info.biBitCount < 16 then
-      Stream.Position := Stream.Position + Info.biClrUsed * 4;
-
-    // Jump to the data
-    Stream.Position := StreamPos + Header.bfOffBits;
-
-    // Select Format
-    case Info.biBitCount of
-      8 : Format := ifLuminance;
-      16:
-        begin
-          if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
-              Format := ifRGB5A1;
-          end else begin
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then
-              Format := ifLuminanceAlpha;
-
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA4) then
-              Format := ifRGBA4;
-
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifRGB5A1) then
-              Format := ifRGB5A1;
-
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then
-              Format := ifR5G6B5;
-          end;
-        end;
-      24: Format := ifBGR8;
-      32:
-        begin
-          if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin
-            Format := ifBGRA8;
-          end else begin
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA8) then
-              Format := ifRGBA8;
-
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then
-              Format := ifBGRA8;
-
-            if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGB10A2) then
-              Format := ifRGB10A2;
-          end;
-        end;
-    end;
-
-    if Format <> ifEmpty then begin
-       LineSize := Trunc(Info.biWidth * FormatGetSize(Format));
-      Padding := GetLineWidth - LineSize;
-
-      // copying data
-      GetMem(NewImage, Info.biHeight * LineSize);
-      try
-        FillChar(NewImage^, Info.biHeight * LineSize, $FF);
-
-        // Set pData to last Line
-        pData := NewImage;
-        Inc(pData, LineSize * (Info.biHeight -1));
-
-        // Copy Image Data
-        for LineIdx := 0 to Info.biHeight - 1 do begin
-          Stream.Read(pData^, LineSize);
-          Dec(pData, LineSize);
-
-          Stream.Read(PaddingBuff, Padding);
-        end;
-
-        // Set new Image
-        SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight);
-
-        Result := True;
-      except
-        FreeMem(NewImage);
-        raise;
-      end;
-    end;
-  end
-    else Stream.Position := StreamPos;
-end;
-
-
-const
-  DDS_MAGIC                   = $20534444;
-
-  // DDS_header.dwFlags
-  DDSD_CAPS                   = $00000001;
-  DDSD_HEIGHT                 = $00000002;
-  DDSD_WIDTH                  = $00000004;
-  DDSD_PITCH                  = $00000008;
-  DDSD_PIXELFORMAT            = $00001000;
-  DDSD_MIPMAPCOUNT            = $00020000;
-  DDSD_LINEARSIZE             = $00080000;
-  DDSD_DEPTH                  = $00800000;
-
-  // DDS_header.sPixelFormat.dwFlags
-  DDPF_ALPHAPIXELS            = $00000001;
-  DDPF_FOURCC                 = $00000004;
-  DDPF_INDEXED                = $00000020;
-  DDPF_RGB                    = $00000040;
-
-  // DDS_header.sCaps.dwCaps1
-  DDSCAPS_COMPLEX             = $00000008;
-  DDSCAPS_TEXTURE             = $00001000;
-  DDSCAPS_MIPMAP              = $00400000;
-
-  // DDS_header.sCaps.dwCaps2
-  DDSCAPS2_CUBEMAP            = $00000200;
-  DDSCAPS2_CUBEMAP_POSITIVEX  = $00000400;
-  DDSCAPS2_CUBEMAP_NEGATIVEX  = $00000800;
-  DDSCAPS2_CUBEMAP_POSITIVEY  = $00001000;
-  DDSCAPS2_CUBEMAP_NEGATIVEY  = $00002000;
-  DDSCAPS2_CUBEMAP_POSITIVEZ  = $00004000;
-  DDSCAPS2_CUBEMAP_NEGATIVEZ  = $00008000;
-  DDSCAPS2_VOLUME             = $00200000;
-
-  D3DFMT_DXT1                 = $31545844;
-  D3DFMT_DXT3                 = $33545844;
-  D3DFMT_DXT5                 = $35545844;
-
-type
-  TDDSPixelFormat = packed record
-    dwSize: Cardinal;
-    dwFlags: Cardinal;
-    dwFourCC: Cardinal;
-    dwRGBBitCount: Cardinal;
-    dwRBitMask: Cardinal;
-    dwGBitMask: Cardinal;
-    dwBBitMask: Cardinal;
-    dwAlphaBitMask: Cardinal;
-  end;
-
-  TDDSCaps = packed record
-    dwCaps1: Cardinal;
-    dwCaps2: Cardinal;
-    dwDDSX: Cardinal;
-    dwReserved: Cardinal;
-  end;
-
-  TDDSHeader = packed record
-    dwMagic: Cardinal;
-    dwSize: Cardinal;
-    dwFlags: Cardinal;
-    dwHeight: Cardinal;
-    dwWidth: Cardinal;
-    dwPitchOrLinearSize: Cardinal;
-    dwDepth: Cardinal;
-    dwMipMapCount: Cardinal;
-    dwReserved: array[0..10] of Cardinal;
-    PixelFormat: TDDSPixelFormat;
-    Caps: TDDSCaps;
-    dwReserved2: Cardinal;
-  end;
-
-procedure TglBitmap.SetCustomData(const aValue: Pointer);
-begin
-  if fCustomData = aValue then Exit;
-  fCustomData := aValue;
-end;
-
-procedure TglBitmap.SetCustomName(const aValue: String);
-begin
-  if fCustomName = aValue then Exit;
-  fCustomName := aValue;
-end;
-
-procedure TglBitmap.SetCustomNameW(const aValue: WideString);
-begin
-  if fCustomNameW = aValue then Exit;
-  fCustomNameW := aValue;
-end;
-
-procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
-begin
-  if fDeleteTextureOnFree = aValue then Exit;
-  fDeleteTextureOnFree := aValue;
-end;
-
-procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat);
-begin
-  if fFormat = aValue then Exit;
-  fFormat := aValue;
-end;
-
-procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean);
-begin
-  if fFreeDataAfterGenTexture = aValue then Exit;
-  fFreeDataAfterGenTexture := aValue;
-end;
-
-procedure TglBitmap.SetID(const aValue: Cardinal);
-begin
-  if fID = aValue then Exit;
-  fID := aValue;
-end;
-
-procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap);
-begin
-  if fMipMap = aValue then Exit;
-  fMipMap := aValue;
-end;
-
-procedure TglBitmap.SetTarget(const aValue: Cardinal);
-begin
-  if fTarget = aValue then Exit;
-  fTarget := aValue;
-end;
-
-function TglBitmap.LoadDDS(Stream: TStream): Boolean;
-var
-  Header: TDDSHeader;
-  StreamPos: Int64;
-  Y, LineSize: Cardinal;
-
-//  MipMapCount, X, Y, XSize, YSize: Cardinal;
-  RowSize: Cardinal;
-  NewImage, pData: pByte;
-  Format: TglBitmapInternalFormat;
-
-
-  function RaiseEx : Exception;
-  begin
-    Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
-  end;
-
-  
-  function GetInternalFormat: TglBitmapInternalFormat;
-  begin
-    with Header.PixelFormat do begin
-      // Compresses
-      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;
-        end;
-      end else
-
-      // RGB
-      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
-        case dwRGBBitCount of
-           8:
-            begin
-              if dwFlags and DDPF_ALPHAPIXELS > 0 then
-                Result := ifAlpha
-              else
-                Result := ifLuminance;
-            end;
-          16:
-            begin
-              if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
-                // Alpha
-                case GetBitSize(dwRBitMask) of
-                  5: Result := ifRGB5A1;
-                  4: Result := ifRGBA4;
-                else
-                  Result := ifLuminanceAlpha;
-                end;
-              end else begin
-                // no Alpha
-                Result := ifR5G6B5;
-              end;
-            end;
-          24:
-            begin
-              if dwRBitMask > dwBBitMask then
-                Result := ifBGR8
-              else
-                Result := ifRGB8;
-            end;
-          32:
-            begin
-              if GetBitSize(dwRBitMask) = 10 then
-                Result := ifRGB10A2
-              else
-
-              if dwRBitMask > dwBBitMask then
-                Result := ifBGRA8
-              else
-                Result := ifRGBA8;
-            end;
-          else
-            raise RaiseEx;
-        end;
-      end else
-        raise RaiseEx;
-    end;
-  end;
-
-begin
-  Result := False;
-
-  // Header
-  StreamPos := Stream.Position;
-  Stream.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
-    Stream.Position := StreamPos;
-    Exit;
-  end;
-
-  // Pixelformat
-//  if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0
-//    then MipMapCount := Header.dwMipMapCount
-//    else MipMapCount := 1;
-
-  Format := GetInternalFormat;
-  LineSize := Trunc(Header.dwWidth * FormatGetSize(Format));
-
-  GetMem(NewImage, Header.dwHeight * LineSize);
-  try
-    pData := NewImage;
-
-    // Compressed
-    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
-        Stream.Read(pData^, RowSize);
-        Inc(pData, 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
-        Stream.Read(pData^, RowSize);
-        Inc(pData, LineSize);
-      end;
-    end
-      else raise RaiseEx;
-
-    SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight);
-
-    Result := True;
-  except
-    FreeMem(NewImage);
-    raise;
-  end;
-end;
-
-
-type
-  TTGAHeader = packed record
-    ImageID: Byte;
-    ColorMapType: Byte;
-    ImageType: Byte;
-    ColorMapSpec: Array[0..4] of Byte;
-    OrigX: Word;
-    OrigY: Word;
-    Width: Word;
-    Height: Word;
-    Bpp: Byte;
-    ImageDes: Byte;
-  end;
-
-const
-  TGA_UNCOMPRESSED_RGB = 2;
-  TGA_UNCOMPRESSED_GRAY = 3;
-  TGA_COMPRESSED_RGB = 10;
-  TGA_COMPRESSED_GRAY = 11;
-
-
-
-function TglBitmap.LoadTGA(Stream: TStream): Boolean;
-var
-  Header: TTGAHeader;
-  NewImage, pData: PByte;
-  StreamPos: Int64;
-  PixelSize, LineSize, YStart, YEnd, YInc: Integer;
-  Format: TglBitmapInternalFormat;
-
-const
-  CACHE_SIZE = $4000;
-
-  procedure ReadUncompressed;
-  var
-    RowSize: Integer;
-  begin
-    RowSize := Header.Width * PixelSize;
-
-    // copy line by line
-    while YStart <> YEnd + YInc do begin
-      pData := NewImage;
-      Inc(pData, YStart * LineSize);
-
-      Stream.Read(pData^, RowSize);
-      Inc(YStart, YInc);
-    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;
-
-
-    procedure CheckLine;
-    begin
-      if LinePixelsRead >= HeaderWidth then begin
-        LinePixelsRead := 0;
-        pData := NewImage;
-        Inc(YStart, YInc);
-        Inc(pData, YStart * LineSize);
-      end;
-    end;
-
-
-    procedure CachedRead(var Buffer; Count: Integer);
-    var
-      BytesRead: Integer;
-    begin
-      if (CachePos + Count) > CacheSize then begin
-        BytesRead := 0;
-
-        // Read Data
-        if CacheSize - CachePos > 0 then begin
-          BytesRead := CacheSize - CachePos;
-
-          Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
-          Inc(CachePos, BytesRead);
-        end;
-
-        // Reload Data
-        CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position);
-        Stream.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);
-        end;
-      end else begin
-        Move(pByteArray(Cache)^[CachePos], Buffer, Count);
-        Inc(CachePos, Count);
-      end;
-    end;
-
-
-  begin
-    CacheSize := 0;
-    CachePos := 0;
-
-    HeaderWidth := Header.Width;
-    HeaderHeight := Header.Height;
-
-    GetMem(Cache, CACHE_SIZE); // 16K Buffer
-    try
-      ImgPixelsToRead := HeaderWidth * HeaderHeight;
-      ImgPixelsRead := 0;
-      LinePixelsRead := 0;
-
-      pData := NewImage;
-      Inc(pData, YStart * LineSize);
-
-      // Read until all Pixels
-      repeat
-        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);
-          end;
-        end;
-      until ImgPixelsRead >= ImgPixelsToRead;
-    finally
-      FreeMem(Cache)
-    end;
-  end;
-
-begin
-  Result := False;
-
-  // reading header to test file and set cursor back to begin
-  StreamPos := Stream.Position;
-  Stream.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
-      case Header.Bpp of
-         8: Format := ifAlpha;
-        16: Format := ifLuminanceAlpha;
-        24: Format := ifBGR8;
-        32: Format := ifBGRA8;
-        else
-          raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.');
-      end;
-
-      // skip image ID
-      if Header.ImageID <> 0 then
-        Stream.Position := Stream.Position + Header.ImageID;
-
-      PixelSize := Trunc(FormatGetSize(Format));
-      LineSize := Trunc(Header.Width * PixelSize);
-
-      GetMem(NewImage, LineSize * Header.Height);
-      try
-        // Row direction
-        if (Header.ImageDes and $20 > 0) then begin
-          YStart := 0;
-          YEnd := Header.Height -1;
-          YInc := 1;
-        end else begin
-          YStart := Header.Height -1;
-          YEnd := 0;
-          YInc := -1;
-        end;
-
-        // Read Image
-        case Header.ImageType of
-          TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
-            ReadUncompressed;
-          TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
-            ReadCompressed;
-        end;
-
-        SetDataPointer(NewImage, Format, Header.Width, Header.Height);
-
-        Result := True;
-      except
-        FreeMem(NewImage);
-        raise;
-      end;
-    end
-      else Stream.Position := StreamPos;
-  end
-    else Stream.Position := StreamPos;
-end;
-
-
-{$IFDEF GLB_SUPPORT_PNG_WRITE}
-{$IFDEF GLB_LIB_PNG}
-procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl;
-begin
-  TStream(png_get_io_ptr(png)).Write(buffer^, size);
-end;
-{$ENDIF}
-
-procedure TglBitmap.SavePNG(Stream: TStream);
-{$IFDEF GLB_LIB_PNG}
-var
-  png: png_structp;
-  png_info: png_infop;
-  png_rows: array of pByte;
-  LineSize: Integer;
-  ColorType: Integer;
-  Row: Integer;
-begin
-  if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  if not init_libPNG then
-    raise Exception.Create('SavePNG - unable to initialize libPNG.');
-
-  try
-    case FInternalFormat of
-      ifAlpha, ifLuminance, ifDepth8:
-        ColorType := PNG_COLOR_TYPE_GRAY;
-      ifLuminanceAlpha:
-        ColorType := PNG_COLOR_TYPE_GRAY_ALPHA;
-      ifBGR8, ifRGB8:
-        ColorType := PNG_COLOR_TYPE_RGB;
-      ifBGRA8, ifRGBA8:
-        ColorType := PNG_COLOR_TYPE_RGBA;
-      else
-        raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
-    end;
-
-    LineSize := Trunc(FormatGetSize(FInternalFormat) * Width);
-
-    // creating array for scanline
-    SetLength(png_rows, Height);
-    try
-      for Row := 0 to Height - 1 do begin
-        png_rows[Row] := Data;
-        Inc(png_rows[Row], Row * LineSize)
-      end;
-
-      // write struct
-      png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
-      if png = nil then
-        raise EglBitmapException.Create('SavePng - couldn''t create write struct.');
-
-      // create png info
-      png_info := png_create_info_struct(png);
-      if png_info = nil then begin
-        png_destroy_write_struct(@png, nil);
-        raise EglBitmapException.Create('SavePng - couldn''t create info struct.');
-      end;
-
-      // set read callback
-      png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil);
-
-      // set compression
-      png_set_compression_level(png, 6);
-
-      if InternalFormat in [ifBGR8, ifBGRA8] then
-        png_set_bgr(png);
-
-      // setup header
-      png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
-      // write info
-      png_write_info(png, png_info);
-
-      // write image data
-      png_write_image(png, @png_rows[0]);
-
-      // write end
-      png_write_end(png, png_info);
-
-      // destroy write struct
-      png_destroy_write_struct(@png, @png_info);
-    finally
-      SetLength(png_rows, 0);
-    end;
-  finally
-    quit_libPNG;
-  end;
-end;
-{$ENDIF}
-{$IFDEF GLB_PNGIMAGE}
-var
-  Png: TPNGObject;
-
-  pSource, pDest: pByte;
-  X, Y, PixSize: Integer;
-  ColorType: Cardinal;
-  Alpha: Boolean;
-
-  pTemp: pByte;
-  Temp: Byte;
-begin
-  if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then 
-    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  case FInternalFormat of
-    ifAlpha, ifLuminance, ifDepth8:
-      begin
-        ColorType := COLOR_GRAYSCALE;
-        PixSize := 1;
-        Alpha := False;
-      end;
-    ifLuminanceAlpha:
-      begin
-        ColorType := COLOR_GRAYSCALEALPHA;
-        PixSize := 1;
-        Alpha := True;
-      end;
-    ifBGR8, ifRGB8:
-      begin
-        ColorType := COLOR_RGB;
-        PixSize := 3;
-        Alpha := False;
-      end;
-    ifBGRA8, ifRGBA8:
-      begin
-        ColorType := COLOR_RGBALPHA;
-        PixSize := 3;
-        Alpha := True
-      end;
-    else
-      raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
-  end;
-
-  Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
-  try
-    // Copy ImageData
-    pSource := Data;
-    for Y := 0 to Height -1 do begin
-      pDest := png.ScanLine[Y];
-
-      for X := 0 to Width -1 do begin
-        Move(pSource^, pDest^, PixSize);
-
-        Inc(pDest, PixSize);
-        Inc(pSource, PixSize);
-
-        if Alpha then begin
-          png.AlphaScanline[Y]^[X] := pSource^;
-          Inc(pSource);
-        end;
-      end;
-
-      // convert RGB line to BGR
-      if InternalFormat in [ifRGB8, ifRGBA8] then begin
-        pTemp := png.ScanLine[Y];
-
-        for X := 0 to Width -1 do begin
-          Temp := pByteArray(pTemp)^[0];
-          pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2];
-          pByteArray(pTemp)^[2] := Temp;
-
-          Inc(pTemp, 3);
-        end;
-      end;
-    end;
-
-    // Save to Stream
-    Png.CompressionLevel := 6; 
-    Png.SaveToStream(Stream);
-  finally
-    FreeAndNil(Png);
-  end;
-end;
-{$ENDIF}
-{$ENDIF}
-
-
-procedure TglBitmap.SaveDDS(Stream: TStream);
-var
-  Header: TDDSHeader;
-  Pix: TglBitmapPixelData;
-begin
-  if not FormatIsUncompressed(InternalFormat) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  if InternalFormat = ifAlpha then
-    FormatPreparePixel(Pix, ifLuminance)
-  else
-    FormatPreparePixel(Pix, InternalFormat);
-
-  // Generell
-  FillChar(Header, SizeOf(Header), 0);
-
-  Header.dwMagic := DDS_MAGIC;
-  Header.dwSize := 124;
-  Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
-
-  if Width > 0 then begin
-    Header.dwWidth := Width;
-    Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
-  end;
-
-  if Height > 0 then begin
-    Header.dwHeight := Height;
-    Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
-  end;
-
-  Header.dwPitchOrLinearSize := fRowSize;
-  Header.dwMipMapCount := 1;
-
-  // Caps
-  Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
-
-  // Pixelformat
-  Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat);
-  Header.PixelFormat.dwFlags := DDPF_RGB;
-
-  if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha)
-    then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
-
-  Header.PixelFormat.dwRGBBitCount  := Trunc(FormatGetSize(InternalFormat) * 8);
-  Header.PixelFormat.dwRBitMask     := Pix.PixelDesc.RedRange   shl Pix.PixelDesc.RedShift;
-  Header.PixelFormat.dwGBitMask     := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift;
-  Header.PixelFormat.dwBBitMask     := Pix.PixelDesc.BlueRange  shl Pix.PixelDesc.BlueShift;
-  Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift;
-
-  // Write
-  Stream.Write(Header, SizeOf(Header));
-
-  Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat));
-end;
-
-
-procedure TglBitmap.SaveTGA(Stream: TStream);
-var
-  Header: TTGAHeader;
-  Size: Integer;
-  pTemp: pByte;
-
-
-  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;
-
-
-begin
-  if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then 
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  FillChar(Header, SizeOf(Header), 0);
-
-  case InternalFormat of
-    ifAlpha, ifLuminance, ifDepth8:
-      begin
-        Header.ImageType := TGA_UNCOMPRESSED_GRAY;
-        Header.Bpp := 8;
-      end;
-    ifLuminanceAlpha:
-      begin
-        Header.ImageType := TGA_UNCOMPRESSED_GRAY;
-        Header.Bpp := 16;
-      end;
-    ifRGB8, ifBGR8:
-      begin
-        Header.ImageType := TGA_UNCOMPRESSED_RGB;
-        Header.Bpp := 24;
-      end;
-    ifRGBA8, ifBGRA8:
-      begin
-        Header.ImageType := TGA_UNCOMPRESSED_RGB;
-        Header.Bpp := 32;
-      end;
-    else
-      raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT);
-  end;
-
-  Header.Width := Width;
-  Header.Height := Height;
-  Header.ImageDes := $20;
-
-  if FormatHasAlpha(InternalFormat) then
-    Header.ImageDes := Header.ImageDes or $08;
-
-  Stream.Write(Header, SizeOf(Header));
-
-  // convert RGB(A) to BGR(A)
-  Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat);
-  if InternalFormat in [ifRGB8, ifRGBA8] then begin
-    GetMem(pTemp, Size);
-  end else
-    pTemp := Data;
-
-  try
-    // convert data
-    if InternalFormat in [ifRGB8, ifRGBA8] then begin
-      Move(Data^, pTemp^, Size);
-      ConvertData(pTemp);
-    end;
-
-    // write data
-    Stream.Write(pTemp^, Size);
-  finally
-    // free tempdata
-    if InternalFormat in [ifRGB8, ifRGBA8] then
-      FreeMem(pTemp);
-  end;
-end;
-
-
-{$IFDEF GLB_SUPPORT_JPEG_WRITE}
-procedure TglBitmap.SaveJPEG(Stream: TStream);
-{$IFDEF GLB_LIB_JPEG}
-var
-  jpeg: jpeg_compress_struct;
-  jpeg_err: jpeg_error_mgr;
-  Row: Integer;
-  pTemp, pTemp2: pByte;
-
-
-  procedure CopyRow(pDest, pSource: pByte);
-  var
-    X: Integer;
-  begin
-    for X := 0 to Width - 1 do begin
-      pByteArray(pDest)^[0] := pByteArray(pSource)^[2];
-      pByteArray(pDest)^[1] := pByteArray(pSource)^[1];
-      pByteArray(pDest)^[2] := pByteArray(pSource)^[0];
-
-      Inc(pDest, 3);
-      Inc(pSource, 3); 
-    end;
-  end;
-
-begin
-  if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  if not init_libJPEG then
-    raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
-
-  try
-    FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
-    FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
-
-    // error managment
-    jpeg.err := jpeg_std_error(@jpeg_err);
-    jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
-    jpeg_err.output_message := glBitmap_libJPEG_output_message;
-
-    // compression struct
-    jpeg_create_compress(@jpeg);
-
-    // allocation space for streaming methods
-    jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
-
-    // seeting up custom functions
-    with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
-      pub.init_destination    := glBitmap_libJPEG_init_destination;
-      pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
-      pub.term_destination    := glBitmap_libJPEG_term_destination;
-
-      pub.next_output_byte  := @DestBuffer[1];
-      pub.free_in_buffer    := Length(DestBuffer);
-
-      DestStream := Stream;
-    end;
-
-    // very important state
-    jpeg.global_state := CSTATE_START;
-
-    jpeg.image_width := Width;
-    jpeg.image_height := Height;
-    case InternalFormat of
-      ifAlpha, ifLuminance, ifDepth8:
-        begin
-          jpeg.input_components := 1;
-          jpeg.in_color_space := JCS_GRAYSCALE;
-        end;
-      ifRGB8, ifBGR8:
-        begin
-          jpeg.input_components := 3;
-          jpeg.in_color_space := JCS_RGB;
-        end;
-    end;
-
-    // setting defaults
-    jpeg_set_defaults(@jpeg);
-
-    // compression quality
-    jpeg_set_quality(@jpeg, 95, True);
-
-    // start compression
-    jpeg_start_compress(@jpeg, true);
-
-    // write rows
-    pTemp := Data;
-
-    // initialing row  
-    if InternalFormat = ifBGR8 then
-      GetMem(pTemp2, fRowSize)
-    else
-      pTemp2 := pTemp;
-
-    try
-      for Row := 0 to jpeg.image_height -1 do begin
-        // prepare row
-        if InternalFormat = ifBGR8 then
-          CopyRow(pTemp2, pTemp)
-        else
-          pTemp2 := pTemp;
-
-        // write row
-        jpeg_write_scanlines(@jpeg, @pTemp2, 1);
-        inc(pTemp, fRowSize);
-      end;
-    finally
-      // free memory
-      if InternalFormat = ifBGR8 then
-        FreeMem(pTemp2);
-    end;
-
-    // finish compression
-    jpeg_finish_compress(@jpeg);
-
-    // destroy compression
-    jpeg_destroy_compress(@jpeg);
-  finally
-    quit_libJPEG;
-  end;
-end;
-{$ENDIF}
-{$IFDEF GLB_DELPHI_JPEG}
-var
-  Bmp: TBitmap;
-  Jpg: TJPEGImage;
-begin
-  if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then 
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  Bmp := TBitmap.Create;
-  try
-    Jpg := TJPEGImage.Create;
-    try
-      AssignToBitmap(Bmp);
-
-      if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
-        Jpg.Grayscale := True;
-        Jpg.PixelFormat := jf8Bit;
-      end;
-
-      Jpg.Assign(Bmp);
-
-      Jpg.SaveToStream(Stream);
-    finally
-      FreeAndNil(Jpg);
-    end;
-  finally
-    FreeAndNil(Bmp);
-  end;
-end;
-{$ENDIF}
-{$ENDIF}
-
-
-procedure TglBitmap.SaveBMP(Stream: TStream);
-var
-  Header: TBMPHeader;
-  Info: TBMPInfo;
-  pData, pTemp: pByte;
-
-  PixelFormat: TglBitmapPixelData;
-  ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
-  Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
-
-  PaddingBuff: Cardinal;
-
-
-  function GetLineWidth : Integer;
-  begin
-    Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
-  end;
-
-
-begin
-  if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat));
-
-  Header.bfType := BMP_MAGIC;
-  Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize;
-  Header.bfReserved1 := 0;
-  Header.bfReserved2 := 0;
-  Header.bfOffBits := SizeOf(Header) + SizeOf(Info);
-
-  FillChar(Info, SizeOf(Info), 0);
-  Info.biSize := SizeOf(Info);
-  Info.biWidth := Width;
-  Info.biHeight := Height;
-  Info.biPlanes := 1;
-  Info.biCompression := BMP_COMP_RGB;
-  Info.biSizeImage := ImageSize;
-  case InternalFormat of
-    ifAlpha, ifLuminance, ifDepth8:
-      begin
-        Info.biBitCount :=  8;
-
-        Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
-        Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
-
-        Info.biClrUsed := 256;
-        Info.biClrImportant := 256;
-      end;
-    ifLuminanceAlpha, ifRGBA4, ifR5G6B5, ifRGB5A1:
-      begin
-        Info.biBitCount := 16;
-        Info.biCompression := BMP_COMP_BITFIELDS;
-      end;
-    ifBGR8, ifRGB8:
-      Info.biBitCount := 24;
-    ifBGRA8, ifRGBA8, ifRGB10A2:
-      begin
-        Info.biBitCount := 32;
-        Info.biCompression := BMP_COMP_BITFIELDS;
-      end;
-    else
-      raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT);
-  end;
-  Info.biXPelsPerMeter := 2835;
-  Info.biYPelsPerMeter := 2835;
-
-  // 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);
-
-    FormatPreparePixel(PixelFormat, InternalFormat);
-
-    with PixelFormat.PixelDesc do begin
-      RedMask   := RedRange   shl RedShift;
-      GreenMask := GreenRange shl GreenShift;
-      BlueMask  := BlueRange  shl BlueShift;
-      AlphaMask := AlphaRange shl AlphaShift;
-    end;
-  end;
-
-  // headers
-  Stream.Write(Header, SizeOf(Header));
-  Stream.Write(Info, SizeOf(Info));
-
-  // colortable
-  if Info.biBitCount = 8 then begin
-    Temp := 0;
-    for ColorIdx := Low(Byte) to High(Byte) do begin
-      Stream.Write(Temp, 4);
-      Temp := Temp + $00010101;
-    end;
-  end;
-
-  // bitmasks
-  if Info.biCompression = BMP_COMP_BITFIELDS then begin
-    Stream.Write(RedMask, SizeOf(Cardinal));
-    Stream.Write(GreenMask, SizeOf(Cardinal));
-    Stream.Write(BlueMask, SizeOf(Cardinal));
-    Stream.Write(AlphaMask, SizeOf(Cardinal));
-  end;
-
-  // image data
-  LineSize := Trunc(Width * FormatGetSize(InternalFormat));
-  Padding := GetLineWidth - LineSize;
-  PaddingBuff := 0;
-
-  pData := Data;
-  Inc(pData, (Height -1) * LineSize);
-
-  // prepare row buffer. But only for RGB because RGBA supports color masks
-  // so it's possible to change color within the image.
-  if InternalFormat = ifRGB8 then
-    GetMem(pTemp, fRowSize)
-  else
-    pTemp := nil;
-
-  try
-    // write image data
-    for LineIdx := 0 to Height - 1 do begin
-      // preparing row
-      if InternalFormat = ifRGB8 then begin
-        Move(pData^, pTemp^, fRowSize);
-        SwapRGB(pTemp, Width, False);
-      end else
-        pTemp := pData;
-
-      Stream.Write(pTemp^, LineSize);
-
-      Dec(pData, LineSize);
-
-      if Padding > 0 then
-        Stream.Write(PaddingBuff, Padding);
-    end;
-  finally
-    // destroy row buffer
-    if InternalFormat = ifRGB8 then
-      FreeMem(pTemp);
-  end;
-end;
-
-
-procedure TglBitmap.Bind(EnableTextureUnit: Boolean);
-begin
-  if EnableTextureUnit then
-    glEnable(Target);
-
-  if ID > 0 then
-    glBindTexture(Target, ID);
-end;
-
-
-procedure TglBitmap.Unbind(DisableTextureUnit: Boolean);
-begin
-  if DisableTextureUnit then
-    glDisable(Target);
-
-  glBindTexture(Target, 0);
-end;
-
-
-procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition;
-  var Pixel: TglBitmapPixelData);
-begin
-  if Assigned (fGetPixelFunc) then
-    fGetPixelFunc(Pos, Pixel);
-end;
-
-
-procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition;
-  const Pixel: TglBitmapPixelData);
-begin
-  if Assigned (fSetPixelFunc) then
-    fSetPixelFunc(Pos, Pixel);
-end;
-
-
-procedure TglBitmap.CreateID;
-begin
-  // Generate Texture
-  if ID <> 0 then
-    glDeleteTextures(1, @ID);
-
-  glGenTextures(1, @ID);
-
-  Bind(False);
-end;
-
-
-procedure TglBitmap.SetupParameters(var BuildWithGlu: Boolean);
-begin
-  // Set up parameters
-  SetWrap(fWrapS, fWrapT, fWrapR);
-  SetFilter(fFilterMin, fFilterMag);
-  SetAnisotropic(fAnisotropic);
-  SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]);
-
-  // Mip Maps generation Mode
-  BuildWithGlu := False;
-
-  if (MipMap = mmMipmap) then begin
-    if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then
-      glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE)
-    else
-      BuildWithGlu := True;
-  end else
-  if (MipMap = mmMipmapGlu) then
-    BuildWithGlu := True;
-end;
-
-
-procedure TglBitmap.SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True);
-
-  procedure Check12;
-  begin
-    if not GL_VERSION_1_2 then
-      raise EglBitmapUnsupportedInternalFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.');
-  end;
-
-begin
-  glType := GL_UNSIGNED_BYTE;
-
-  // selecting Format
-  case DataFormat of
-    ifAlpha:
-      glFormat := GL_ALPHA;
-    ifLuminance:
-      glFormat := GL_LUMINANCE;
-    ifDepth8:
-      glFormat := GL_DEPTH_COMPONENT;
-    ifLuminanceAlpha:
-      glFormat := GL_LUMINANCE_ALPHA;
-    ifBGR8:
-      begin
-        if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
-          glFormat := GL_BGR;
-        end else begin
-          if CanConvertImage then
-            ConvertTo(ifRGB8);
-          glFormat := GL_RGB;
-        end;
-      end;
-    ifBGRA8:
-      begin
-        if (GL_VERSION_1_2 or GL_EXT_bgra) then begin
-          glFormat := GL_BGRA;
-        end else begin
-          if CanConvertImage then
-            ConvertTo(ifRGBA8);
-          glFormat := GL_RGBA;
-        end;
-      end;
-    ifRGB8:
-      glFormat := GL_RGB;
-    ifRGBA8:
-      glFormat := GL_RGBA;
-    ifRGBA4:
-      begin
-        Check12;
-        glFormat := GL_BGRA;
-        glType := GL_UNSIGNED_SHORT_4_4_4_4_REV; 
-      end;
-    ifRGB5A1:
-      begin
-        Check12;
-        glFormat := GL_BGRA;
-        glType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
-      end;
-    ifRGB10A2:
-      begin
-        Check12;
-        glFormat := GL_BGRA;
-        glType := GL_UNSIGNED_INT_2_10_10_10_REV;
-      end;
-    ifR5G6B5:
-      begin
-        Check12;
-        glFormat := GL_RGB;
-        glType := GL_UNSIGNED_SHORT_5_6_5;
-      end;
-    else
-      glFormat := 0;
-  end;
-
-  // Selecting InternalFormat
-  case DataFormat of
-    ifDXT1, ifDXT3, ifDXT5:
-      begin
-        if GL_EXT_texture_compression_s3tc then begin
-          case DataFormat of
-            ifDXT1:
-              glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
-            ifDXT3:
-              glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
-            ifDXT5:
-              glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
-          end;
-        end else begin
-          // Compression isn't supported so convert to RGBA
-          if CanConvertImage then
-            ConvertTo(ifRGBA8);
-          glFormat := GL_RGBA;
-          glInternalFormat := GL_RGBA8;
-        end;
-      end;
-    ifAlpha:
-      begin
-        case Format of
-          tf4BitsPerChanel:
-            glInternalFormat := GL_ALPHA4;
-          tf8BitsPerChanel:
-            glInternalFormat := GL_ALPHA8;
-          tfCompressed:
-            begin
-              if (GL_ARB_texture_compression or GL_VERSION_1_3) then
-                glInternalFormat := GL_COMPRESSED_ALPHA
-              else
-                glInternalFormat := GL_ALPHA;
-            end;
-          else
-            glInternalFormat := GL_ALPHA;
-        end;
-      end;
-    ifLuminance:
-      begin
-        case Format of
-          tf4BitsPerChanel:
-            glInternalFormat := GL_LUMINANCE4;
-          tf8BitsPerChanel:
-            glInternalFormat := GL_LUMINANCE8;
-          tfCompressed:
-            begin
-              if (GL_ARB_texture_compression or GL_VERSION_1_3) then
-                glInternalFormat := GL_COMPRESSED_LUMINANCE
-              else
-                glInternalFormat := GL_LUMINANCE;
-            end;
-          else
-            glInternalFormat := GL_LUMINANCE;
-        end;
-      end;
-    ifDepth8:
-      begin
-        glInternalFormat := GL_DEPTH_COMPONENT;
-      end;
-    ifLuminanceAlpha:
-      begin
-        case Format of
-          tf4BitsPerChanel:
-            glInternalFormat := GL_LUMINANCE4_ALPHA4;
-          tf8BitsPerChanel:
-            glInternalFormat := GL_LUMINANCE8_ALPHA8;
-          tfCompressed:
-            begin
-              if (GL_ARB_texture_compression or GL_VERSION_1_3) then
-                glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA
-              else
-                glInternalFormat := GL_LUMINANCE_ALPHA;
-            end;
-          else
-            glInternalFormat := GL_LUMINANCE_ALPHA;
-        end;
-      end;
-    ifBGR8, ifRGB8:
-      begin
-        case Format of
-          tf4BitsPerChanel:
-            glInternalFormat := GL_RGB4;
-          tf8BitsPerChanel:
-            glInternalFormat := GL_RGB8;
-          tfCompressed:
-            begin
-              if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
-                glInternalFormat := GL_COMPRESSED_RGB
-              end else begin
-                if (GL_EXT_texture_compression_s3tc) then
-                  glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT
-                else
-                  glInternalFormat := GL_RGB;
-              end;
-            end;
-          else
-            glInternalFormat := GL_RGB;
-        end;
-      end;
-    ifBGRA8, ifRGBA8, ifRGBA4, ifRGB5A1, ifRGB10A2, ifR5G6B5:
-      begin
-        case Format of
-          tf4BitsPerChanel:
-            glInternalFormat := GL_RGBA4;
-          tf8BitsPerChanel:
-            glInternalFormat := GL_RGBA8;
-          tfCompressed:
-            begin
-              if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin
-                glInternalFormat := GL_COMPRESSED_RGBA
-              end else begin
-                if (GL_EXT_texture_compression_s3tc) then
-                  glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
-                else
-                  glInternalFormat := GL_RGBA;
-              end;
-            end;
-          else
-            glInternalFormat := GL_RGBA;
-        end;
-      end;
-  end;
-end;
-
-
-function TglBitmap.FlipHorz: Boolean;
-begin
-  Result := False;
-end;
-
-
-function TglBitmap.FlipVert: Boolean;
-begin
-  Result := False;
-end;
+begin
+  if not (ftJPEG in FormatGetSupportedFiles(Format)) then
+    raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
 
+  if not init_libJPEG then
+    raise Exception.Create('SaveJPG - unable to initialize libJPEG.');
 
-procedure TglBitmap.FreeData;
-begin
-  SetDataPointer(nil, ifEmpty);
-end;
+  try
+    FillChar(jpeg, SizeOf(jpeg_compress_struct), $00);
+    FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
 
+    // error managment
+    jpeg.err := jpeg_std_error(@jpeg_err);
+    jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
+    jpeg_err.output_message := glBitmap_libJPEG_output_message;
 
-procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec);
-type
-  PglBitmapPixelData = ^TglBitmapPixelData;
-begin
-  with FuncRec do begin
-    Dest.Red   := PglBitmapPixelData(CustomData)^.Red;
-    Dest.Green := PglBitmapPixelData(CustomData)^.Green;
-    Dest.Blue  := PglBitmapPixelData(CustomData)^.Blue;
-    Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha;
-  end;
-end;
+    // compression struct
+    jpeg_create_compress(@jpeg);
 
+    // allocation space for streaming methods
+    jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr));
 
-procedure TglBitmap.FillWithColor(Red, Green, Blue: Byte; Alpha: Byte);
-begin
-  FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF);
-end;
+    // seeting up custom functions
+    with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin
+      pub.init_destination    := glBitmap_libJPEG_init_destination;
+      pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer;
+      pub.term_destination    := glBitmap_libJPEG_term_destination;
 
+      pub.next_output_byte  := @DestBuffer[1];
+      pub.free_in_buffer    := Length(DestBuffer);
 
-procedure TglBitmap.FillWithColorFloat(Red, Green, Blue: Single; Alpha: Single);
-var
-  PixelData: TglBitmapPixelData;
-begin
-  FormatPreparePixel(PixelData, InternalFormat);
+      DestStream := Stream;
+    end;
 
-  PixelData.Red   := Max(0, Min(PixelData.PixelDesc.RedRange,   Trunc(PixelData.PixelDesc.RedRange   * Red)));
-  PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green)));
-  PixelData.Blue  := Max(0, Min(PixelData.PixelDesc.BlueRange,  Trunc(PixelData.PixelDesc.BlueRange  * Blue)));
-  PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha)));
+    // very important state
+    jpeg.global_state := CSTATE_START;
+    jpeg.image_width  := Width;
+    jpeg.image_height := Height;
+    case InternalFormat of
+      ifAlpha, ifLuminance, ifDepth8: begin
+        jpeg.input_components := 1;
+        jpeg.in_color_space := JCS_GRAYSCALE;
+      end;
+      ifRGB8, ifBGR8: begin
+        jpeg.input_components := 3;
+        jpeg.in_color_space := JCS_RGB;
+      end;
+    end;
 
-  AddFunc(glBitmapFillWithColorFunc, False, @PixelData);
-end;
+    jpeg_set_defaults(@jpeg);
+    jpeg_set_quality(@jpeg, 95, true);
+    jpeg_start_compress(@jpeg, true);
+    pTemp := Data;
 
+    if InternalFormat = ifBGR8 then
+      GetMem(pTemp2, fRowSize)
+    else
+      pTemp2 := pTemp;
 
-procedure TglBitmap.FillWithColorRange(Red, Green, Blue: Cardinal;
-  Alpha: Cardinal);
-var
-  PixelData: TglBitmapPixelData;
-begin
-  FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat));
+    try
+      for Row := 0 to jpeg.image_height -1 do begin
+        // prepare row
+        if InternalFormat = ifBGR8 then
+          CopyRow(pTemp2, pTemp)
+        else
+          pTemp2 := pTemp;
 
-  FillWithColorFloat(
-    Red   / PixelData.PixelDesc.RedRange,
-    Green / PixelData.PixelDesc.GreenRange,
-    Blue  / PixelData.PixelDesc.BlueRange,
-    Alpha / PixelData.PixelDesc.AlphaRange);
+        // write row
+        jpeg_write_scanlines(@jpeg, @pTemp2, 1);
+        inc(pTemp, fRowSize);
+      end;
+    finally
+      // free memory
+      if InternalFormat = ifBGR8 then
+        FreeMem(pTemp2);
+    end;
+    jpeg_finish_compress(@jpeg);
+    jpeg_destroy_compress(@jpeg);
+  finally
+    quit_libJPEG;
+  end;
 end;
 
-
-procedure TglBitmap.SetAnisotropic(const aValue: Integer);
+{$ELSEIF DEFINED(GLB_DELPHI_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveJPEG(Stream: TStream);
 var
-  MaxAniso: Integer;
+  Bmp: TBitmap;
+  Jpg: TJPEGImage;
 begin
-  fAnisotropic := Value;
-
-  if (ID > 0) then begin
-    if GL_EXT_texture_filter_anisotropic then begin
-      if fAnisotropic > 0 then begin
-        Bind(False);
-
-        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAniso);
-
-        if Value > MaxAniso then
-          fAnisotropic := MaxAniso;
+  if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then
+    raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
 
-        glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic);
+  Bmp := TBitmap.Create;
+  try
+    Jpg := TJPEGImage.Create;
+    try
+      AssignToBitmap(Bmp);
+      if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin
+        Jpg.Grayscale := true;
+        Jpg.PixelFormat := jf8Bit;
       end;
-    end else begin
-      fAnisotropic := 0;
+      Jpg.Assign(Bmp);
+      Jpg.SaveToStream(Stream);
+    finally
+      FreeAndNil(Jpg);
     end;
+  finally
+    FreeAndNil(Bmp);
   end;
 end;
+{$ENDIF}
+{$ENDIF}
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const
+  BMP_MAGIC          = $4D42;
 
-procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapInternalFormat);
-begin
-  if InternalFormat <> Value then begin
-    if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then
-      raise EglBitmapUnsupportedInternalFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  BMP_COMP_RGB       = 0;
+  BMP_COMP_RLE8      = 1;
+  BMP_COMP_RLE4      = 2;
+  BMP_COMP_BITFIELDS = 3;
 
-    // Update whatever
-    SetDataPointer(Data, Value);
+type
+  TBMPHeader = packed record
+    bfType: Word;
+    bfSize: Cardinal;
+    bfReserved1: Word;
+    bfReserved2: Word;
+    bfOffBits: Cardinal;
   end;
-end;
-
-
-function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean;
-  CustomData: Pointer): boolean;
-begin
-  Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData);
-end;
 
+  TBMPInfo = packed record
+    biSize: Cardinal;
+    biWidth: Longint;
+    biHeight: Longint;
+    biPlanes: Word;
+    biBitCount: Word;
+    biCompression: Cardinal;
+    biSizeImage: Cardinal;
+    biXPelsPerMeter: Longint;
+    biYPelsPerMeter: Longint;
+    biClrUsed: Cardinal;
+    biClrImportant: Cardinal;
+  end;
 
-function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction;
-  CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer): boolean;
-var
-  pDest, NewImage, pSource: pByte;
-  TempHeight, TempWidth: Integer;
-  MapFunc: TglBitmapMapFunc;
-  UnMapFunc: TglBitmapUnMapFunc;
-
-  FuncRec: TglBitmapFunctionRec;
-begin
-  Assert(Assigned(Data));
-  Assert(Assigned(Source));
-  Assert(Assigned(Source.Data));
+  (* TODO: delete?
+  TBMPInfoOS = packed record
+    biSize: Cardinal;
+    biWidth: Longint;
+    biHeight: Longint;
+    biPlanes: Word;
+    biBitCount: Word;
+  end;
+  *)
 
-  Result := False;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadBMP(const aStream: TStream): Boolean;
 
-  if Assigned (Source.Data) and FormatIsUncompressed(Format) and
-     ((Source.Height > 0) or (Source.Width > 0)) then begin
+  //////////////////////////////////////////////////////////////////////////////////////////////////
+  function ReadInfo(var aInfo: TBMPInfo; var aMask: TglBitmapColorRec): TglBitmapFormat;
+  begin
+    result := tfEmpty;
+    aStream.Read(aInfo, SizeOf(aInfo));
+    FillChar(aMask, SizeOf(aMask), 0);
+
+    //Read Compression
+    case aInfo.biCompression of
+      BMP_COMP_RLE4,
+      BMP_COMP_RLE8: begin
+        raise EglBitmapException.Create('RLE compression is not supported');
+      end;
+      BMP_COMP_BITFIELDS: begin
+        if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin
+          aStream.Read(aMask.r, SizeOf(aMask.r));
+          aStream.Read(aMask.g, SizeOf(aMask.g));
+          aStream.Read(aMask.b, SizeOf(aMask.b));
+          aStream.Read(aMask.a, SizeOf(aMask.a));
+        end else
+          raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats');
+      end;
+    end;
 
-    // inkompatible Formats so CreateTemp
-    if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then
-      CreateTemp := True;
+    //get suitable format
+    case aInfo.biBitCount of
+       8: result := tfLuminance8;
+      16: result := tfBGR5;
+      24: result := tfBGR8;
+      32: result := tfBGRA8;
+    end;
+  end;
 
-    // Values
-    TempHeight := Max(1, Source.Height);
-    TempWidth := Max(1, Source.Width);
+  function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TColorTableFormat;
+  var
+    i, c: Integer;
+    ColorTable: TColorTable;
+  begin
+    result := nil;
+    if (aInfo.biBitCount >= 16) then
+      exit;
+    aFormat := tfLuminance8;
+    c := aInfo.biClrUsed;
+    if (c = 0) then
+      c := 1 shl aInfo.biBitCount;
+    SetLength(ColorTable, c);
+    for i := 0 to c-1 do begin
+      aStream.Read(ColorTable[i], SizeOf(TColorTableEnty));
+      if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then
+        aFormat := tfRGB8;
+    end;
 
-    FuncRec.Sender := Self;
-    FuncRec.CustomData := CustomData;
+    result := TColorTableFormat.Create;
+    result.PixelSize  := aInfo.biBitCount / 8;
+    result.ColorTable := ColorTable;
+    result.Range := glBitmapColorRec($FF, $FF, $FF, $00);
+  end;
 
-    NewImage := nil;
+  //////////////////////////////////////////////////////////////////////////////////////////////////
+  function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec;
+    const aInfo: TBMPInfo): TBitfieldFormat;
+  var
+    TmpFormat: TglBitmapFormat;
+    FormatDesc: TFormatDescriptor;
+  begin
+    result := nil;
+    if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin
+      for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
+        FormatDesc := TFormatDescriptor.Get(TmpFormat);
+        if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin
+          aFormat := FormatDesc.Format;
+          exit;
+        end;
+      end;
 
-    if CreateTemp then begin
-      GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth));
-      pDest := NewImage;
-    end
-      else pDest := Data;
+      if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then
+        aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha;
+      if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then
+        aFormat := TFormatDescriptor.Get(aFormat).WithAlpha;
+
+      result := TBitfieldFormat.Create;
+      result.PixelSize := aInfo.biBitCount / 8;
+      result.RedMask   := aMask.r;
+      result.GreenMask := aMask.g;
+      result.BlueMask  := aMask.b;
+      result.AlphaMask := aMask.a;
+    end;
+  end;
 
-    try
-      // Mapping
-      MapFunc := FormatGetMapFunc(Format);
-      FormatPreparePixel(FuncRec.Dest, Format);
-      FormatPreparePixel(FuncRec.Source, Source.InternalFormat);
+var
+  //simple types
+  StartPos: Int64;
+  ImageSize, rbLineSize, wbLineSize, Padding, i: Integer;
+  PaddingBuff: Cardinal;
+  LineBuf, ImageData, TmpData: PByte;
+  SourceMD, DestMD: Pointer;
+  BmpFormat: TglBitmapFormat;
+  ColorTable: TColorTable;
 
-      FuncRec.Size := Source.Dimension;
-      FuncRec.Position.Fields := FuncRec.Size.Fields;
+  //records
+  Mask: TglBitmapColorRec;
+  Header: TBMPHeader;
+  Info: TBMPInfo;
 
-      if FormatIsUncompressed(Source.InternalFormat) then begin
-        // Uncompressed Images
-        pSource := Source.Data;
-        UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat);
+  //classes
+  SpecialFormat: TFormatDescriptor;
+  FormatDesc: TFormatDescriptor;
 
-        FuncRec.Position.Y := 0;
-        while FuncRec.Position.Y < TempHeight do begin
-          FuncRec.Position.X := 0;
-          while FuncRec.Position.X < TempWidth do begin
-            // Get Data
-            UnMapFunc(pSource, FuncRec.Source);
-            // Func
-            Func(FuncRec);
-            // Set Data
-            MapFunc(FuncRec.Dest, pDest);
-            Inc(FuncRec.Position.X);
-          end;
-          Inc(FuncRec.Position.Y);
-        end;
-      end else begin
-        // Compressed Images
-        FuncRec.Position.Y := 0;
-        while FuncRec.Position.Y < TempHeight do begin
-          FuncRec.Position.X := 0;
-          while FuncRec.Position.X < TempWidth do begin
-            // Get Data
-            fGetPixelFunc(FuncRec.Position, FuncRec.Source);
-            // Func
-            Func(FuncRec);
-            // Set Data
-            MapFunc(FuncRec.Dest, pDest);
-            Inc(FuncRec.Position.X);
+  //////////////////////////////////////////////////////////////////////////////////////////////////
+  procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte);
+  var
+    i, j: Integer;
+    Pixel: TglBitmapPixelData;
+  begin
+    aStream.Read(aLineBuf^, rbLineSize);
+    SpecialFormat.PreparePixel(Pixel);
+    for i := 0 to Info.biWidth-1 do begin
+      SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD);
+      with FormatDesc do begin
+        //TODO: use convert function
+        for j := 0 to 3 do
+          if (SpecialFormat.Range.arr[j] <> Range.arr[j]) then begin
+            if (SpecialFormat.Range.arr[j] > 0) then
+              Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / SpecialFormat.Range.arr[j] * Range.arr[j])
+            else
+              Pixel.Data.arr[j] := 0;
           end;
-          Inc(FuncRec.Position.Y);
-        end;
       end;
-
-      // Updating Image or InternalFormat
-      if CreateTemp then
-        SetDataPointer(NewImage, Format)
-      else
-
-      if Format <> InternalFormat then
-        SetInternalFormat(Format);
-
-      Result := True;
-    except
-      if CreateTemp
-        then FreeMem(NewImage);
-      raise;
+      FormatDesc.Map(Pixel, aData, DestMD);
     end;
   end;
-end;
 
-
-procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec);
 begin
-  with FuncRec do begin
-    if Source.PixelDesc.RedRange > 0 then
-      Dest.Red   := Source.Red;
+  result        := false;
+  BmpFormat     := tfEmpty;
+  SpecialFormat := nil;
+  LineBuf       := nil;
+  SourceMD      := nil;
+  DestMD        := nil;
 
-    if Source.PixelDesc.GreenRange > 0 then
-      Dest.Green := Source.Green;
+  // Header
+  StartPos := aStream.Position;
+  aStream.Read(Header, SizeOf(Header));
 
-    if Source.PixelDesc.BlueRange > 0 then
-      Dest.Blue  := Source.Blue;
+  if Header.bfType = BMP_MAGIC then begin
+    try try
+      BmpFormat        := ReadInfo(Info, Mask);
+      SpecialFormat    := ReadColorTable(BmpFormat, Info);
+      if not Assigned(SpecialFormat) then
+        SpecialFormat  := CheckBitfields(BmpFormat, Mask, Info);
+      aStream.Position := StartPos + Header.bfOffBits;
+
+      if (BmpFormat <> tfEmpty) then begin
+        FormatDesc := TFormatDescriptor.Get(BmpFormat);
+        rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize
+        wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize);
+        Padding    := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize;
+
+        //get Memory
+        DestMD    := FormatDesc.CreateMappingData;
+        ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight));
+        GetMem(ImageData, ImageSize);
+        if Assigned(SpecialFormat) then begin
+          GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields
+          SourceMD := SpecialFormat.CreateMappingData;
+        end;
 
-    if Source.PixelDesc.AlphaRange > 0 then
-      Dest.Alpha := Source.Alpha;
-  end;
+        //read Data
+        try try
+          FillChar(ImageData^, ImageSize, $FF);
+          TmpData := ImageData;
+          if (Info.biHeight > 0) then
+            Inc(TmpData, wbLineSize * (Info.biHeight-1));
+          for i := 0 to Abs(Info.biHeight)-1 do begin
+            if Assigned(SpecialFormat) then
+              SpecialFormatReadLine(TmpData, LineBuf)  //if is special format read and convert data
+            else
+              aStream.Read(TmpData^, wbLineSize);   //else only read data
+            if (Info.biHeight > 0) then
+              dec(TmpData, wbLineSize)
+            else
+              inc(TmpData, wbLineSize);
+            aStream.Read(PaddingBuff, Padding);
+          end;
+          SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight));
+          result := true;
+        finally
+          if Assigned(LineBuf) then
+            FreeMem(LineBuf);
+          if Assigned(SourceMD) then
+            SpecialFormat.FreeMappingData(SourceMD);
+          FormatDesc.FreeMappingData(DestMD);
+        end;
+        except
+          FreeMem(ImageData);
+          raise;
+        end;
+      end else
+        raise EglBitmapException.Create('LoadBMP - No suitable format found');
+    except
+      aStream.Position := StartPos;
+      raise;
+    end;
+    finally
+      FreeAndNil(SpecialFormat);
+    end;
+  end
+    else aStream.Position := StartPos;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveBMP(const aStream: TStream);
+var
+  Header: TBMPHeader;
+  Info: TBMPInfo;
+  pData, pTemp: pByte;
 
-procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec);
-begin
-  with FuncRec do begin
-    if Source.PixelDesc.RedRange > 0 then
-      Dest.Red   := Round(Dest.PixelDesc.RedRange   * Source.Red   / Source.PixelDesc.RedRange);
-
-    if Source.PixelDesc.GreenRange > 0 then
-      Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange);
-
-    if Source.PixelDesc.BlueRange > 0 then
-      Dest.Blue  := Round(Dest.PixelDesc.BlueRange  * Source.Blue  / Source.PixelDesc.BlueRange);
+  PixelFormat: TglBitmapPixelData;
+  FormatDesc: TFormatDescriptor;
+  ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer;
+  Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal;
 
-    if Source.PixelDesc.AlphaRange > 0 then
-      Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange);
-  end;
-end;
+  PaddingBuff: Cardinal;
 
+  function GetLineWidth : Integer;
+  begin
+    result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3;
+  end;
 
-procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec);
 begin
-  with FuncRec do
-    with TglBitmapPixelDesc(CustomData^) do begin
-      if Source.PixelDesc.RedRange > 0 then
-        Dest.Red   := Source.Red   shr RedShift;
+  if not (ftBMP in FormatGetSupportedFiles(Format)) then
+    raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
 
-      if Source.PixelDesc.GreenRange > 0 then
-        Dest.Green := Source.Green shr GreenShift;
+  ImageSize := TFormatDescriptor.Get(Format).GetSize(Dimension);
 
-      if Source.PixelDesc.BlueRange > 0 then
-        Dest.Blue  := Source.Blue  shr BlueShift;
-
-      if Source.PixelDesc.AlphaRange > 0 then
-        Dest.Alpha := Source.Alpha shr AlphaShift;
-    end;
-end;
+  Header.bfType      := BMP_MAGIC;
+  Header.bfSize      := SizeOf(Header) + SizeOf(Info) + ImageSize;
+  Header.bfReserved1 := 0;
+  Header.bfReserved2 := 0;
+  Header.bfOffBits   := SizeOf(Header) + SizeOf(Info);
 
+  FillChar(Info, SizeOf(Info), 0);
+  Info.biSize        := SizeOf(Info);
+  Info.biWidth       := Width;
+  Info.biHeight      := Height;
+  Info.biPlanes      := 1;
+  Info.biCompression := BMP_COMP_RGB;
+  Info.biSizeImage   := ImageSize;
+  case Format of
+    //TODO tfAlpha8, ifLuminance8, ifDepth8:
+    tfLuminance8:
+      begin
+        Info.biBitCount :=  8;
 
-function TglBitmap.ConvertTo(NewFormat: TglBitmapInternalFormat): boolean;
-var
-  Source, Dest: TglBitmapPixelData;
-  PixelDesc: TglBitmapPixelDesc;
+        Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal);
+        Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal);
 
-  function CopyDirect: Boolean;
-  begin
-    Result :=
-      ((Source.PixelDesc.RedRange   = Dest.PixelDesc.RedRange)   or (Source.PixelDesc.RedRange   = 0) or (Dest.PixelDesc.RedRange   = 0)) and
-      ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
-      ((Source.PixelDesc.BlueRange  = Dest.PixelDesc.BlueRange)  or (Source.PixelDesc.BlueRange  = 0) or (Dest.PixelDesc.BlueRange  = 0)) and
-      ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
+        Info.biClrUsed := 256;
+        Info.biClrImportant := 256;
+      end;
+    //TODO ifLuminance8Alpha8, tfRGBA4, ifR5G6B5, tfRGB5A1:
+    tfLuminance8Alpha8, tfRGB5A1:
+      begin
+        Info.biBitCount := 16;
+        Info.biCompression := BMP_COMP_BITFIELDS;
+      end;
+    tfBGR8, tfRGB8:
+      Info.biBitCount := 24;
+    //TODO tfBGRA8, tfRGBA8, tfRGB10A2:
+    tfBGRA8, tfRGBA8:
+      begin
+        Info.biBitCount := 32;
+        Info.biCompression := BMP_COMP_BITFIELDS;
+      end;
+    else
+      raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT);
   end;
+  Info.biXPelsPerMeter := 2835;
+  Info.biYPelsPerMeter := 2835;
 
-  function CanShift: Boolean;
-  begin
-    Result :=
-      ((Source.PixelDesc.RedRange   >= Dest.PixelDesc.RedRange  ) or (Source.PixelDesc.RedRange   = 0) or (Dest.PixelDesc.RedRange   = 0)) and
-      ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and
-      ((Source.PixelDesc.BlueRange  >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange  = 0) or (Dest.PixelDesc.BlueRange  = 0)) and
-      ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0));
+  // 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);
+
+    FormatDesc := TFormatDescriptor.Get(Format);
+    RedMask   := FormatDesc.RedMask;
+    GreenMask := FormatDesc.GreenMask;
+    BlueMask  := FormatDesc.BlueMask;
+    AlphaMask := FormatDesc.AlphaMask;
   end;
 
-  function GetShift(Source, Dest: Cardinal) : ShortInt;
-  begin
-    Result := 0;
+  // headers
+  aStream.Write(Header, SizeOf(Header));
+  aStream.Write(Info, SizeOf(Info));
 
-    while (Source > Dest) and (Source > 0) do begin
-      Inc(Result);
-      Source := Source shr 1;
+  // 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;
     end;
   end;
 
-begin
-  if NewFormat <> InternalFormat then begin
-    FormatPreparePixel(Source, InternalFormat);
-    FormatPreparePixel(Dest, NewFormat);
-
-    if CopyDirect then
-      Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat)
-    else
-    if CanShift then begin
-      PixelDesc.RedShift   := GetShift(Source.PixelDesc.RedRange,   Dest.PixelDesc.RedRange);
-      PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange);
-      PixelDesc.BlueShift  := GetShift(Source.PixelDesc.BlueRange,  Dest.PixelDesc.BlueRange);
-      PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange);
-
-      Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc);
-    end
-      else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat);
-  end
-    else Result := True;
-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;
 
-function TglBitmap.RemoveAlpha: Boolean;
-begin
-  Result := False;
+  pData := Data;
+  Inc(pData, (Height -1) * LineSize);
 
-  if (Assigned(Data)) then begin
-    if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then
-      raise EglBitmapUnsupportedInternalFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  // 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;
 
-    Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat));
+  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);
+    end;
+  finally
+    // destroy row buffer
+    if Format = tfRGB8 then
+      FreeMem(pTemp);
   end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TGA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+type
+  TTGAHeader = packed record
+    ImageID: Byte;
+    ColorMapType: Byte;
+    ImageType: Byte;
+    ColorMapSpec: Array[0..4] of Byte;
+    OrigX: Word;
+    OrigY: Word;
+    Width: Word;
+    Height: Word;
+    Bpp: Byte;
+    ImageDes: Byte;
+  end;
 
-function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean;
-begin
-  if not FormatIsUncompressed(InternalFormat) then
-    raise EglBitmapUnsupportedInternalFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT);
+const
+  TGA_UNCOMPRESSED_RGB = 2;
+  TGA_UNCOMPRESSED_GRAY = 3;
+  TGA_COMPRESSED_RGB = 10;
+  TGA_COMPRESSED_GRAY = 11;
 
-  Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData);
-end;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadTGA(const aStream: TStream): Boolean;
+var
+  Header: TTGAHeader;
+  NewImage, pData: PByte;
+  StreamPos: Int64;
+  PixelSize, LineSize, YStart, YEnd, YInc: Integer;
+  Format: TglBitmapFormat;
 
+const
+  CACHE_SIZE = $4000;
 
-function TglBitmap.GetHeight: Integer;
-begin
-  if ffY in fDimension.Fields then
-    Result := fDimension.Y
-  else
-    Result := -1;
-end;
+  ////////////////////////////////////////////////////////////////////////////////////////
+  procedure ReadUncompressed;
+  var
+    RowSize: Integer;
+  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);
+    end;
+  end;
 
+  ////////////////////////////////////////////////////////////////////////////////////////
+  procedure ReadCompressed;
+  var
+    HeaderWidth, HeaderHeight: Integer;
+    LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer;
 
-function TglBitmap.GetWidth: Integer;
-begin
-  if ffX in fDimension.Fields then
-    Result := fDimension.X
-  else
-    Result := -1;
-end;
+    Cache: PByte;
+    CacheSize, CachePos: Integer;
 
+    Temp: Byte;
+    TempBuf: Array [0..15] of Byte;
 
-function TglBitmap.GetFileHeight: Integer;
-begin
-  Result := Max(1, Height);
-end;
+    PixelRepeat: Boolean;
+    PixelToRead, TempPixels: Integer;
 
+    /////////////////////////////////////////////////////////////////
+    procedure CheckLine;
+    begin
+      if LinePixelsRead >= HeaderWidth then begin
+        LinePixelsRead := 0;
+        pData := NewImage;
+        Inc(YStart, YInc);
+        Inc(pData, YStart * LineSize);
+      end;
+    end;
 
-function TglBitmap.GetFileWidth: Integer;
-begin
-  Result := Max(1, Width);
-end;
+    /////////////////////////////////////////////////////////////////
+    procedure CachedRead(out Buffer; Count: Integer);
+    var
+      BytesRead: Integer;
+    begin
+      if (CachePos + Count) > CacheSize then begin
+        BytesRead := 0;
 
+        // Read Data
+        if CacheSize - CachePos > 0 then begin
+          BytesRead := CacheSize - CachePos;
+          Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead);
+          Inc(CachePos, BytesRead);
+        end;
 
-procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec);
-var
-  Temp: Single;
-begin
-  with FuncRec do begin
-    Temp :=
-      Source.Red   / Source.PixelDesc.RedRange   * 0.3 +
-      Source.Green / Source.PixelDesc.GreenRange * 0.59 +
-      Source.Blue  / Source.PixelDesc.BlueRange  * 0.11;
+        // Reload Data
+        CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position);
+        aStream.Read(Cache^, CacheSize);
+        CachePos := 0;
 
-    Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp);
-  end;
-end;
+        // Read else
+        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);
+      end;
+    end;
 
+  begin
+    CacheSize := 0;
+    CachePos := 0;
 
-function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean;
-var
-  pDest, pDest2, pSource: pByte;
-  TempHeight, TempWidth: Integer;
-  MapFunc: TglBitmapMapFunc;
-  DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc;
+    HeaderWidth := Header.Width;
+    HeaderHeight := Header.Height;
 
-  FuncRec: TglBitmapFunctionRec;
-begin
-  Result := False;
+    GetMem(Cache, CACHE_SIZE); // 16K Buffer
+    try
+      ImgPixelsToRead := HeaderWidth * HeaderHeight;
+      ImgPixelsRead := 0;
+      LinePixelsRead := 0;
 
-  assert(Assigned(Data));
-  assert(Assigned(glBitmap));
-  assert(Assigned(glBitmap.Data));
+      pData := NewImage;
+      Inc(pData, YStart * LineSize);
 
-  if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin
-    // Convert to Data with Alpha
-    Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat)));
+      // Read until all Pixels
+      repeat
+        CachedRead(Temp, 1);
 
-    if not Assigned(Func) then
-      Func := glBitmapAlphaFunc;
+        PixelRepeat := Temp and $80 > 0;
+        PixelToRead := (Temp and $7F) + 1;
 
-    // Values
-    TempHeight := glBitmap.FileHeight;
-    TempWidth := glBitmap.FileWidth;
+        Inc(ImgPixelsRead, PixelToRead);
 
-    FuncRec.Sender := Self;
-    FuncRec.CustomData := CustomData;
+        if PixelRepeat then begin
+          // repeat one pixel x times
+          CachedRead(TempBuf[0], PixelSize);
 
-    pDest := Data;
-    pDest2 := Data;
-    pSource := glBitmap.Data;
+          // repeat Pixel
+          while PixelToRead > 0 do begin
+            CheckLine;
 
-    // Mapping
-    FormatPreparePixel(FuncRec.Dest, InternalFormat);
-    FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat);
-    MapFunc := FormatGetMapFunc(InternalFormat);
-    DestUnMapFunc := FormatGetUnMapFunc(InternalFormat);
-    UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat);
+            TempPixels := HeaderWidth - LinePixelsRead;
+            if PixelToRead < TempPixels then
+              TempPixels := PixelToRead;
 
-    FuncRec.Size := Dimension;
-    FuncRec.Position.Fields := FuncRec.Size.Fields;
+            Inc(LinePixelsRead, TempPixels);
+            Dec(PixelToRead, TempPixels);
 
-    FuncRec.Position.Y := 0;
-    while FuncRec.Position.Y < TempHeight do begin
-      FuncRec.Position.X := 0;
-      while FuncRec.Position.X < TempWidth do begin
-        // Get Data
-        UnMapFunc(pSource, FuncRec.Source);
-        DestUnMapFunc(pDest2, FuncRec.Dest);
-        // Func
-        Func(FuncRec);
-        // Set Data
-        MapFunc(FuncRec.Dest, pDest);
-        Inc(FuncRec.Position.X);
-      end;
-      Inc(FuncRec.Position.Y);
+            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);
+          end;
+        end;
+      until ImgPixelsRead >= ImgPixelsToRead;
+    finally
+      FreeMem(Cache)
     end;
   end;
-end;
-
-
-procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single);
-begin
-  fBorderColor[0] := Red;
-  fBorderColor[1] := Green;
-  fBorderColor[2] := Blue;
-  fBorderColor[3] := Alpha;
-
-  if ID > 0 then begin
-    Bind (False);
-
-    glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]);
-  end;
-end;
 
+begin
+  result := false;
 
-{ TglBitmap2D }
+  // reading header to test file and set cursor back to begin
+  StreamPos := aStream.Position;
+  aStream.Read(Header, SizeOf(Header));
 
-procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
-var
-  Idx, LineWidth: Integer;
-begin
-  inherited;
+  // 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
+      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.');
+      end;
 
-  // Format
-  if FormatIsUncompressed(Format) then begin
-    fUnmapFunc := FormatGetUnMapFunc(Format);
-    fGetPixelFunc := GetPixel2DUnmap;
+      // skip image ID
+      if Header.ImageID <> 0 then
+        aStream.Position := aStream.Position + Header.ImageID;
 
-    fMapFunc := FormatGetMapFunc(Format);
-    fSetPixelFunc := SetPixel2DUnmap;
+      PixelSize := TFormatDescriptor.Get(Format).GetSize(1, 1);
+      LineSize  := Trunc(Header.Width * PixelSize);
 
-    // Assigning Data
-    if Assigned(Data) then begin
-      SetLength(fLines, GetHeight);
+      GetMem(NewImage, LineSize * Header.Height);
+      try
+        // Row direction
+        if (Header.ImageDes and $20 > 0) then begin
+          YStart := 0;
+          YEnd := Header.Height -1;
+          YInc := 1;
+        end else begin
+          YStart := Header.Height -1;
+          YEnd := 0;
+          YInc := -1;
+        end;
 
-      LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat));
+        // Read Image
+        case Header.ImageType of
+          TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY:
+            ReadUncompressed;
+          TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY:
+            ReadCompressed;
+        end;
 
-      for Idx := 0 to GetHeight -1 do begin
-        fLines[Idx] := Data;
-        Inc(fLines[Idx], Idx * LineWidth);
+        SetDataPointer(NewImage, Format, Header.Width, Header.Height);
+        result := true;
+      except
+        FreeMem(NewImage);
+        raise;
       end;
     end
-      else SetLength(fLines, 0);
-  end else begin
-    SetLength(fLines, 0);
-
-    fSetPixelFunc := nil;
-
-    case Format of
-      ifDXT1:
-        fGetPixelFunc := GetPixel2DDXT1;
-      ifDXT3:
-        fGetPixelFunc := GetPixel2DDXT3;
-      ifDXT5:
-        fGetPixelFunc := GetPixel2DDXT5;
-      else
-        fGetPixelFunc := nil;
-    end;
-  end;
+      else aStream.Position := StreamPos;
+  end
+    else aStream.Position := StreamPos;
 end;
 
-
-procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData);
-type
-  PDXT1Chunk = ^TDXT1Chunk;
-  TDXT1Chunk = packed record
-    Color1: WORD;
-    Color2: WORD;
-    Pixels: array [0..3] of byte;
-  end;
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveTGA(const aStream: TStream);
 var
-  BasePtr: pDXT1Chunk;
-  PixPos: Integer;
-  Colors: array [0..3] of TRGBQuad;
-begin
-  BasePtr := pDXT1Chunk(pData);
-
-  PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3;
-
-  if PixPos in [0, 2, 3] then begin
-    Colors[0].rgbRed      := BasePtr^.Color1 and $F800 shr 8;
-    Colors[0].rgbGreen    := BasePtr^.Color1 and $07E0 shr 3;
-    Colors[0].rgbBlue     := BasePtr^.Color1 and $001F shl 3;
-    Colors[0].rgbReserved := 255;
-  end;
+  Header: TTGAHeader;
+  Size: Integer;
+  pTemp: pByte;
+  FormatDesc: TFormatDescriptor;
 
-  if PixPos in [1, 2, 3] then begin
-    Colors[1].rgbRed      := BasePtr^.Color2 and $F800 shr 8;
-    Colors[1].rgbGreen    := BasePtr^.Color2 and $07E0 shr 3;
-    Colors[1].rgbBlue     := BasePtr^.Color2 and $001F shl 3;
-    Colors[1].rgbReserved := 255;
+  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;
 
-  if PixPos = 2 then begin
-    Colors[2].rgbRed      := (Colors[0].rgbRed   * 67 + Colors[1].rgbRed   * 33) div 100;
-    Colors[2].rgbGreen    := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100;
-    Colors[2].rgbBlue     := (Colors[0].rgbBlue  * 67 + Colors[1].rgbBlue  * 33) div 100;
-    Colors[2].rgbReserved := 255;
-  end;
+begin
+  if not (ftTGA in FormatGetSupportedFiles(Format)) then
+    raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT);
 
-  if PixPos = 3 then begin
-    Colors[3].rgbRed      := (Colors[0].rgbRed   * 33 + Colors[1].rgbRed   * 67) div 100;
-    Colors[3].rgbGreen    := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100;
-    Colors[3].rgbBlue     := (Colors[0].rgbBlue  * 33 + Colors[1].rgbBlue  * 67) div 100;
-    if BasePtr^.Color1 > BasePtr^.Color2 then
-      Colors[3].rgbReserved := 255
-    else
-      Colors[3].rgbReserved := 0;
+  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;
 
-  Pixel.Red   := Colors[PixPos].rgbRed;
-  Pixel.Green := Colors[PixPos].rgbGreen;
-  Pixel.Blue  := Colors[PixPos].rgbBlue;
-  Pixel.Alpha := Colors[PixPos].rgbReserved;
-end;
-
+  Header.Width    := Width;
+  Header.Height   := Height;
+  Header.ImageDes := $20;
+  FormatDesc      := TFormatDescriptor.Get(Format);
 
-procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
-var
-  BasePtr: pByte;
-  PosX, PosY: Integer;
-begin
-  inherited;
+  if FormatDesc.HasAlpha then
+    Header.ImageDes := Header.ImageDes or $08;
+  aStream.Write(Header, SizeOf(Header));
 
-  if (Pos.Y <= Height) and (Pos.X <= Width) then begin
-    PosX := Pos.X div 4;
-    PosY := Pos.Y div 4;
+  // convert RGB(A) to BGR(A)
+  Size := FormatDesc.GetSize(Dimension);
+  if Format in [tfRGB8, tfRGBA8] then begin
+    GetMem(pTemp, Size);
+  end else
+    pTemp := Data;
 
-    BasePtr := Data;
-    Inc(BasePtr, (PosY * Width div 4 + PosX) * 8);
+  try
+    // convert data
+    if Format in [tfRGB8, tfRGBA8] then begin
+      Move(Data^, pTemp^, Size);
+      ConvertData(pTemp);
+    end;
 
-    GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel);
+    // write data
+    aStream.Write(pTemp^, Size);
+  finally
+    // free tempdata
+    if Format in [tfRGB8, tfRGBA8] then
+      FreeMem(pTemp);
   end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//DDS/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+const
+  DDS_MAGIC                   = $20534444;
 
-procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
-type
-  PDXT3AlphaChunk = ^TDXT3AlphaChunk;
-  TDXT3AlphaChunk = array [0..3] of WORD;
+  // DDS_header.dwFlags
+  DDSD_CAPS                   = $00000001;
+  DDSD_HEIGHT                 = $00000002;
+  DDSD_WIDTH                  = $00000004;
+  DDSD_PITCH                  = $00000008;
+  DDSD_PIXELFORMAT            = $00001000;
+  DDSD_MIPMAPCOUNT            = $00020000;
+  DDSD_LINEARSIZE             = $00080000;
+  DDSD_DEPTH                  = $00800000;
 
-var
-  ColorPtr: pByte;
-  AlphaPtr: PDXT3AlphaChunk;
-  PosX, PosY, relX, relY: Integer;
-begin
-  inherited;
+  // DDS_header.sPixelFormat.dwFlags
+  DDPF_ALPHAPIXELS            = $00000001;
+  DDPF_FOURCC                 = $00000004;
+  DDPF_INDEXED                = $00000020;
+  DDPF_RGB                    = $00000040;
 
-  if (Pos.Y <= Height) and (Pos.X <= Width) then begin
-    PosX := Pos.X div 4;
-    PosY := Pos.Y div 4;
-    relX := Pos.X - PosX * 4;
-    relY := Pos.Y - PosY * 4;
+  // DDS_header.sCaps.dwCaps1
+  DDSCAPS_COMPLEX             = $00000008;
+  DDSCAPS_TEXTURE             = $00001000;
+  DDSCAPS_MIPMAP              = $00400000;
 
-    // get color value
-    AlphaPtr := PDXT3AlphaChunk(Data);
-    Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
+  // DDS_header.sCaps.dwCaps2
+  DDSCAPS2_CUBEMAP            = $00000200;
+  DDSCAPS2_CUBEMAP_POSITIVEX  = $00000400;
+  DDSCAPS2_CUBEMAP_NEGATIVEX  = $00000800;
+  DDSCAPS2_CUBEMAP_POSITIVEY  = $00001000;
+  DDSCAPS2_CUBEMAP_NEGATIVEY  = $00002000;
+  DDSCAPS2_CUBEMAP_POSITIVEZ  = $00004000;
+  DDSCAPS2_CUBEMAP_NEGATIVEZ  = $00008000;
+  DDSCAPS2_VOLUME             = $00200000;
 
-    ColorPtr := pByte(AlphaPtr);
-    Inc(ColorPtr, 8);
+  D3DFMT_DXT1                 = $31545844;
+  D3DFMT_DXT3                 = $33545844;
+  D3DFMT_DXT5                 = $35545844;
 
-    GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
+type
+  TDDSPixelFormat = packed record
+    dwSize: Cardinal;
+    dwFlags: Cardinal;
+    dwFourCC: Cardinal;
+    dwRGBBitCount: Cardinal;
+    dwRBitMask: Cardinal;
+    dwGBitMask: Cardinal;
+    dwBBitMask: Cardinal;
+    dwABitMask: Cardinal;
+  end;
 
-    // extracting alpha
-    Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4;
+  TDDSCaps = packed record
+    dwCaps1: Cardinal;
+    dwCaps2: Cardinal;
+    dwDDSX: Cardinal;
+    dwReserved: Cardinal;
   end;
-end;
 
+  TDDSHeader = packed record
+    dwMagic: Cardinal;
+    dwSize: Cardinal;
+    dwFlags: Cardinal;
+    dwHeight: Cardinal;
+    dwWidth: Cardinal;
+    dwPitchOrLinearSize: Cardinal;
+    dwDepth: Cardinal;
+    dwMipMapCount: Cardinal;
+    dwReserved: array[0..10] of Cardinal;
+    PixelFormat: TDDSPixelFormat;
+    Caps: TDDSCaps;
+    dwReserved2: Cardinal;
+  end;
 
-procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
 var
-  ColorPtr: pByte;
-  AlphaPtr: PInt64;
-  PixPos, PosX, PosY, relX, relY: Integer;
-  Alpha0, Alpha1: Byte;
-begin
-  inherited;
+  Header: TDDSHeader;
+  StreamPos: Int64;
+  Y, LineSize: Cardinal;
+  RowSize: Cardinal;
+  NewImage, pData: pByte;
+  ddsFormat: TglBitmapFormat;
 
-  if (Pos.Y <= Height) and (Pos.X <= Width) then begin
-    PosX := Pos.X div 4;
-    PosY := Pos.Y div 4;
-    relX := Pos.X - PosX * 4;
-    relY := Pos.Y - PosY * 4;
+  function RaiseEx : Exception;
+  begin
+    result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
+  end;
 
-    // get color value
-    AlphaPtr := PInt64(Data);
-    Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2);
+  function GetDDSFormat: TglBitmapFormat;
+  begin
+    with Header.PixelFormat do begin
+      // Compresses
+      if (dwFlags and DDPF_FOURCC) > 0 then begin
+        (* TODO
+        case Header.PixelFormat.dwFourCC of
+          D3DFMT_DXT1: result := ifDXT1;
+          D3DFMT_DXT3: result := ifDXT3;
+          D3DFMT_DXT5: result := ifDXT5;
+        else
+          raise RaiseEx;
+        end;
+        *)
+        raise RaiseEx;
+      end else
 
-    ColorPtr := pByte(AlphaPtr);
-    Inc(ColorPtr, 8);
+      // RGB
+      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
+        case dwRGBBitCount of
+          8: begin
+            (* TODO if dwFlags and DDPF_ALPHAPIXELS > 0 then
+              result := tfAlpha
+            else
+            *)
+              result := tfLuminance8;
+          end;
+          16: begin
+            if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
+              // Alpha
+              case CountSetBits(dwRBitMask) of
+                5: result := tfRGB5A1;
+                //TODO 4: result := tfRGBA4;
+              else
+                result := tfLuminance8Alpha8;
+              end;
+            end else begin
+              // no Alpha
+              //TODO result := ifR5G6B5;
+              raise RaiseEx;
+            end;
+          end;
+          24: begin
+            if dwRBitMask > dwBBitMask then
+              result := tfBGR8
+            else
+              result := tfRGB8;
+          end;
+        32: begin
+            if CountSetBits(dwRBitMask) = 10 then
+              //TODO result := tfRGB10A2
+              raise RaiseEx
+            else
+
+            if dwRBitMask > dwBBitMask then
+              result := tfBGRA8
+            else
+              result := tfRGBA8;
+          end;
+        else
+          raise RaiseEx;
+        end;
+      end else
+        raise RaiseEx;
+    end;
+  end;
 
-    GetDXTColorBlock(ColorPtr, relX, relY, Pixel);
+begin
+  result := false;
 
-    // extracting alpha
-    Alpha0 := AlphaPtr^ and $FF;
-    Alpha1 := AlphaPtr^ shr 8 and $FF;
+  // Header
+  StreamPos := aStream.Position;
+  aStream.Read(Header, sizeof(Header));
 
-    PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07;
+  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
+    aStream.Position := StreamPos;
+    exit;
+  end;
 
-    // use alpha 0
-    if PixPos = 0 then begin
-      Pixel.Alpha := Alpha0;
-    end else
+  ddsFormat := GetDDSFormat;
+  LineSize  := Trunc(Header.dwWidth * TFormatDescriptor.Get(ddsFormat).PixelSize);
+  GetMem(NewImage, Header.dwHeight * LineSize);
+  try
+    pData := NewImage;
 
-    // use alpha 1
-    if PixPos = 1 then begin
-      Pixel.Alpha := Alpha1;
+    // Compressed
+    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);
+      end;
     end else
 
-    // alpha interpolate 7 Steps
-    if Alpha0 > Alpha1 then begin
-      Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7;
-    end else
+    // RGB(A)
+    if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
+      RowSize := Header.dwPitchOrLinearSize;
 
-    // alpha is 100% transparent or not transparent
-    if PixPos >= 6 then begin
-      if PixPos = 6 then
-        Pixel.Alpha := 0
-      else
-        Pixel.Alpha := 255;
+      for Y := 0 to Header.dwHeight -1 do begin
+        aStream.Read(pData^, RowSize);
+        Inc(pData, LineSize);
+      end;
     end else
+      raise RaiseEx;
 
-    // alpha interpolate 5 Steps
-    begin
-      Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5;
-    end;
-  end;
-end;
-
-
-procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData);
-var
-  pTemp: pByte;
-begin
-  pTemp := fLines[Pos.Y];
-  Inc(pTemp, Pos.X * fPixelSize);
-
-  fUnmapFunc(pTemp, Pixel);
+    SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
+    result := true;
+  except
+    FreeMem(NewImage);
+    raise;
+  end;
 end;
 
-
-procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveDDS(const aStream: TStream);
 var
-  pTemp: pByte;
+  Header: TDDSHeader;
+  Pix: TglBitmapPixelData;
+  FormatDesc: TFormatDescriptor;
 begin
-  pTemp := fLines[Pos.Y];
-  Inc(pTemp, Pos.X * fPixelSize);
+  //if not FormatIsUncompressed(InternalFormat) then
+  //  raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT);
 
-  fMapFunc(Pixel, pTemp);
-end;
+  (* TODO if Format = tfAlpha8 then
+    FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix);
+  else    *)
+    TFormatDescriptor.Get(Format).PreparePixel(Pix);
 
+  // Generell
+  FillChar(Header, SizeOf(Header), 0);
+  Header.dwMagic := DDS_MAGIC;
+  Header.dwSize  := 124;
+  Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT;
 
-function TglBitmap2D.FlipHorz: Boolean;
-var
-  Col, Row: Integer;
-  pTempDest, pDest, pSource: pByte;
-  ImgSize: Integer;
-begin
-  Result := Inherited FlipHorz;
+  if Width > 0 then begin
+    Header.dwWidth := Width;
+    Header.dwFlags := Header.dwFlags or DDSD_WIDTH;
+  end;
 
-  if Assigned(Data) then begin
-    pSource := Data;
-    ImgSize := Height * fRowSize;
+  if Height > 0 then begin
+    Header.dwHeight := Height;
+    Header.dwFlags := Header.dwFlags or DDSD_HEIGHT;
+  end;
 
-    GetMem(pDest, ImgSize);
-    try
-      pTempDest := pDest;
+  Header.dwPitchOrLinearSize := fRowSize;
+  Header.dwMipMapCount := 1;
 
-      Dec(pTempDest, fRowSize + fPixelSize);
-      for Row := 0 to Height -1 do begin
-        Inc(pTempDest, fRowSize * 2);
-        for Col := 0 to Width -1 do begin
-          Move(pSource^, pTempDest^, fPixelSize);
+  // Caps
+  Header.Caps.dwCaps1 := DDSCAPS_TEXTURE;
 
-          Inc(pSource, fPixelSize);
-          Dec(pTempDest, fPixelSize);
-        end;
-      end;
+  // Pixelformat
+  Header.PixelFormat.dwSize  := Sizeof(Header.PixelFormat);
+  Header.PixelFormat.dwFlags := DDPF_RGB;
 
-      SetDataPointer(pDest, InternalFormat);
+  (* TODO tfAlpha8
+  if FORMAT_DESCRIPTORS[Format].HasAlpha and (Format <> tfAlpha8) then
+    Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS;
+  *)
 
-      Result := True;
-    except
-      FreeMem(pDest);
-      raise;
-    end;
-  end;
+  FormatDesc := TFormatDescriptor.Get(Format);
+  Header.PixelFormat.dwRGBBitCount  := Trunc(FormatDesc.PixelSize * 8);
+  Header.PixelFormat.dwRBitMask     := FormatDesc.RedMask;
+  Header.PixelFormat.dwGBitMask     := FormatDesc.GreenMask;
+  Header.PixelFormat.dwBBitMask     := FormatDesc.BlueMask;
+  Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask;
+
+  aStream.Write(Header, SizeOf(Header));
+  aStream.Write(Data^, FormatDesc.GetSize(Dimension));
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmap2D/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer;
+begin
+  if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then
+    result := fLines[aIndex]
+  else
+    result := nil;
+end;
 
-function TglBitmap2D.FlipVert: Boolean;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat;
+  const aWidth: Integer; const aHeight: Integer);
 var
-  Row: Integer;
-  pTempDest, pDest, pSource: pByte;
+  Idx, LineWidth: Integer;
 begin
-  Result := Inherited FlipVert;
-
-  if Assigned(Data) then begin
-    pSource := Data;
-    GetMem(pDest, Height * fRowSize);
-    try
-      pTempDest := pDest;
+  inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
 
-      Inc(pTempDest, Width * (Height -1) * fPixelSize);
-
-      for Row := 0 to Height -1 do begin
-        Move(pSource^, pTempDest^, fRowSize);
+  //TODO compression
+  if {FormatIsUncompressed(Format)} true then begin
+    (* TODO PixelFuncs
+    fGetPixelFunc := GetPixel2DUnmap;
+    fSetPixelFunc := SetPixel2DUnmap;
+    *)
+    // Assigning Data
+    if Assigned(Data) then begin
+      SetLength(fLines, GetHeight);
+      LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize);
 
-        Dec(pTempDest, fRowSize);
-        Inc(pSource, fRowSize);
+      for Idx := 0 to GetHeight -1 do begin
+        fLines[Idx] := Data;
+        Inc(fLines[Idx], Idx * LineWidth);
       end;
+    end
+      else SetLength(fLines, 0);
+  end else begin
+    (*
+    SetLength(fLines, 0);
 
-      SetDataPointer(pDest, InternalFormat);
+    fSetPixelFunc := nil;
 
-      Result := True;
-    except
-      FreeMem(pDest);
-      raise;
+    case Format of
+      ifDXT1:
+        fGetPixelFunc := GetPixel2DDXT1;
+      ifDXT3:
+        fGetPixelFunc := GetPixel2DDXT3;
+      ifDXT5:
+        fGetPixelFunc := GetPixel2DDXT5;
+      else
+        fGetPixelFunc := nil;
     end;
+    *)
   end;
 end;
 
-
-procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean);
+var
+  FormatDesc: TFormatDescriptor;
 begin
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-  // Upload data
+  (* 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
+  *)
 
-  if BuildWithGlu then
-    gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data)
+  FormatDesc := TFormatDescriptor.Get(Format);
+  if aBuildWithGlu then
+    gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
+      FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
   else
-    glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data);
+    glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
+      FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
 
   // Freigeben
   if (FreeDataAfterGenTexture) then
     FreeData;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.AfterConstruction;
+begin
+  inherited;
+  Target := GL_TEXTURE_2D;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat);
+var
+  Temp: pByte;
+  Size, w, h: Integer;
+  FormatDesc: TFormatDescriptor;
+begin
+  (* TODO compression
+  if not FormatIsUncompressed(Format) then
+    raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
+  *)
+
+  w := aRight  - aLeft;
+  h := aBottom - aTop;
+  FormatDesc   := TFormatDescriptor.Get(Format);
+  Size         := FormatDesc.GetSize(w, h);
+  GetMem(Temp, Size);
+  try
+    glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
+    SetDataPointer(Temp, Format, w, h);
+    FlipVert;
+  except
+    FreeMem(Temp);
+    raise;
+  end;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.GetDataFromTexture;
+var
+  Temp: PByte;
+  TempWidth, TempHeight: Integer;
+  TempType, TempIntFormat: Cardinal;
+  IntFormat, f: TglBitmapFormat;
+  FormatDesc: TFormatDescriptor;
+begin
+  Bind;
+
+  // Request Data
+  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH,           @TempWidth);
+  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT,          @TempHeight);
+  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
+
+  IntFormat := tfEmpty;
+  for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do
+    if (TFormatDescriptor.Get(f).glInternalFormat = TempIntFormat) then begin
+      IntFormat := FormatDesc.Format;
+      break;
+    end;
+
+  // Getting data from OpenGL
+  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
+      glGetCompressedTexImage(Target, 0, Temp)
+    else
+    *)
+    glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
+    SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
+  except
+    FreeMem(Temp);
+    raise;
+  end;
+end;
 
-procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean);
 var
   BuildWithGlu, PotTex, TexRec: Boolean;
-  glFormat, glInternalFormat, glType: Cardinal;
   TexSize: Integer;
 begin
   if Assigned(Data) then begin
     // Check Texture Size
-    if (TestTextureSize) then begin
+    if (aTestTextureSize) then begin
       glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize);
 
       if ((Height > TexSize) or (Width > TexSize)) then
         raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.');
 
-      PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width);
-      TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and
-                (Target = GL_TEXTURE_RECTANGLE_ARB);
+      PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width);
+      TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB);
 
       if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then
         raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.');
     end;
 
     CreateId;
-
     SetupParameters(BuildWithGlu);
-    SelectFormat(InternalFormat, glFormat, glInternalFormat, glType);
-
-    UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
-
-    // Infos sammeln
-    glAreTexturesResident(1, @ID, @fIsResident);
+    UploadData(Target, BuildWithGlu);
+    glAreTexturesResident(1, @fID, @fIsResident);
   end;
 end;
 
-
-procedure TglBitmap2D.AfterConstruction;
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap2D.FlipHorz: Boolean;
+var
+  Col, Row: Integer;
+  TempDestData, DestData, SourceData: PByte;
+  ImgSize: Integer;
 begin
-  inherited;
-
-  Target := GL_TEXTURE_2D;
+  result := inherited FlipHorz;
+  if Assigned(Data) then begin
+    SourceData := Data;
+    ImgSize := Height * fRowSize;
+    GetMem(DestData, ImgSize);
+    try
+      TempDestData := DestData;
+      Dec(TempDestData, fRowSize + fPixelSize);
+      for Row := 0 to Height -1 do begin
+        Inc(TempDestData, fRowSize * 2);
+        for Col := 0 to Width -1 do begin
+          Move(SourceData^, TempDestData^, fPixelSize);
+          Inc(SourceData, fPixelSize);
+          Dec(TempDestData, fPixelSize);
+        end;
+      end;
+      SetDataPointer(DestData, Format);
+      result := true;
+    except
+      FreeMem(DestData);
+      raise;
+    end;
+  end;
 end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap2D.FlipVert: Boolean;
+var
+  Row: Integer;
+  TempDestData, DestData, SourceData: PByte;
+begin
+  result := inherited FlipVert;
+  if Assigned(Data) then begin
+    SourceData := Data;
+    GetMem(DestData, Height * fRowSize);
+    try
+      TempDestData := DestData;
+      Inc(TempDestData, Width * (Height -1) * fPixelSize);
+      for Row := 0 to Height -1 do begin
+        Move(SourceData^, TempDestData^, fRowSize);
+        Dec(TempDestData, fRowSize);
+        Inc(SourceData, fRowSize);
+      end;
+      SetDataPointer(DestData, Format);
+      result := true;
+    except
+      FreeMem(DestData);
+      raise;
+    end;
+  end;
+end;
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TglBitmap2D - ToNormalMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 type
   TMatrixItem = record
     X, Y: Integer;
@@ -6648,26 +6873,30 @@ type
   end;
 
 const
-  oneover255 = 1 / 255;
+  ONE_OVER_255 = 1 / 255;
 
-procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec);
+  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec);
 var
   Val: Single;
 begin
   with FuncRec do begin
-    Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue *  0.11;
-    PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255;
+    Val :=
+      Source.Data.r * LUMINANCE_WEIGHT_R +
+      Source.Data.g * LUMINANCE_WEIGHT_G +
+      Source.Data.b * LUMINANCE_WEIGHT_B;
+    PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255;
   end;
 end;
 
-
-procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec);
 begin
   with FuncRec do
-    PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255;
+    PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255;
 end;
 
-
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec);
 type
   TVec = Array[0..2] of Single;
@@ -6682,14 +6911,13 @@ var
     with FuncRec do begin
       X := Max(0, Min(Size.X -1, X));
       Y := Max(0, Min(Size.Y -1, Y));
-
-      Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X];
+      result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X];
     end;
   end;
 
 begin
   with FuncRec do begin
-    with PglBitmapToNormalMapRec (CustomData)^ do begin
+    with PglBitmapToNormalMapRec(Args)^ do begin
       du := 0;
       for Idx := Low(MatrixU) to High(MatrixU) do
         du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W;
@@ -6712,14 +6940,14 @@ begin
     end;
 
     // Farbe zuweisem
-    Dest.Red   := Trunc((Vec[0] + 1) * 127.5);
-    Dest.Green := Trunc((Vec[1] + 1) * 127.5);
-    Dest.Blue  := Trunc((Vec[2] + 1) * 127.5);
+    Dest.Data.r := Trunc((Vec[0] + 1) * 127.5);
+    Dest.Data.g := Trunc((Vec[1] + 1) * 127.5);
+    Dest.Data.b := Trunc((Vec[2] + 1) * 127.5);
   end;
 end;
 
-
-procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean);
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean);
 var
   Rec: TglBitmapToNormalMapRec;
 
@@ -6733,253 +6961,134 @@ var
   end;
 
 begin
+  (* TODO Compression
   if not FormatIsUncompressed(InternalFormat) then
-    raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT);
+    raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT);
+    *)
 
-  if Scale > 100 then
+  if aScale > 100 then
     Rec.Scale := 100
-  else
-  if Scale < -100 then
+  else if aScale < -100 then
     Rec.Scale := -100
   else
-    Rec.Scale := Scale;
+    Rec.Scale := aScale;
 
   SetLength(Rec.Heights, Width * Height);
   try
-    case Func of
-      nm4Samples:
-        begin
-          SetLength(Rec.MatrixU, 2);
-          SetEntry(Rec.MatrixU, 0, -1,  0, -0.5);
-          SetEntry(Rec.MatrixU, 1,  1,  0,  0.5);
-
-          SetLength(Rec.MatrixV, 2);
-          SetEntry(Rec.MatrixV, 0,  0,  1,  0.5);
-          SetEntry(Rec.MatrixV, 1,  0, -1, -0.5);
-        end;
-      nmSobel:
-        begin
-          SetLength(Rec.MatrixU, 6);
-          SetEntry(Rec.MatrixU, 0, -1,  1, -1.0);
-          SetEntry(Rec.MatrixU, 1, -1,  0, -2.0);
-          SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
-          SetEntry(Rec.MatrixU, 3,  1,  1,  1.0);
-          SetEntry(Rec.MatrixU, 4,  1,  0,  2.0);
-          SetEntry(Rec.MatrixU, 5,  1, -1,  1.0);
-
-          SetLength(Rec.MatrixV, 6);
-          SetEntry(Rec.MatrixV, 0, -1,  1,  1.0);
-          SetEntry(Rec.MatrixV, 1,  0,  1,  2.0);
-          SetEntry(Rec.MatrixV, 2,  1,  1,  1.0);
-          SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
-          SetEntry(Rec.MatrixV, 4,  0, -1, -2.0);
-          SetEntry(Rec.MatrixV, 5,  1, -1, -1.0);
-        end;
-      nm3x3:
-        begin
-          SetLength(Rec.MatrixU, 6);
-          SetEntry(Rec.MatrixU, 0, -1,  1, -1/6);
-          SetEntry(Rec.MatrixU, 1, -1,  0, -1/6);
-          SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
-          SetEntry(Rec.MatrixU, 3,  1,  1,  1/6);
-          SetEntry(Rec.MatrixU, 4,  1,  0,  1/6);
-          SetEntry(Rec.MatrixU, 5,  1, -1,  1/6);
-
-          SetLength(Rec.MatrixV, 6);
-          SetEntry(Rec.MatrixV, 0, -1,  1,  1/6);
-          SetEntry(Rec.MatrixV, 1,  0,  1,  1/6);
-          SetEntry(Rec.MatrixV, 2,  1,  1,  1/6);
-          SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
-          SetEntry(Rec.MatrixV, 4,  0, -1, -1/6);
-          SetEntry(Rec.MatrixV, 5,  1, -1, -1/6);
-        end;
-      nm5x5:
-        begin
-          SetLength(Rec.MatrixU, 20);
-          SetEntry(Rec.MatrixU,  0, -2,  2, -1 / 16);
-          SetEntry(Rec.MatrixU,  1, -1,  2, -1 / 10);
-          SetEntry(Rec.MatrixU,  2,  1,  2,  1 / 10);
-          SetEntry(Rec.MatrixU,  3,  2,  2,  1 / 16);
-          SetEntry(Rec.MatrixU,  4, -2,  1, -1 / 10);
-          SetEntry(Rec.MatrixU,  5, -1,  1, -1 /  8);
-          SetEntry(Rec.MatrixU,  6,  1,  1,  1 /  8);
-          SetEntry(Rec.MatrixU,  7,  2,  1,  1 / 10);
-          SetEntry(Rec.MatrixU,  8, -2,  0, -1 / 2.8);
-          SetEntry(Rec.MatrixU,  9, -1,  0, -0.5);
-          SetEntry(Rec.MatrixU, 10,  1,  0,  0.5);
-          SetEntry(Rec.MatrixU, 11,  2,  0,  1 / 2.8);
-          SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
-          SetEntry(Rec.MatrixU, 13, -1, -1, -1 /  8);
-          SetEntry(Rec.MatrixU, 14,  1, -1,  1 /  8);
-          SetEntry(Rec.MatrixU, 15,  2, -1,  1 / 10);
-          SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
-          SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
-          SetEntry(Rec.MatrixU, 18,  1, -2,  1 / 10);
-          SetEntry(Rec.MatrixU, 19,  2, -2,  1 / 16);
-
-          SetLength(Rec.MatrixV, 20);
-          SetEntry(Rec.MatrixV,  0, -2,  2,  1 / 16);
-          SetEntry(Rec.MatrixV,  1, -1,  2,  1 / 10);
-          SetEntry(Rec.MatrixV,  2,  0,  2,  0.25);
-          SetEntry(Rec.MatrixV,  3,  1,  2,  1 / 10);
-          SetEntry(Rec.MatrixV,  4,  2,  2,  1 / 16);
-          SetEntry(Rec.MatrixV,  5, -2,  1,  1 / 10);
-          SetEntry(Rec.MatrixV,  6, -1,  1,  1 /  8);
-          SetEntry(Rec.MatrixV,  7,  0,  1,  0.5);
-          SetEntry(Rec.MatrixV,  8,  1,  1,  1 /  8);
-          SetEntry(Rec.MatrixV,  9,  2,  1,  1 / 16);
-          SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
-          SetEntry(Rec.MatrixV, 11, -1, -1, -1 /  8);
-          SetEntry(Rec.MatrixV, 12,  0, -1, -0.5);
-          SetEntry(Rec.MatrixV, 13,  1, -1, -1 /  8);
-          SetEntry(Rec.MatrixV, 14,  2, -1, -1 / 10);
-          SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
-          SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
-          SetEntry(Rec.MatrixV, 17,  0, -2, -0.25);
-          SetEntry(Rec.MatrixV, 18,  1, -2, -1 / 10);
-          SetEntry(Rec.MatrixV, 19,  2, -2, -1 / 16);
-        end;
+    case aFunc of
+      nm4Samples: begin
+        SetLength(Rec.MatrixU, 2);
+        SetEntry(Rec.MatrixU, 0, -1,  0, -0.5);
+        SetEntry(Rec.MatrixU, 1,  1,  0,  0.5);
+
+        SetLength(Rec.MatrixV, 2);
+        SetEntry(Rec.MatrixV, 0,  0,  1,  0.5);
+        SetEntry(Rec.MatrixV, 1,  0, -1, -0.5);
+      end;
+
+      nmSobel: begin
+        SetLength(Rec.MatrixU, 6);
+        SetEntry(Rec.MatrixU, 0, -1,  1, -1.0);
+        SetEntry(Rec.MatrixU, 1, -1,  0, -2.0);
+        SetEntry(Rec.MatrixU, 2, -1, -1, -1.0);
+        SetEntry(Rec.MatrixU, 3,  1,  1,  1.0);
+        SetEntry(Rec.MatrixU, 4,  1,  0,  2.0);
+        SetEntry(Rec.MatrixU, 5,  1, -1,  1.0);
+
+        SetLength(Rec.MatrixV, 6);
+        SetEntry(Rec.MatrixV, 0, -1,  1,  1.0);
+        SetEntry(Rec.MatrixV, 1,  0,  1,  2.0);
+        SetEntry(Rec.MatrixV, 2,  1,  1,  1.0);
+        SetEntry(Rec.MatrixV, 3, -1, -1, -1.0);
+        SetEntry(Rec.MatrixV, 4,  0, -1, -2.0);
+        SetEntry(Rec.MatrixV, 5,  1, -1, -1.0);
+      end;
+
+      nm3x3: begin
+        SetLength(Rec.MatrixU, 6);
+        SetEntry(Rec.MatrixU, 0, -1,  1, -1/6);
+        SetEntry(Rec.MatrixU, 1, -1,  0, -1/6);
+        SetEntry(Rec.MatrixU, 2, -1, -1, -1/6);
+        SetEntry(Rec.MatrixU, 3,  1,  1,  1/6);
+        SetEntry(Rec.MatrixU, 4,  1,  0,  1/6);
+        SetEntry(Rec.MatrixU, 5,  1, -1,  1/6);
+
+        SetLength(Rec.MatrixV, 6);
+        SetEntry(Rec.MatrixV, 0, -1,  1,  1/6);
+        SetEntry(Rec.MatrixV, 1,  0,  1,  1/6);
+        SetEntry(Rec.MatrixV, 2,  1,  1,  1/6);
+        SetEntry(Rec.MatrixV, 3, -1, -1, -1/6);
+        SetEntry(Rec.MatrixV, 4,  0, -1, -1/6);
+        SetEntry(Rec.MatrixV, 5,  1, -1, -1/6);
+      end;
+
+      nm5x5: begin
+        SetLength(Rec.MatrixU, 20);
+        SetEntry(Rec.MatrixU,  0, -2,  2, -1 / 16);
+        SetEntry(Rec.MatrixU,  1, -1,  2, -1 / 10);
+        SetEntry(Rec.MatrixU,  2,  1,  2,  1 / 10);
+        SetEntry(Rec.MatrixU,  3,  2,  2,  1 / 16);
+        SetEntry(Rec.MatrixU,  4, -2,  1, -1 / 10);
+        SetEntry(Rec.MatrixU,  5, -1,  1, -1 /  8);
+        SetEntry(Rec.MatrixU,  6,  1,  1,  1 /  8);
+        SetEntry(Rec.MatrixU,  7,  2,  1,  1 / 10);
+        SetEntry(Rec.MatrixU,  8, -2,  0, -1 / 2.8);
+        SetEntry(Rec.MatrixU,  9, -1,  0, -0.5);
+        SetEntry(Rec.MatrixU, 10,  1,  0,  0.5);
+        SetEntry(Rec.MatrixU, 11,  2,  0,  1 / 2.8);
+        SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10);
+        SetEntry(Rec.MatrixU, 13, -1, -1, -1 /  8);
+        SetEntry(Rec.MatrixU, 14,  1, -1,  1 /  8);
+        SetEntry(Rec.MatrixU, 15,  2, -1,  1 / 10);
+        SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16);
+        SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10);
+        SetEntry(Rec.MatrixU, 18,  1, -2,  1 / 10);
+        SetEntry(Rec.MatrixU, 19,  2, -2,  1 / 16);
+
+        SetLength(Rec.MatrixV, 20);
+        SetEntry(Rec.MatrixV,  0, -2,  2,  1 / 16);
+        SetEntry(Rec.MatrixV,  1, -1,  2,  1 / 10);
+        SetEntry(Rec.MatrixV,  2,  0,  2,  0.25);
+        SetEntry(Rec.MatrixV,  3,  1,  2,  1 / 10);
+        SetEntry(Rec.MatrixV,  4,  2,  2,  1 / 16);
+        SetEntry(Rec.MatrixV,  5, -2,  1,  1 / 10);
+        SetEntry(Rec.MatrixV,  6, -1,  1,  1 /  8);
+        SetEntry(Rec.MatrixV,  7,  0,  1,  0.5);
+        SetEntry(Rec.MatrixV,  8,  1,  1,  1 /  8);
+        SetEntry(Rec.MatrixV,  9,  2,  1,  1 / 16);
+        SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16);
+        SetEntry(Rec.MatrixV, 11, -1, -1, -1 /  8);
+        SetEntry(Rec.MatrixV, 12,  0, -1, -0.5);
+        SetEntry(Rec.MatrixV, 13,  1, -1, -1 /  8);
+        SetEntry(Rec.MatrixV, 14,  2, -1, -1 / 10);
+        SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16);
+        SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10);
+        SetEntry(Rec.MatrixV, 17,  0, -2, -0.25);
+        SetEntry(Rec.MatrixV, 18,  1, -2, -1 / 10);
+        SetEntry(Rec.MatrixV, 19,  2, -2, -1 / 16);
+      end;
     end;
 
     // Daten Sammeln
-    if UseAlpha and FormatHasAlpha(InternalFormat) then
-      AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec)
+    if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then
+      AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec))
     else
-      AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec);
-
-    // Neues Bild berechnen
-    AddFunc(glBitmapToNormalMapFunc, False, @Rec);
+      AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec));
+    AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec));
   finally
     SetLength(Rec.Heights, 0);
   end;
 end;
 
 
-procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat);
-var
-  Temp: pByte;
-  Size: Integer;
-  glFormat, glInternalFormat, glType: Cardinal;
-begin
-  if not FormatIsUncompressed(Format) then
-    raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT);
-
-  // Only to select Formats
-  SelectFormat(Format, glFormat, glInternalFormat, glType, False);
-
-  Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format);
-  GetMem(Temp, Size);
-  try
-    glPixelStorei(GL_PACK_ALIGNMENT, 1);
-    glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp);
-
-    // Set Data
-    SetDataPointer(Temp, Format, Right - Left, Bottom - Top);
-
-    // Flip
-    FlipVert;
-  except
-    FreeMem(Temp);
-    raise;
-  end;
-end;
-
-
-procedure TglBitmap2D.GetDataFromTexture;
-var
-  Temp: pByte;
-  TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer;
-  TempType, TempIntFormat: Cardinal;
-  IntFormat: TglBitmapInternalFormat;
-begin
-  Bind;
-
-  // Request Data
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat);
-
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize);
-  glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize);
-
-  // Get glBitmapInternalFormat from TempIntFormat
-  TempType := GL_UNSIGNED_BYTE;
-  case TempIntFormat of
-    GL_ALPHA:
-      IntFormat := ifAlpha;
-    GL_LUMINANCE:
-      IntFormat := ifLuminance;
-    GL_LUMINANCE_ALPHA:
-      IntFormat := ifLuminanceAlpha;
-    GL_RGB4:
-      begin
-        IntFormat := ifR5G6B5;
-        TempIntFormat := GL_RGB;
-        TempType := GL_UNSIGNED_SHORT_5_6_5;
-      end;
-    GL_RGB, GL_RGB8:
-      IntFormat := ifRGB8;
-    GL_RGBA, GL_RGBA4, GL_RGBA8:
-      begin
-        if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin
-          IntFormat := ifRGBA4;
-          TempIntFormat := GL_BGRA;
-          TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV;
-        end else
-        if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin
-          IntFormat := ifRGB5A1;
-          TempIntFormat := GL_BGRA;
-          TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV;
-        end else begin
-          IntFormat := ifRGBA8;
-        end;
-      end;
-    GL_BGR:
-      IntFormat := ifBGR8;
-    GL_BGRA:
-      IntFormat := ifBGRA8;
-    GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
-      IntFormat := ifDXT1;
-    GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      IntFormat := ifDXT1;
-    GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
-      IntFormat := ifDXT3;
-    GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
-      IntFormat := ifDXT5;
-    else
-      IntFormat := ifEmpty;
-  end;
 
-  // Getting data from OpenGL
-  GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
-  try
-    if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
-      glGetCompressedTexImage(Target, 0, Temp)
-    else
-      glGetTexImage(Target, 0, TempIntFormat, TempType, Temp);
 
-    SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
-  except
-    FreeMem(Temp);
-    raise;
-  end;
-end;
 
 
-function TglBitmap2D.GetScanline(Index: Integer): Pointer;
-begin
-  if (Index >= Low(fLines)) and (Index <= High(fLines)) then
-    Result := fLines[Index]
-  else
-    Result := nil;
-end;
 
 
-{ TglBitmap1D }
 
+(*
 procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer);
 var
   pTemp: pByte;
@@ -7022,7 +7131,7 @@ var
   Col: Integer;
   pTempDest, pDest, pSource: pByte;
 begin
-  Result := Inherited FlipHorz;
+  result := inherited FlipHorz;
 
   if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin
     pSource := Data;
@@ -7041,7 +7150,7 @@ begin
 
       SetDataPointer(pDest, InternalFormat);
 
-      Result := True;
+      result := true;
     finally
       FreeMem(pDest);
     end;
@@ -7097,7 +7206,7 @@ begin
     UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu);
 
     // Infos sammeln
-    glAreTexturesResident(1, @ID, @fIsResident);
+    glAreTexturesResident(1, @fID, @fIsResident);
   end;
 end;
 
@@ -7171,7 +7280,7 @@ end;
 
 procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean);
 begin
-  Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
+  Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.');
 end;
 
 
@@ -7296,7 +7405,7 @@ var
 begin
   Rec.HalfSize := Size div 2;
 
-  FreeDataAfterGenTexture := False;
+  FreeDataAfterGenTexture := false;
 
   SizeRec.Fields := [ffX, ffY];
   SizeRec.X := Size;
@@ -7332,17 +7441,20 @@ begin
   LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec);
   GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize);
 end;
-
-
+*)
 
 initialization
-  glBitmapSetDefaultFormat(tfDefault);
+  glBitmapSetDefaultFormat(tfEmpty);
+  glBitmapSetDefaultMipmap(mmMipmap);
   glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR);
-  glBitmapSetDefaultWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+  glBitmapSetDefaultWrap  (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
+
+  glBitmapSetDefaultFreeDataAfterGenTexture(true);
+  glBitmapSetDefaultDeleteTextureOnFree    (true);
 
-  glBitmapSetDefaultFreeDataAfterGenTexture(True);
-  glBitmapSetDefaultDeleteTextureOnFree(True);
+  TFormatDescriptor.Init;
 
 finalization
+  TFormatDescriptor.Finalize;
 
 end.