* Format: implemented HasRed, HasGreen and HasBlue
[LazOpenGLCore.git] / glBitmap.pas
index 1a2f7d6..b181705 100644 (file)
@@ -24,7 +24,7 @@ History
 - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson)
 10-08-2008
 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson)
-- Additional Datapointer for functioninterface now has the name CustomData  
+- Additional Datapointer for functioninterface now has the name CustomData
 24-07-2008
 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson)
 - If you load an texture from an file the property Filename will be set to the name of the file
@@ -53,7 +53,7 @@ History
 - Property DataPtr now has the name Data
 - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR
 - Unused Depth removed
-- Function FreeData to freeing image data added 
+- Function FreeData to freeing image data added
 24-10-2007
 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen)
 15-11-2006
@@ -221,7 +221,7 @@ unit glBitmap;
 
 // Please uncomment the defines below to configure the glBitmap to your preferences.
 // If you have configured the unit you can uncomment the warning above.
-{$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
+{.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'}
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 // Preferences ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -242,7 +242,7 @@ unit glBitmap;
 {.$DEFINE GLB_DELPHI}
 
 // activate to enable the support for TLazIntfImage from Lazarus
-{$DEFINE GLB_LAZARUS}
+{.$DEFINE GLB_LAZARUS}
 
 
 
@@ -252,6 +252,10 @@ unit glBitmap;
 
 
 
+// activate to enable Lazarus TPortableNetworkGraphic support
+// if you enable this pngImage and libPNG will be ignored
+{.$DEFINE GLB_LAZ_PNG}
+
 // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/
 // if you enable pngimage the libPNG will be ignored
 {.$DEFINE GLB_PNGIMAGE}
@@ -262,6 +266,10 @@ unit glBitmap;
 
 
 
+// activate to enable Lazarus TJPEGImage support
+// if you enable this delphi jpegs and libJPEG will be ignored
+{.$DEFINE GLB_LAZ_JPEG}
+
 // if you enable delphi jpegs the libJPEG will be ignored
 {.$DEFINE GLB_DELPHI_JPEG}
 
@@ -306,18 +314,32 @@ unit glBitmap;
     {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'}
     {$DEFINE GLB_SDL}
   {$ENDIF}
+
+  {$IFDEF GLB_LAZ_PNG}
+    {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'}
+    {$undef GLB_LAZ_PNG}
+  {$ENDIF}
+
   {$IFDEF GLB_PNGIMAGE}
     {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'}
     {$undef GLB_PNGIMAGE}
   {$ENDIF}
+
+  {$IFDEF GLB_LAZ_JPEG}
+    {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'}
+    {$undef GLB_LAZ_JPEG}
+  {$ENDIF}
+
   {$IFDEF GLB_DELPHI_JPEG}
     {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'}
     {$undef GLB_DELPHI_JPEG}
   {$ENDIF}
+
   {$IFDEF GLB_LIB_PNG}
     {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'}
     {$undef GLB_LIB_PNG}
   {$ENDIF}
+
   {$IFDEF GLB_LIB_JPEG}
     {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'}
     {$undef GLB_LIB_JPEG}
@@ -327,6 +349,27 @@ unit glBitmap;
   {$DEFINE GLB_SUPPORT_JPEG_READ}
 {$ENDIF}
 
+// Lazarus TPortableNetworkGraphic
+{$IFDEF GLB_LAZ_PNG}
+  {$IFNDEF GLB_LAZARUS}
+    {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'}
+    {$DEFINE GLB_LAZARUS}
+  {$ENDIF}
+
+  {$IFDEF GLB_PNGIMAGE}
+    {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
+    {$undef GLB_PNGIMAGE}
+  {$ENDIF}
+
+  {$IFDEF GLB_LIB_PNG}
+    {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'}
+    {$undef GLB_LIB_PNG}
+  {$ENDIF}
+
+  {$DEFINE GLB_SUPPORT_PNG_READ}
+  {$DEFINE GLB_SUPPORT_PNG_WRITE}
+{$ENDIF}
+
 // PNG Image
 {$IFDEF GLB_PNGIMAGE}
   {$IFDEF GLB_LIB_PNG}
@@ -344,6 +387,27 @@ unit glBitmap;
   {$DEFINE GLB_SUPPORT_PNG_WRITE}
 {$ENDIF}
 
+// Lazarus TJPEGImage
+{$IFDEF GLB_LAZ_JPEG}
+  {$IFNDEF GLB_LAZARUS}
+    {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'}
+    {$DEFINE GLB_LAZARUS}
+  {$ENDIF}
+
+  {$IFDEF GLB_DELPHI_JPEG}
+    {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'}
+    {$undef GLB_DELPHI_JPEG}
+  {$ENDIF}
+
+  {$IFDEF GLB_LIB_JPEG}
+    {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'}
+    {$undef GLB_LIB_JPEG}
+  {$ENDIF}
+
+  {$DEFINE GLB_SUPPORT_JPEG_READ}
+  {$DEFINE GLB_SUPPORT_JPEG_WRITE}
+{$ENDIF}
+
 // JPEG Image
 {$IFDEF GLB_DELPHI_JPEG}
   {$IFDEF GLB_LIB_JPEG}
@@ -377,19 +441,20 @@ unit glBitmap;
 interface
 
 uses
-  {$IFNDEF GLB_NATIVE_OGL}      dglOpenGL,                {$ENDIF}
+  {$IFNDEF GLB_NATIVE_OGL}      dglOpenGL,                          {$ENDIF}
   {$IF DEFINED(GLB_WIN) AND
-       DEFINED(GLB_NATIVE_OGL)} windows,                  {$IFEND}
+       (DEFINED(GLB_NATIVE_OGL) OR
+        DEFINED(GLB_DELPHI))}   windows,                            {$IFEND}
 
-  {$IFDEF GLB_SDL}              SDL,                      {$ENDIF}
-  {$IFDEF GLB_LAZARUS}          IntfGraphics, GraphType,  {$ENDIF}
-  {$IFDEF GLB_DELPHI}           Dialogs, Graphics,        {$ENDIF}
+  {$IFDEF GLB_SDL}              SDL,                                {$ENDIF}
+  {$IFDEF GLB_LAZARUS}          IntfGraphics, GraphType, Graphics,  {$ENDIF}
+  {$IFDEF GLB_DELPHI}           Dialogs, Graphics, Types,           {$ENDIF}
 
-  {$IFDEF GLB_SDL_IMAGE}        SDL_image,                {$ENDIF}
-  {$IFDEF GLB_PNGIMAGE}         pngimage,                 {$ENDIF}
-  {$IFDEF GLB_LIB_PNG}          libPNG,                   {$ENDIF}
-  {$IFDEF GLB_DELPHI_JPEG}      JPEG,                     {$ENDIF}
-  {$IFDEF GLB_LIB_JPEG}         libJPEG,                  {$ENDIF}
+  {$IFDEF GLB_SDL_IMAGE}        SDL_image,                          {$ENDIF}
+  {$IFDEF GLB_PNGIMAGE}         pngimage,                           {$ENDIF}
+  {$IFDEF GLB_LIB_PNG}          libPNG,                             {$ENDIF}
+  {$IFDEF GLB_DELPHI_JPEG}      JPEG,                               {$ENDIF}
+  {$IFDEF GLB_LIB_JPEG}         libJPEG,                            {$ENDIF}
 
   Classes, SysUtils;
 
@@ -795,6 +860,7 @@ type
    EglBitmapSizeToLarge       = class(EglBitmap);
    EglBitmapNonPowerOfTwo     = class(EglBitmap);
    EglBitmapUnsupportedFormat = class(EglBitmap)
+   public
      constructor Create(const aFormat: TglBitmapFormat); overload;
      constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload;
    end;
@@ -823,6 +889,9 @@ type
   TglBitmapFormatDescriptor = class(TObject)
   protected
     function GetIsCompressed: Boolean; virtual; abstract;
+    function GetHasRed:       Boolean; virtual; abstract;
+    function GetHasGreen:     Boolean; virtual; abstract;
+    function GetHasBlue:      Boolean; virtual; abstract;
     function GetHasAlpha:     Boolean; virtual; abstract;
 
     function GetglDataFormat:     GLenum;  virtual; abstract;
@@ -830,6 +899,9 @@ type
     function GetglInternalFormat: GLenum;  virtual; abstract;
   public
     property IsCompressed: Boolean read GetIsCompressed;
+    property HasRed:       Boolean read GetHasRed;
+    property HasGreen:     Boolean read GetHasGreen;
+    property HasBlue:      Boolean read GetHasBlue;
     property HasAlpha:     Boolean read GetHasAlpha;
 
     property glFormat:         GLenum  read GetglFormat;
@@ -858,9 +930,10 @@ type
     fTarget: GLuint;
     fAnisotropic: Integer;
     fDeleteTextureOnFree: Boolean;
+    fFreeDataOnDestroy: Boolean;
     fFreeDataAfterGenTexture: Boolean;
     fData: PByte;
-    fIsResident: Boolean;
+    fIsResident: GLboolean;
     fBorderColor: array[0..3] of Single;
 
     fDimension: TglBitmapPixelPosition;
@@ -900,6 +973,7 @@ type
     procedure SetCustomData(const aValue: Pointer);
     procedure SetCustomName(const aValue: String);
     procedure SetCustomNameW(const aValue: WideString);
+    procedure SetFreeDataOnDestroy(const aValue: Boolean);
     procedure SetDeleteTextureOnFree(const aValue: Boolean);
     procedure SetFormat(const aValue: TglBitmapFormat);
     procedure SetFreeDataAfterGenTexture(const aValue: Boolean);
@@ -938,11 +1012,12 @@ type
     property CustomData:  Pointer    read fCustomData  write SetCustomData;
 
     property DeleteTextureOnFree:     Boolean read fDeleteTextureOnFree     write SetDeleteTextureOnFree;
+    property FreeDataOnDestroy:       Boolean read fFreeDataOnDestroy       write SetFreeDataOnDestroy;
     property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture;
 
     property Dimension:  TglBitmapPixelPosition  read fDimension;
     property Data:       PByte                   read fData;
-    property IsResident: Boolean                 read fIsResident;
+    property IsResident: GLboolean               read fIsResident;
 
     procedure AfterConstruction; override;
     procedure BeforeDestruction; override;
@@ -1038,7 +1113,7 @@ type
     constructor Create; 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; aData: PByte = nil); overload;
     constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); 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;
@@ -1160,7 +1235,9 @@ function CreateGrayPalette: HPALETTE;
 implementation
 
 uses
-  Math, syncobjs, typinfo;
+  Math, syncobjs, typinfo
+  {$IFDEF GLB_DELPHI}, Types{$ENDIF}
+  {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND};
 
 type
 {$IFNDEF fpc}
@@ -1201,6 +1278,9 @@ type
     fglDataFormat:     GLenum;
 
     function GetIsCompressed: Boolean; override;
+    function GetHasRed: Boolean; override;
+    function GetHasGreen: Boolean; override;
+    function GetHasBlue: Boolean; override;
     function GetHasAlpha: Boolean; override;
 
     function GetglFormat: GLenum; override;
@@ -1228,7 +1308,7 @@ type
     procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract;
 
     function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual;
-    function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual; 
+    function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual;
 
     function CreateMappingData: Pointer; virtual;
     procedure FreeMappingData(var aMappingData: Pointer); virtual;
@@ -1880,7 +1960,7 @@ end;
 var
   GL_LibHandle: Pointer = nil;
 
-function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer;
+function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer;
 begin
   if not Assigned(aLibHandle) then
     aLibHandle := GL_LibHandle;
@@ -1907,7 +1987,7 @@ begin
 
   result := dlsym(aLibHandle, aProcName);
 {$IFEND}
-  if not Assigned(result) then
+  if not Assigned(result) and aRaiseOnErr then
     raise EglBitmap.Create('unable to load procedure form library: ' + aProcName);
 end;
 
@@ -1961,42 +2041,37 @@ begin
   if not Assigned(GLU_LibHandle) then
     raise EglBitmap.Create('unable to load library: ' + libglu);
 
-  try
-  {$IF DEFINED(GLB_WIN)}
-    wglGetProcAddress    := glbGetProcAddress('wglGetProcAddress');
-  {$ELSEIF DEFINED(GLB_LINUX)}
-    glXGetProcAddress    := glbGetProcAddress('glXGetProcAddress');
-    glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
-  {$IFEND}
-
-    glEnable := glbGetProcAddress('glEnable');
-    glDisable := glbGetProcAddress('glDisable');
-    glGetString := glbGetProcAddress('glGetString');
-    glGetIntegerv := glbGetProcAddress('glGetIntegerv');
-    glTexParameteri := glbGetProcAddress('glTexParameteri');
-    glTexParameteriv := glbGetProcAddress('glTexParameteriv');
-    glTexParameterfv := glbGetProcAddress('glTexParameterfv');
-    glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
-    glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
-    glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
-    glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
-    glTexGeni := glbGetProcAddress('glTexGeni');
-    glGenTextures := glbGetProcAddress('glGenTextures');
-    glBindTexture := glbGetProcAddress('glBindTexture');
-    glDeleteTextures := glbGetProcAddress('glDeleteTextures');
-    glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
-    glReadPixels := glbGetProcAddress('glReadPixels');
-    glPixelStorei := glbGetProcAddress('glPixelStorei');
-    glTexImage1D := glbGetProcAddress('glTexImage1D');
-    glTexImage2D := glbGetProcAddress('glTexImage2D');
-    glGetTexImage := glbGetProcAddress('glGetTexImage');
-
-    gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
-    gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
-  finally
-    glbFreeLibrary(GL_LibHandle);
-    glbFreeLibrary(GLU_LibHandle);
-  end;
+{$IF DEFINED(GLB_WIN)}
+  wglGetProcAddress    := glbGetProcAddress('wglGetProcAddress');
+{$ELSEIF DEFINED(GLB_LINUX)}
+  glXGetProcAddress    := glbGetProcAddress('glXGetProcAddress');
+  glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB');
+{$IFEND}
+
+  glEnable := glbGetProcAddress('glEnable');
+  glDisable := glbGetProcAddress('glDisable');
+  glGetString := glbGetProcAddress('glGetString');
+  glGetIntegerv := glbGetProcAddress('glGetIntegerv');
+  glTexParameteri := glbGetProcAddress('glTexParameteri');
+  glTexParameteriv := glbGetProcAddress('glTexParameteriv');
+  glTexParameterfv := glbGetProcAddress('glTexParameterfv');
+  glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv');
+  glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv');
+  glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv');
+  glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv');
+  glTexGeni := glbGetProcAddress('glTexGeni');
+  glGenTextures := glbGetProcAddress('glGenTextures');
+  glBindTexture := glbGetProcAddress('glBindTexture');
+  glDeleteTextures := glbGetProcAddress('glDeleteTextures');
+  glAreTexturesResident := glbGetProcAddress('glAreTexturesResident');
+  glReadPixels := glbGetProcAddress('glReadPixels');
+  glPixelStorei := glbGetProcAddress('glPixelStorei');
+  glTexImage1D := glbGetProcAddress('glTexImage1D');
+  glTexImage2D := glbGetProcAddress('glTexImage2D');
+  glGetTexImage := glbGetProcAddress('glGetTexImage');
+
+  gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle);
+  gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle);
 end;
 {$ENDIF}
 
@@ -2099,9 +2174,9 @@ begin
     glCompressedTexImage2D  := glbGetProcAddress('glCompressedTexImage2D');
     glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage');
   end else begin
-    glCompressedTexImage1D  := glbGetProcAddress('glCompressedTexImage1DARB');
-    glCompressedTexImage2D  := glbGetProcAddress('glCompressedTexImage2DARB');
-    glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB');
+    glCompressedTexImage1D  := glbGetProcAddress('glCompressedTexImage1DARB',  nil, false);
+    glCompressedTexImage2D  := glbGetProcAddress('glCompressedTexImage2DARB',  nil, false);
+    glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false);
   end;
 end;
 {$ENDIF}
@@ -2242,7 +2317,7 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//TglBitmapFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TFormatDescriptor.GetRedMask: QWord;
 begin
@@ -2274,6 +2349,24 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetHasRed: Boolean;
+begin
+  result := (fRange.r > 0);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetHasGreen: Boolean;
+begin
+  result := (fRange.g > 0);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TFormatDescriptor.GetHasBlue: Boolean;
+begin
+  result := (fRange.b > 0);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TFormatDescriptor.GetHasAlpha: Boolean;
 begin
   result := (fRange.a > 0);
@@ -4114,6 +4207,14 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean);
+begin
+  if fFreeDataOnDestroy = aValue then
+    exit;
+  fFreeDataOnDestroy := aValue;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean);
 begin
   if fDeleteTextureOnFree = aValue then
@@ -4228,12 +4329,11 @@ begin
     fData := aData;
   end;
 
-  FillChar(fDimension, SizeOf(fDimension), 0);
   if not Assigned(fData) then begin
-    fFormat    := tfEmpty;
     fPixelSize := 0;
     fRowSize   := 0;
   end else begin
+    FillChar(fDimension, SizeOf(fDimension), 0);
     if aWidth <> -1 then begin
       fDimension.Fields := fDimension.Fields + [ffX];
       fDimension.X := aWidth;
@@ -4274,7 +4374,6 @@ begin
   fTarget     := 0;
   fIsResident := false;
 
-  fFormat                  := glBitmapGetDefaultFormat;
   fMipMap                  := glBitmapDefaultMipmap;
   fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture;
   fDeleteTextureOnFree     := glBitmapGetDefaultDeleteTextureOnFree;
@@ -4289,8 +4388,10 @@ procedure TglBitmap.BeforeDestruction;
 var
   NewData: PByte;
 begin
-  NewData := nil;
-  SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
+  if fFreeDataOnDestroy then begin
+    NewData := nil;
+    SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method
+  end;
   if (fID > 0) and fDeleteTextureOnFree then
     glDeleteTextures(1, @fID);
   inherited BeforeDestruction;
@@ -4357,7 +4458,7 @@ begin
       FreeMem(tmpData);
     raise;
   end;
-  AddFunc(Self, aFunc, false, Format, aArgs);
+  AddFunc(Self, aFunc, false, aFormat, aArgs);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -4713,7 +4814,7 @@ begin
         tfRGBA8, tfBGRA8:
           aBitmap.PixelFormat := pf32bit;
       else
-        raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.');
+        raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.');
       end;
 
       pSource := Data;
@@ -4751,7 +4852,7 @@ begin
       pf32bit:
         IntFormat := tfBGRA8;
     else
-      raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.');
+      raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.');
     end;
 
     TempWidth  := aBitmap.Width;
@@ -4815,7 +4916,7 @@ begin
               Inc(pSource);
             end;
           end;
-        end;   
+        end;
         result := true;
       end;
     end;
@@ -4862,7 +4963,7 @@ begin
 
   rid.Width        := Width;
   rid.Height       := Height;
-  rid.Depth        := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a);
+  rid.Depth        := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask);
   rid.BitOrder     := riboBitsInOrder;
   rid.ByteOrder    := riboLSBFirst;
   rid.LineOrder    := riloTopToBottom;
@@ -4895,6 +4996,42 @@ var
   FormatDesc: TFormatDescriptor;
   ImageData: PByte;
   ImageSize: Integer;
+  CanCopy: Boolean;
+
+  procedure CopyConvert;
+  var
+    bfFormat: TbmpBitfieldFormat;
+    pSourceLine, pDestLine: PByte;
+    pSourceMD, pDestMD: Pointer;
+    x, y: Integer;
+    pixel: TglBitmapPixelData;
+  begin
+    bfFormat  := TbmpBitfieldFormat.Create;
+    with aImage.DataDescription do begin
+      bfFormat.RedMask   := ((1 shl RedPrec)   - 1) shl RedShift;
+      bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift;
+      bfFormat.BlueMask  := ((1 shl BluePrec)  - 1) shl BlueShift;
+      bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift;
+      bfFormat.PixelSize := BitsPerPixel / 8;
+    end;
+    pSourceMD := bfFormat.CreateMappingData;
+    pDestMD   := FormatDesc.CreateMappingData;
+    try
+      for y := 0 to aImage.Height-1 do begin
+        pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine;
+        pDestLine   := ImageData        + y * Round(FormatDesc.PixelSize * aImage.Width);
+        for x := 0 to aImage.Width-1 do begin
+          bfFormat.Unmap(pSourceLine, pixel, pSourceMD);
+          FormatDesc.Map(pixel, pDestLine, pDestMD);
+        end;
+      end;
+    finally
+      FormatDesc.FreeMappingData(pDestMD);
+      bfFormat.FreeMappingData(pSourceMD);
+      bfFormat.Free;
+    end;
+  end;
+
 begin
   result := false;
   if not Assigned(aImage) then
@@ -4913,10 +5050,17 @@ begin
   if (f = tfEmpty) then
     exit;
 
+  CanCopy :=
+    (Round(FormatDesc.PixelSize * 8)     = aImage.DataDescription.Depth) and
+    (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth);
+
   ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height);
   ImageData := GetMem(ImageSize);
   try
-    Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3);
+    if CanCopy then
+      Move(aImage.PixelData^, ImageData^, ImageSize)
+    else
+      CopyConvert;
     SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method
   except
     if Assigned(ImageData) then
@@ -5350,8 +5494,8 @@ procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean);
 begin
   if aUseRGB or aUseAlpha then
     AddFunc(glBitmapInvertFunc, false, {%H-}Pointer(
-      ((PtrInt(aUseAlpha) and 1) shl 1) or
-       (PtrInt(aUseRGB)   and 1)      ));
+      ((Byte(aUseAlpha) and 1) shl 1) or
+       (Byte(aUseRGB)   and 1)      ));
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -5533,7 +5677,7 @@ begin
 
   if (ID > 0) then begin
     Bind(false);
-    glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]);
+    glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0]));
   end;
 end;
 
@@ -5563,6 +5707,8 @@ begin
   glbReadOpenGLExtensions;
 {$ENDIF}
   inherited Create;
+  fFormat            := glBitmapGetDefaultFormat;
+  fFreeDataOnDestroy := true;
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -5580,27 +5726,30 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat);
+constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte);
 var
-  Image: PByte;
   ImageSize: Integer;
 begin
   Create;
-  ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
-  GetMem(Image, ImageSize);
-  try
-    FillChar(Image^, ImageSize, #$FF);
-    SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
-  except
-    if Assigned(Image) then
-      FreeMem(Image);
-    raise;
+  if not Assigned(aData) then begin
+    ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize);
+    GetMem(aData, ImageSize);
+    try
+      FillChar(aData^, ImageSize, #$FF);
+      SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
+    except
+      if Assigned(aData) then
+        FreeMem(aData);
+      raise;
+    end;
+  end else begin
+    SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method
+    fFreeDataOnDestroy := false;
   end;
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat;
-  const aFunc: TglBitmapFunction; const aArgs: Pointer);
+constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer);
 begin
   Create;
   LoadFromFunc(aSize, aFunc, aFormat, aArgs);
@@ -5621,11 +5770,51 @@ begin
 end;
 
 {$IFDEF GLB_SUPPORT_PNG_READ}
-{$IF DEFINED(GLB_SDL_IMAGE)}
+{$IF DEFINED(GLB_LAZ_PNG)}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //PNG/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
+const
+  MAGIC_LEN = 8;
+  PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A;
+var
+  reader: TLazReaderPNG;
+  intf: TLazIntfImage;
+  StreamPos: Int64;
+  magic: String[MAGIC_LEN];
+begin
+  result := true;
+  StreamPos := aStream.Position;
+
+  SetLength(magic, MAGIC_LEN);
+  aStream.Read(magic[1], MAGIC_LEN);
+  aStream.Position := StreamPos;
+  if (magic <> PNG_MAGIC) then begin
+    result := false;
+    exit;
+  end;
+
+  intf   := TLazIntfImage.Create(0, 0);
+  reader := TLazReaderPNG.Create;
+  try try
+    reader.UpdateDescription := true;
+    reader.ImageRead(aStream, intf);
+    AssignFromLazIntfImage(intf);
+  except
+    result := false;
+    aStream.Position := StreamPos;
+    exit;
+  end;
+  finally
+    reader.Free;
+    intf.Free;
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_SDL_IMAGE)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
 var
   Surface: PSDL_Surface;
   RWops: PSDL_RWops;
@@ -5699,7 +5888,7 @@ begin
       // read informations
       png_read_info(png, png_info);
 
-      // size 
+      // size
       TempHeight := png_get_image_height(png, png_info);
       TempWidth := png_get_image_width(png, png_info);
 
@@ -5866,7 +6055,29 @@ begin
 end;
 {$ENDIF}
 
-{$IF DEFINED(GLB_LIB_PNG)}
+{$IF DEFINED(GLB_LAZ_PNG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SavePNG(const aStream: TStream);
+var
+  png: TPortableNetworkGraphic;
+  intf: TLazIntfImage;
+  raw: TRawImage;
+begin
+  png  := TPortableNetworkGraphic.Create;
+  intf := TLazIntfImage.Create(0, 0);
+  try
+    if not AssignToLazIntfImage(intf) then
+      raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
+    intf.GetRawImage(raw);
+    png.LoadFromRawImage(raw, false);
+    png.SaveToStream(aStream);
+  finally
+    png.Free;
+    intf.Free;
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_LIB_PNG)}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.SavePNG(const aStream: TStream);
 var
@@ -6156,7 +6367,47 @@ end;
 {$ENDIF}
 
 {$IFDEF GLB_SUPPORT_JPEG_READ}
-{$IF DEFINED(GLB_SDL_IMAGE)}
+{$IF DEFINED(GLB_LAZ_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
+const
+  MAGIC_LEN = 2;
+  JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8;
+var
+  intf: TLazIntfImage;
+  reader: TFPReaderJPEG;
+  StreamPos: Int64;
+  magic: String[MAGIC_LEN];
+begin
+  result := true;
+  StreamPos := aStream.Position;
+
+  SetLength(magic, MAGIC_LEN);
+  aStream.Read(magic[1], MAGIC_LEN);
+  aStream.Position := StreamPos;
+  if (magic <> JPEG_MAGIC) then begin
+    result := false;
+    exit;
+  end;
+
+  reader := TFPReaderJPEG.Create;
+  intf := TLazIntfImage.Create(0, 0);
+  try try
+    intf.DataDescription := GetDescriptionFromDevice(0, 0, 0);
+    reader.ImageRead(aStream, intf);
+    AssignFromLazIntfImage(intf);
+  except
+    result := false;
+    aStream.Position := StreamPos;
+    exit;
+  end;
+  finally
+    reader.Free;
+    intf.Free;
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_SDL_IMAGE)}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function TglBitmap.LoadJPEG(const aStream: TStream): Boolean;
 var
@@ -6334,7 +6585,29 @@ end;
 {$ENDIF}
 
 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
-{$IF DEFINED(GLB_LIB_JPEG)}
+{$IF DEFINED(GLB_LAZ_JPEG)}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TglBitmap.SaveJPEG(const aStream: TStream);
+var
+  jpeg: TJPEGImage;
+  intf: TLazIntfImage;
+  raw: TRawImage;
+begin
+  jpeg := TJPEGImage.Create;
+  intf := TLazIntfImage.Create(0, 0);
+  try
+    if not AssignToLazIntfImage(intf) then
+      raise EglBitmap.Create('unable to create LazIntfImage from glBitmap');
+    intf.GetRawImage(raw);
+    jpeg.LoadFromRawImage(raw, false);
+    jpeg.SaveToStream(aStream);
+  finally
+    intf.Free;
+    jpeg.Free;
+  end;
+end;
+
+{$ELSEIF DEFINED(GLB_LIB_JPEG)}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TglBitmap.SaveJPEG(const aStream: TStream);
 var
@@ -6713,7 +6986,7 @@ procedure TglBitmap.SaveBMP(const aStream: TStream);
 var
   Header: TBMPHeader;
   Info: TBMPInfo;
-  Converter: TbmpColorTableFormat;
+  Converter: TFormatDescriptor;
   FormatDesc: TFormatDescriptor;
   SourceFD, DestFD: Pointer;
   pData, srcData, dstData, ConvertBuffer: pByte;
@@ -6758,26 +7031,30 @@ begin
         Info.biBitCount  := 4;
         Header.bfSize    := Header.bfSize    + 16 * SizeOf(Cardinal);
         Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries
-        Converter           := TbmpColorTableFormat.Create;
-        Converter.PixelSize := 0.5;
-        Converter.Format    := Format;
-        Converter.Range     := glBitmapColorRec($F, $F, $F, $0);
-        Converter.CreateColorTable;
+        Converter := TbmpColorTableFormat.Create;
+        with (Converter as TbmpColorTableFormat) do begin
+          PixelSize := 0.5;
+          Format    := Format;
+          Range     := glBitmapColorRec($F, $F, $F, $0);
+          CreateColorTable;
+        end;
       end;
 
       tfR3G3B2, tfLuminance8: begin
         Info.biBitCount  :=  8;
         Header.bfSize    := Header.bfSize    + 256 * SizeOf(Cardinal);
         Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries
-        Converter           := TbmpColorTableFormat.Create;
-        Converter.PixelSize := 1;
-        Converter.Format    := Format;
-        if (Format = tfR3G3B2) then begin
-          Converter.Range := glBitmapColorRec($7, $7, $3, $0);
-          Converter.Shift := glBitmapShiftRec(0, 3, 6, 0);
-        end else
-          Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0);
-        Converter.CreateColorTable;
+        Converter := TbmpColorTableFormat.Create;
+        with (Converter as TbmpColorTableFormat) do begin
+          PixelSize := 1;
+          Format    := Format;
+          if (Format = tfR3G3B2) then begin
+            Range := glBitmapColorRec($7, $7, $3, $0);
+            Shift := glBitmapShiftRec(0, 3, 6, 0);
+          end else
+            Range := glBitmapColorRec($FF, $FF, $FF, $0);
+          CreateColorTable;
+        end;
       end;
 
       tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4,
@@ -6788,6 +7065,8 @@ begin
 
       tfBGR8, tfRGB8: begin
         Info.biBitCount := 24;
+        if (Format = tfRGB8) then
+          Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values
       end;
 
       tfRGB10, tfRGB10A2, tfRGBA8,
@@ -6817,9 +7096,10 @@ begin
     aStream.Write(Info, SizeOf(Info));
 
     // colortable
-    if Assigned(Converter) then
-      aStream.Write(Converter.ColorTable[0].b,
-        SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable));
+    if Assigned(Converter) and (Converter is TbmpColorTableFormat) then
+      with (Converter as TbmpColorTableFormat) do
+        aStream.Write(ColorTable[0].b,
+          SizeOf(TbmpColorTableEnty) * Length(ColorTable));
 
     // bitmasks
     if Info.biCompression = BMP_COMP_BITFIELDS then begin
@@ -7107,7 +7387,7 @@ begin
       if Header.ImageID <> 0 then       // skip image ID
         aStream.Position := aStream.Position + Header.ImageID;
 
-      tgaFormat := tfEmpty;        
+      tgaFormat := tfEmpty;
       case Header.Bpp of
          8: if IsGrayFormat then case (Header.ImageDesc and $F) of
                0: tgaFormat := tfLuminance8;
@@ -7626,9 +7906,11 @@ var
 begin
   // Upload data
   FormatDesc := TFormatDescriptor.Get(Format);
-  if FormatDesc.IsCompressed then
+  if FormatDesc.IsCompressed then begin
+    if not Assigned(glCompressedTexImage1D) then
+      raise EglBitmap.Create('compressed formats not supported by video adapter');
     glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data)
-  else if aBuildWithGlu then
+  end else if aBuildWithGlu then
     gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
   else
     glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
@@ -7717,6 +7999,8 @@ begin
 
   FormatDesc := TFormatDescriptor.Get(Format);
   if FormatDesc.IsCompressed then begin
+    if not Assigned(glCompressedTexImage2D) then
+      raise EglBitmap.Create('compressed formats not supported by video adapter');
     glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
   end else if aBuildWithGlu then begin
     gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
@@ -7770,7 +8054,7 @@ procedure TglBitmap2D.GetDataFromTexture;
 var
   Temp: PByte;
   TempWidth, TempHeight: Integer;
-  TempIntFormat: Cardinal;
+  TempIntFormat: GLint;
   IntFormat, f: TglBitmapFormat;
   FormatDesc: TFormatDescriptor;
 begin
@@ -7794,10 +8078,12 @@ begin
   FormatDesc := TFormatDescriptor.Get(IntFormat);
   GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
   try
-    if FormatDesc.IsCompressed then
+    if FormatDesc.IsCompressed then begin
+      if not Assigned(glGetCompressedTexImage) then
+        raise EglBitmap.Create('compressed formats not supported by video adapter');
       glGetCompressedTexImage(Target, 0, Temp)
-    else
-     glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
+    end else
+      glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp);
     SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method
   except
     if Assigned(Temp) then
@@ -8349,9 +8635,15 @@ initialization
 finalization
   TFormatDescriptor.Finalize;
 
+{$IFDEF GLB_NATIVE_OGL}
+  if Assigned(GL_LibHandle) then
+    glbFreeLibrary(GL_LibHandle);
+
 {$IFDEF GLB_NATIVE_OGL_DYNAMIC}
+  if Assigned(GLU_LibHandle) then
+    glbFreeLibrary(GLU_LibHandle);
   FreeAndNil(InitOpenGLCS);
 {$ENDIF}
+{$ENDIF}  
 
 end.
-