Formats.DDSImage.pas 4.0 KB

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