Formatx.DDSImage.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //
  2. // The graphics engine GXScene https://github.com/glscene
  3. //
  4. unit Formatx.DDSImage;
  5. (*
  6. Alternative for DDS unit with more supported formats of flat image:
  7. Alpha8, Luminance8, R3G3B2, RGB5A1, RGBA4, Alpha8Luminance8, Luminance16, R5G6B5,
  8. RGB8, R10G10B10A2, RGBA8, RGBA16, R16F, RGBA16F, R32F, RGBA32F, GR16, GR16F, GR32F,
  9. Compressed RGB S3TC DXT1, Compressed RGBA S3TC DXT1, Compressed RGBA S3TC DXT3,
  10. Compressed RGBA S3TC DXT5
  11. But it down color to RGBA8 because becomes to TBitmap
  12. Good for preview picture in OpenDialog,
  13. so you may include both DDSImage (preview) and GLFileDDS (loading)
  14. *)
  15. interface
  16. {$I GLScene.Defines.inc}
  17. uses
  18. Winapi.OpenGL,
  19. Winapi.Windows,
  20. System.Classes,
  21. System.SysUtils,
  22. FMX.Graphics,
  23. FMX.Types,
  24. GLScene.VectorGeometry,
  25. GXS.Graphics,
  26. GXS.Context,
  27. GXS.TextureFormat,
  28. GXS.FileDDS,
  29. Formatx.DXTC;
  30. type
  31. TDDSImage = class(TBitmap)
  32. public
  33. procedure LoadFromStream(stream: TStream); //override; -> E2170 Cannot override a non-virtual method override;
  34. procedure SaveToStream(stream: TStream); //override; -> E2170 Cannot override a non-virtual method override;
  35. end;
  36. EDDSException = class(Exception);
  37. //-----------------------------------------------------------------------
  38. implementation
  39. //-----------------------------------------------------------------------
  40. // ------------------
  41. // ------------------ TDDSImage ------------------
  42. // ------------------
  43. procedure TDDSImage.LoadFromStream(stream: TStream);
  44. var
  45. FullDDS: TgxDDSImage;
  46. DDSImage: TDDSImage; // added to replace Scanline in FMX
  47. BitmapData: TBitmapData;
  48. bCubeMap: Boolean;
  49. src, dst: PGLubyte;
  50. y: integer;
  51. begin
  52. FullDDS := TgxDDSImage.Create;
  53. DDSImage := TDDSImage.Create;
  54. try
  55. FullDDS.LoadFromStream(stream);
  56. DDSImage.LoadFromStream(stream);
  57. except
  58. FullDDS.Free;
  59. DDSImage.Free;
  60. raise;
  61. end;
  62. bCubeMap := FullDDS.CubeMap;
  63. FullDDS.Narrow;
  64. // TODO : E2129 Cannot assign to a read-only property
  65. (*PixelFormat := glpf32bit;*)
  66. // TODO : E2064 Left side cannot be assigned to
  67. (*Transparent := True; *)
  68. Width := FullDDS.LevelWidth[0];
  69. Height := FullDDS.LevelHeight[0];
  70. src := PGLubyte(FullDDS.Data);
  71. if bCubeMap then
  72. for y := 0 to Height - 1 do
  73. begin
  74. DDSImage.Map(TMapAccess.ReadWrite, BitmapData);
  75. dst := BitmapData.GetScanline(y);
  76. BGRA32ToRGBA32(src, dst, Width);
  77. Inc(src, Width * 4);
  78. end
  79. else
  80. for y := 0 to Height - 1 do
  81. begin
  82. DDSImage.Map(TMapAccess.ReadWrite, BitmapData);
  83. dst := BitmapData.GetScanline(Height - 1 - y);
  84. BGRA32ToRGBA32(src, dst, Width);
  85. Inc(src, Width * 4);
  86. end;
  87. FullDDS.Free;
  88. DDSImage.Free;
  89. end;
  90. procedure TDDSImage.SaveToStream(stream: TStream);
  91. const
  92. Magic: array[0..3] of AnsiChar = 'DDS ';
  93. var
  94. header: TDDSHeader;
  95. rowSize: integer;
  96. i: Integer;
  97. begin
  98. FillChar(header, SizeOf(TDDSHeader), 0);
  99. header.magic := cardinal(Magic);
  100. with header.SurfaceFormat do
  101. begin
  102. dwSize := sizeof(TDDSURFACEDESC2);
  103. dwFlags := DDSD_CAPS + DDSD_PIXELFORMAT + DDSD_WIDTH + DDSD_HEIGHT + DDSD_PITCH;
  104. dwWidth := Width;
  105. dwHeight := Height;
  106. ddpf.dwSize := sizeof(TDDPIXELFORMAT);
  107. case PixelFormat of
  108. TPixelFormat.RGBA:
  109. begin
  110. ddpf.dwFlags := DDPF_RGB;
  111. ddpf.dwRGBBitCount := 32;
  112. ddpf.dwRBitMask := $00FF0000;
  113. ddpf.dwGBitMask := $0000FF00;
  114. ddpf.dwBBitMask := $000000FF;
  115. if Transparent=1 then
  116. begin
  117. ddpf.dwFlags := ddpf.dwFlags + DDPF_ALPHAPIXELS;
  118. ddpf.dwRGBAlphaBitMask := $FF000000;
  119. end;
  120. end;
  121. else
  122. raise EDDSException.Create('Unsupported pixel format');
  123. end;
  124. rowSize := (ddpf.dwRGBBitCount div 8) * dwWidth;
  125. dwPitchOrLinearSize := dwHeight * cardinal(rowSize);
  126. dwCaps := DDSCAPS_TEXTURE;
  127. stream.Write(header, SizeOf(TDDSHeader));
  128. for i := 0 to Height - 1 do
  129. // TODO : E2003 Undeclared identifier: 'ScanLine'
  130. (* stream.Write(ScanLine[i]^, rowSize);*)
  131. end;
  132. end;
  133. // ------------------------------------------------------------------
  134. initialization
  135. // ------------------------------------------------------------------
  136. // TODO : E2003 Undeclared identifier: 'RegisterFileFormat'
  137. (*
  138. TPicture.RegisterFileFormat(
  139. 'dds', 'Microsoft DirectDraw Surface', TDDSImage);
  140. *)
  141. // ------------------------------------------------------------------
  142. finalization
  143. // ------------------------------------------------------------------
  144. // TODO : E2003 Undeclared identifier: 'UnregisterGraphicClass'
  145. (*
  146. TPicture.UnregisterGraphicClass(TDDSImage);
  147. *)
  148. end.