* implemented RAW file format
[glBitmap.git] / glBitmap.pas
index bde9922..759a404 100644 (file)
@@ -859,7 +859,8 @@ type
      {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF}
      ftDDS,
      ftTGA,
-     ftBMP);
+     ftBMP,
+     ftRAW);
    TglBitmapFileTypes = set of TglBitmapFileType;
 
    TglBitmapMipMap = (
@@ -1201,14 +1202,17 @@ type
     {$IFDEF GLB_SUPPORT_JPEG_READ}  function  LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF}
     {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF}
 
-    function LoadBMP(const aStream: TStream): Boolean; virtual;
-    procedure SaveBMP(const aStream: TStream); virtual;
+    function LoadRAW(const aStream: TStream): Boolean;
+    procedure SaveRAW(const aStream: TStream);
 
-    function LoadTGA(const aStream: TStream): Boolean; virtual;
-    procedure SaveTGA(const aStream: TStream); virtual;
+    function LoadBMP(const aStream: TStream): Boolean;
+    procedure SaveBMP(const aStream: TStream);
 
-    function LoadDDS(const aStream: TStream): Boolean; virtual;
-    procedure SaveDDS(const aStream: TStream); virtual;
+    function LoadTGA(const aStream: TStream): Boolean;
+    procedure SaveTGA(const aStream: TStream);
+
+    function LoadDDS(const aStream: TStream): Boolean;
+    procedure SaveDDS(const aStream: TStream);
   end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1293,6 +1297,7 @@ function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosit
 function glBitmapRec4ub(const r, g, b, a: Byte): TglBitmapRec4ub;
 function glBitmapRec4ui(const r, g, b, a: Cardinal): TglBitmapRec4ui;
 function glBitmapRec4ul(const r, g, b, a: QWord): TglBitmapRec4ul;
+function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
 
 function glBitmapCreateTestTexture(const aFormat: TglBitmapFormat): TglBitmap2D;
@@ -1344,11 +1349,14 @@ type
     function MaskMatch(const aMask: TglBitmapRec4ul): Boolean; virtual;
 
     procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual;
+
+    constructor Create; virtual;
   public
     class procedure Init;
     class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor;
     class function GetAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor;
     class function GetFromMask(const aMask: TglBitmapRec4ul; const aBitCount: Integer = 0): TFormatDescriptor;
+    class function GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
     class procedure Clear;
     class procedure Finalize;
   end;
@@ -1890,6 +1898,18 @@ begin
 end;
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function glBitmapRec4ubCompare(const r1, r2: TglBitmapRec4ub): Boolean;
+var
+  i: Integer;
+begin
+  result := false;
+  for i := 0 to high(r1.arr) do
+    if (r1.arr[i] <> r2.arr[i]) then
+      exit;
+  result := true;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function glBitmapRec4uiCompare(const r1, r2: TglBitmapRec4ui): Boolean;
 var
   i: Integer;
@@ -2494,6 +2514,12 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TFormatDescriptor.Create;
+begin
+  inherited Create;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //TfdAlpha_UB1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 procedure TfdAlphaUB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
@@ -3869,7 +3895,7 @@ end;
 
 procedure TfdS3tcDtx5RGBA.SetValues;
 begin
-  inherited Create;
+  inherited SetValues;
   fFormat           := tfS3tcDtx3RGBA;
   fWithAlpha        := tfS3tcDtx3RGBA;
   fOpenGLFormat     := tfS3tcDtx3RGBA;
@@ -4022,7 +4048,36 @@ begin
       exit;
   end;
 
-  result := FormatDescriptors[tfEmpty];
+  result := TFormatDescriptor.Get(tfEmpty);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+class function TFormatDescriptor.GetFromPrecShift(const aPrec, aShift: TglBitmapRec4ub; const aBitCount: Integer): TFormatDescriptor;
+var
+  ft: TglBitmapFormat;
+begin
+  // find matching format with OpenGL support
+  for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
+    result := Get(ft);
+    if glBitmapRec4ubCompare(result.Shift,     aShift) and
+       glBitmapRec4ubCompare(result.Precision, aPrec) and
+       (result.glFormat <> 0)         and
+       (result.glInternalFormat <> 0) and
+       ((aBitCount = 0) or (aBitCount = result.BitsPerPixel))
+    then
+      exit;
+  end;
+
+  // find matching format without OpenGL Support
+  for ft := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin
+    result := Get(ft);
+    if glBitmapRec4ubCompare(result.Shift,     aShift) and
+       glBitmapRec4ubCompare(result.Precision, aPrec)  and
+       ((aBitCount = 0) or (aBitCount = result.BitsPerPixel)) then
+      exit;
+  end;
+
+  result := TFormatDescriptor.Get(tfEmpty);
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -4653,6 +4708,7 @@ begin
   if not LoadDDS(aStream) then
   if not LoadTGA(aStream) then
   if not LoadBMP(aStream) then
+  if not LoadRAW(aStream) then
     raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.');
 end;
 
@@ -4730,6 +4786,7 @@ begin
     ftDDS:  SaveDDS(aStream);
     ftTGA:  SaveTGA(aStream);
     ftBMP:  SaveBMP(aStream);
+    ftRAW:  SaveRAW(aStream);
   end;
 end;
 
@@ -6978,6 +7035,65 @@ end;
 {$ENDIF}
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//RAW/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+type
+  RawHeader = packed record
+    Magic:        String[5];
+    Version:      Byte;
+    Width:        Integer;
+    Height:       Integer;
+    DataSize:     Integer;
+    BitsPerPixel: Integer;
+    Precision:    TglBitmapRec4ub;
+    Shift:        TglBitmapRec4ub;
+  end;
+
+function TglBitmap.LoadRAW(const aStream: TStream): Boolean;
+var
+  header: RawHeader;
+  StartPos: Int64;
+  fd: TFormatDescriptor;
+  buf: PByte;
+begin
+  result := false;
+  StartPos := aStream.Position;
+  aStream.Read(header{%H-}, SizeOf(header));
+  if (header.Magic <> 'glBMP') then begin
+    aStream.Position := StartPos;
+    exit;
+  end;
+
+  fd := TFormatDescriptor.GetFromPrecShift(header.Precision, header.Shift, header.BitsPerPixel);
+  if (fd.Format = tfEmpty) then
+    raise EglBitmapUnsupportedFormat.Create('no supported format found');
+
+  buf := GetMem(header.DataSize);
+  aStream.Read(buf^, header.DataSize);
+  SetDataPointer(buf, fd.Format, header.Width, header.Height);
+
+  result := true;
+end;
+
+procedure TglBitmap.SaveRAW(const aStream: TStream);
+var
+  header: RawHeader;
+  fd: TFormatDescriptor;
+begin
+  fd := TFormatDescriptor.Get(Format);
+  header.Magic        := 'glBMP';
+  header.Version      := 1;
+  header.Width        := Width;
+  header.Height       := Height;
+  header.DataSize     := fd.GetSize(fDimension);
+  header.BitsPerPixel := fd.BitsPerPixel;
+  header.Precision    := fd.Precision;
+  header.Shift        := fd.Shift;
+  aStream.Write(header, SizeOf(header));
+  aStream.Write(Data^,  header.DataSize);
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //BMP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 const