FileDDSImage.pas 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // This unit is part of the GLScene Engine, http://glscene.org
  3. //
  4. (*
  5. Alternative for DDS unit with more supported formats of flat image:
  6. Alpha8, Luminance8, R3G3B2, RGB5A1, RGBA4, Alpha8Luminance8, Luminance16, R5G6B5,
  7. RGB8, R10G10B10A2, RGBA8, RGBA16, R16F, RGBA16F, R32F, RGBA32F, GR16, GR16F, GR32F,
  8. Compressed RGB S3TC DXT1, Compressed RGBA S3TC DXT1, Compressed RGBA S3TC DXT3,
  9. Compressed RGBA S3TC DXT5
  10. But it down color to RGBA8 because becomes to TBitmap
  11. Good for preview picture in OpenDialog,
  12. so you may include both DDSImage (preview) and GLFileDDS (loading)
  13. *)
  14. unit FileDDSImage;
  15. interface
  16. {$I GLScene.inc}
  17. uses
  18. Winapi.Windows,
  19. System.Classes,
  20. System.SysUtils,
  21. Vcl.Graphics,
  22. GLVectorGeometry,
  23. GLGraphics,
  24. OpenGLTokens,
  25. GLContext;
  26. type
  27. TDDSImage = class(TBitmap)
  28. public
  29. procedure LoadFromStream(stream: TStream); override;
  30. procedure SaveToStream(stream: TStream); override;
  31. end;
  32. EDDSException = class(Exception);
  33. //-------------------------------------------------
  34. implementation
  35. //-------------------------------------------------
  36. uses
  37. FileDXTC,
  38. GLFileDDS,
  39. GLTextureFormat;
  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.