Formats.DDSImage.pas 4.0 KB

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