Formats.DDSImage.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //
  2. // The graphics engine GLScene https://github.com/glscene
  3. //
  4. unit Formats.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.Windows,
  19. System.Classes,
  20. System.SysUtils,
  21. Vcl.Graphics,
  22. GLScene.VectorTypes,
  23. GLScene.OpenGLTokens,
  24. GLScene.VectorGeometry,
  25. GLS.Graphics,
  26. GLS.Context,
  27. GLS.FileDDS,
  28. GLS.TextureFormat;
  29. type
  30. TDDSImage = class(TBitmap)
  31. public
  32. procedure LoadFromStream(stream: TStream); override;
  33. procedure SaveToStream(stream: TStream); override;
  34. end;
  35. EDDSException = class(Exception);
  36. //-------------------------------------------------
  37. implementation
  38. //-------------------------------------------------
  39. uses
  40. Formats.DXTC;
  41. // ------------------
  42. // ------------------ TDDSImage ------------------
  43. // ------------------
  44. procedure TDDSImage.LoadFromStream(stream: TStream);
  45. var
  46. FullDDS: TGLDDSImage;
  47. bCubeMap: Boolean;
  48. src, dst: PGLubyte;
  49. y: integer;
  50. begin
  51. FullDDS := TGLDDSImage.Create;
  52. try
  53. FullDDS.LoadFromStream(stream);
  54. except
  55. FullDDS.Free;
  56. raise;
  57. end;
  58. bCubeMap := FullDDS.CubeMap;
  59. FullDDS.Narrow;
  60. PixelFormat := pf32bit;
  61. Transparent := True;
  62. Width := FullDDS.LevelWidth[0];
  63. Height := FullDDS.LevelHeight[0];
  64. src := PGLubyte(FullDDS.Data);
  65. if bCubeMap then
  66. for y := 0 to Height - 1 do
  67. begin
  68. dst := ScanLine[y];
  69. BGRA32ToRGBA32(src, dst, Width);
  70. Inc(src, Width * 4);
  71. end
  72. else
  73. for y := 0 to Height - 1 do
  74. begin
  75. dst := ScanLine[Height - 1 - y];
  76. BGRA32ToRGBA32(src, dst, Width);
  77. Inc(src, Width * 4);
  78. end;
  79. FullDDS.Free;
  80. end;
  81. procedure TDDSImage.SaveToStream(stream: TStream);
  82. const
  83. Magic: array[0..3] of AnsiChar = 'DDS ';
  84. var
  85. header: TDDSHeader;
  86. rowSize: integer;
  87. i: Integer;
  88. begin
  89. FillChar(header, SizeOf(TDDSHeader), 0);
  90. header.magic := cardinal(Magic);
  91. with header.SurfaceFormat do
  92. begin
  93. dwSize := sizeof(TDDSURFACEDESC2);
  94. dwFlags := DDSD_CAPS + DDSD_PIXELFORMAT + DDSD_WIDTH + DDSD_HEIGHT + DDSD_PITCH;
  95. dwWidth := Width;
  96. dwHeight := Height;
  97. ddpf.dwSize := sizeof(TDDPIXELFORMAT);
  98. case PixelFormat of
  99. {$IFDEF MSWINDOWS}
  100. pf24bit:
  101. begin
  102. ddpf.dwFlags := DDPF_RGB;
  103. ddpf.dwRGBBitCount := 24;
  104. ddpf.dwRBitMask := $00FF0000;
  105. ddpf.dwGBitMask := $0000FF00;
  106. ddpf.dwBBitMask := $000000FF;
  107. end;
  108. {$ENDIF}
  109. pf32bit:
  110. begin
  111. ddpf.dwFlags := DDPF_RGB;
  112. ddpf.dwRGBBitCount := 32;
  113. ddpf.dwRBitMask := $00FF0000;
  114. ddpf.dwGBitMask := $0000FF00;
  115. ddpf.dwBBitMask := $000000FF;
  116. if Transparent then
  117. begin
  118. ddpf.dwFlags := ddpf.dwFlags + DDPF_ALPHAPIXELS;
  119. ddpf.dwRGBAlphaBitMask := $FF000000;
  120. end;
  121. end;
  122. else
  123. raise EDDSException.Create('Unsupported pixel format');
  124. end;
  125. rowSize := (ddpf.dwRGBBitCount div 8) * dwWidth;
  126. dwPitchOrLinearSize := dwHeight * cardinal(rowSize);
  127. dwCaps := DDSCAPS_TEXTURE;
  128. stream.Write(header, SizeOf(TDDSHeader));
  129. for i := 0 to Height - 1 do
  130. stream.Write(ScanLine[i]^, rowSize);
  131. end;
  132. end;
  133. // ------------------------------------------------------------------
  134. initialization
  135. // ------------------------------------------------------------------
  136. TPicture.RegisterFileFormat(
  137. 'dds', 'Microsoft DirectDraw Surface', TDDSImage);
  138. // ------------------------------------------------------------------
  139. finalization
  140. // ------------------------------------------------------------------
  141. TPicture.UnregisterGraphicClass(TDDSImage);
  142. end.