* added pngimage Support
[glBitmap.git] / glBitmap.pas
index 5bfb8e7..f745956 100644 (file)
@@ -245,21 +245,21 @@ unit glBitmap;
 // If you enable SDL_image all other libraries will be ignored!
 {.$DEFINE GLB_SDL_IMAGE}
 
-// activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/
+// 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}
+{$DEFINE GLB_PNGIMAGE}
 
-// activate to use the libPNG http://www.libpng.org/
-// You will need an aditional header.
-// http://www.opengl24.de/index.php?cat=header&file=libpng
-{$DEFINE GLB_LIB_PNG}
+// activate to use the libPNG -> http://www.libpng.org/
+// You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng
+{.$DEFINE GLB_LIB_PNG}
 
+// JPEG ////////////////////////////////////////////////////////////////////////////////////////////
 // if you enable delphi jpegs the libJPEG will be ignored
 {.$DEFINE GLB_DELPHI_JPEG}
 
-// activateto use the libJPEG http://www.ijg.org/
-// You will need an aditional header.
-// http://www.opengl24.de/index.php?cat=header&file=libjpeg
+// activate to use the libJPEG -> http://www.ijg.org/
+// You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg
 {.$DEFINE GLB_LIB_JPEG}
 
 
@@ -1660,7 +1660,7 @@ var
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat);
 begin
-  inherited Create(GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
+  inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat)));
 end;
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1777,17 +1777,10 @@ begin
     result := result + [ftPNG];
   {$ENDIF}
 
-(* TODO
   {$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
+  if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then
     result := result + [ftJPEG];
   {$ENDIF}
-  *)
 end;
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -5543,7 +5536,7 @@ begin
   try
     // signature
     StreamPos := aStream.Position;
-    aStream.Read(signature, 8);
+    aStream.Read(signature{%H-}, 8);
     aStream.Position := StreamPos;
 
     if png_check_sig(@signature, 8) <> 0 then begin
@@ -5632,42 +5625,44 @@ function TglBitmap.LoadPNG(const aStream: TStream): Boolean;
 var
   StreamPos: Int64;
   Png: TPNGObject;
-  Header: Array[0..7] of Byte;
+  Header: String[8];
   Row, Col, PixSize, LineSize: Integer;
   NewImage, pSource, pDest, pAlpha: pByte;
-  Format: TglBitmapInternalFormat;
+  PngFormat: TglBitmapFormat;
+  FormatDesc: TFormatDescriptor;
 
 const
-  PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10);
+  PngHeader: String[8] = #137#80#78#71#13#10#26#10;
 
 begin
   result := false;
 
-  StreamPos := Stream.Position;
-  Stream.Read(Header[0], SizeOf(Header));
-  Stream.Position := StreamPos;
+  StreamPos := aStream.Position;
+  aStream.Read(Header[0], SizeOf(Header));
+  aStream.Position := StreamPos;
 
   {Test if the header matches}
   if Header = PngHeader then begin
     Png := TPNGObject.Create;
     try
-      Png.LoadFromStream(Stream);
+      Png.LoadFromStream(aStream);
 
       case Png.Header.ColorType of
         COLOR_GRAYSCALE:
-          Format := ifLuminance;
+          PngFormat := tfLuminance8;
         COLOR_GRAYSCALEALPHA:
-          Format := ifLuminanceAlpha;
+          PngFormat := tfLuminance8Alpha8;
         COLOR_RGB:
-          Format := ifBGR8;
+          PngFormat := tfBGR8;
         COLOR_RGBALPHA:
-          Format := ifBGRA8;
+          PngFormat := tfBGRA8;
         else
           raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
       end;
 
-      PixSize := Trunc(FormatGetSize(Format));
-      LineSize := Integer(Png.Header.Width) * PixSize;
+      FormatDesc := TFormatDescriptor.Get(PngFormat);
+      PixSize    := Round(FormatDesc.PixelSize);
+      LineSize   := FormatDesc.GetSize(Png.Header.Width, 1);
 
       GetMem(NewImage, LineSize * Integer(Png.Header.Height));
       try
@@ -5704,7 +5699,7 @@ begin
             raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.');
         end;
 
-        SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height);
+        SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height);
 
         result := true;
       except
@@ -5819,32 +5814,32 @@ var
   pTemp: pByte;
   Temp: Byte;
 begin
-  if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+  if not (ftPNG in FormatGetSupportedFiles (Format)) then
+    raise EglBitmapUnsupportedFormat.Create(Format);
 
-  case FInternalFormat of
-    ifAlpha, ifLuminance, ifDepth8: begin
+  case Format of
+    tfAlpha8, tfLuminance8: begin
       ColorType := COLOR_GRAYSCALE;
-      PixSize := 1;
-      Alpha := false;
+      PixSize   := 1;
+      Alpha     := false;
     end;
-    ifLuminanceAlpha: begin
+    tfLuminance8Alpha8: begin
       ColorType := COLOR_GRAYSCALEALPHA;
-      PixSize := 1;
-      Alpha := true;
+      PixSize   := 1;
+      Alpha     := true;
     end;
-    ifBGR8, ifRGB8: begin
+    tfBGR8, tfRGB8: begin
       ColorType := COLOR_RGB;
-      PixSize := 3;
-      Alpha := false;
+      PixSize   := 3;
+      Alpha     := false;
     end;
-    ifBGRA8, ifRGBA8: begin
+    tfBGRA8, tfRGBA8: begin
       ColorType := COLOR_RGBALPHA;
-      PixSize := 3;
-      Alpha := true
+      PixSize   := 3;
+      Alpha     := true
     end;
   else
-    raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT);
+    raise EglBitmapUnsupportedFormat.Create(Format);
   end;
 
   Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height);
@@ -5864,7 +5859,7 @@ begin
       end;
 
       // convert RGB line to BGR
-      if InternalFormat in [ifRGB8, ifRGBA8] then begin
+      if Format in [tfRGB8, tfRGBA8] then begin
         pTemp := png.ScanLine[Y];
         for X := 0 to Width -1 do begin
           Temp := pByteArray(pTemp)^[0];
@@ -5877,7 +5872,7 @@ begin
 
     // Save to Stream
     Png.CompressionLevel := 6;
-    Png.SaveToStream(Stream);
+    Png.SaveToStream(aStream);
   finally
     FreeAndNil(Png);
   end;
@@ -5906,6 +5901,35 @@ type
     DestBuffer: array [1..4096] of byte;
   end;
 
+procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl;
+begin
+  //DUMMY
+end;
+
+
+procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl;
+begin
+  //DUMMY
+end;
+
+
+procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl;
+begin
+  //DUMMY
+end;
+
+procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl;
+begin
+  //DUMMY
+end;
+
+
+procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl;
+begin
+  //DUMMY
+end;
+
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl;
 var
@@ -6024,12 +6048,14 @@ var
   jpeg: jpeg_decompress_struct;
   jpeg_err: jpeg_error_mgr;
 
-  IntFormat: TglBitmapInternalFormat;
+  IntFormat: TglBitmapFormat;
   pImage: pByte;
   TempHeight, TempWidth: Integer;
 
   pTemp: pByte;
   Row: Integer;
+
+  FormatDesc: TFormatDescriptor;
 begin
   result := false;
 
@@ -6038,18 +6064,18 @@ begin
 
   try
     // reading first two bytes to test file and set cursor back to begin
-    StreamPos := Stream.Position;
-    Stream.Read(Temp[0], 2);
-    Stream.Position := StreamPos;
+    StreamPos := aStream.Position;
+    aStream.Read({%H-}Temp[0], 2);
+    aStream.Position := StreamPos;
 
     // if Bitmap then read file.
     if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin
-      FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00);
-      FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00);
+      FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00);
+      FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
 
       // error managment
       jpeg.err := jpeg_std_error(@jpeg_err);
-      jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
+      jpeg_err.error_exit     := glBitmap_libJPEG_error_exit;
       jpeg_err.output_message := glBitmap_libJPEG_output_message;
 
       // decompression struct
@@ -6069,7 +6095,7 @@ begin
         pub.bytes_in_buffer := 0;     // forces fill_input_buffer on first read
         pub.next_input_byte := nil;   // until buffer loaded
 
-        SrcStream := Stream;
+        SrcStream := aStream;
       end;
 
       // set global decoding state
@@ -6083,11 +6109,11 @@ begin
         JCS_GRAYSCALE:
           begin
             jpeg.out_color_space := JCS_GRAYSCALE;
-            IntFormat := ifLuminance;
+            IntFormat := tfLuminance8;
           end;
         else
           jpeg.out_color_space := JCS_RGB;
-          IntFormat := ifRGB8;
+          IntFormat := tfRGB8;
       end;
 
       // reading image
@@ -6096,14 +6122,16 @@ begin
       TempHeight := jpeg.output_height;
       TempWidth := jpeg.output_width;
 
+      FormatDesc := TFormatDescriptor.Get(IntFormat);
+
       // creating new image
-      GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat));
+      GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight));
       try
         pTemp := pImage;
 
         for Row := 0 to TempHeight -1 do begin
           jpeg_read_scanlines(@jpeg, @pTemp, 1);
-          Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth));
+          Inc(pTemp, FormatDesc.GetSize(TempWidth, 1));
         end;
 
         // finish decompression
@@ -6162,9 +6190,9 @@ end;
 {$ENDIF}
 
 {$IFDEF GLB_SUPPORT_JPEG_WRITE}
-{$IF DEFEFINED(GLB_LIB_JPEG)}
+{$IF DEFINED(GLB_LIB_JPEG)}
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglBitmap.SaveJPEG(Stream: TStream);
+procedure TglBitmap.SaveJPEG(const aStream: TStream);
 var
   jpeg: jpeg_compress_struct;
   jpeg_err: jpeg_error_mgr;
@@ -6186,18 +6214,18 @@ var
 
 begin
   if not (ftJPEG in FormatGetSupportedFiles(Format)) then
-    raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT);
+    raise EglBitmapUnsupportedFormat.Create(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);
+    FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00);
+    FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00);
 
     // error managment
     jpeg.err := jpeg_std_error(@jpeg_err);
-    jpeg_err.error_exit := glBitmap_libJPEG_error_exit;
+    jpeg_err.error_exit     := glBitmap_libJPEG_error_exit;
     jpeg_err.output_message := glBitmap_libJPEG_output_message;
 
     // compression struct
@@ -6215,21 +6243,21 @@ begin
       pub.next_output_byte  := @DestBuffer[1];
       pub.free_in_buffer    := Length(DestBuffer);
 
-      DestStream := Stream;
+      DestStream := aStream;
     end;
 
     // very important state
     jpeg.global_state := CSTATE_START;
     jpeg.image_width  := Width;
     jpeg.image_height := Height;
-    case InternalFormat of
-      ifAlpha, ifLuminance, ifDepth8: begin
+    case Format of
+      tfAlpha8, tfLuminance8: begin
         jpeg.input_components := 1;
-        jpeg.in_color_space := JCS_GRAYSCALE;
+        jpeg.in_color_space   := JCS_GRAYSCALE;
       end;
-      ifRGB8, ifBGR8: begin
+      tfRGB8, tfBGR8: begin
         jpeg.input_components := 3;
-        jpeg.in_color_space := JCS_RGB;
+        jpeg.in_color_space   := JCS_RGB;
       end;
     end;
 
@@ -6238,7 +6266,7 @@ begin
     jpeg_start_compress(@jpeg, true);
     pTemp := Data;
 
-    if InternalFormat = ifBGR8 then
+    if Format = tfBGR8 then
       GetMem(pTemp2, fRowSize)
     else
       pTemp2 := pTemp;
@@ -6246,7 +6274,7 @@ begin
     try
       for Row := 0 to jpeg.image_height -1 do begin
         // prepare row
-        if InternalFormat = ifBGR8 then
+        if Format = tfBGR8 then
           CopyRow(pTemp2, pTemp)
         else
           pTemp2 := pTemp;
@@ -6257,7 +6285,7 @@ begin
       end;
     finally
       // free memory
-      if InternalFormat = ifBGR8 then
+      if Format = tfBGR8 then
         FreeMem(pTemp2);
     end;
     jpeg_finish_compress(@jpeg);