GLS.FilePNG.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //
  2. // The multimedia graphics platform GLScene https://github.com/glscene
  3. //
  4. unit GLS.FilePNG;
  5. (* PNG files loading implementation *)
  6. interface
  7. {$I GLScene.inc}
  8. uses
  9. Winapi.OpenGL,
  10. System.Classes,
  11. System.SysUtils,
  12. VCL.Imaging.pngimage,
  13. GLS.OpenGLTokens,
  14. GLS.Strings,
  15. GLS.Context,
  16. GLS.Graphics,
  17. GLS.ApplicationFileIO,
  18. GLS.TextureFormat;
  19. type
  20. TGLPNGImage = class(TGLBaseImage)
  21. private
  22. public
  23. class function Capabilities: TGLDataFileCapabilities; override;
  24. procedure LoadFromFile(const filename: string); override;
  25. procedure SaveToFile(const filename: string); override;
  26. procedure LoadFromStream(AStream: TStream); override;
  27. procedure SaveToStream(AStream: TStream); override;
  28. // Assigns from any Texture.
  29. procedure AssignFromTexture(textureContext: TGLContext;
  30. const textureHandle: Cardinal; textureTarget: TGLTextureTarget;
  31. const CurrentFormat: Boolean; const intFormat: TGLInternalFormat);
  32. reintroduce;
  33. end;
  34. // --------------------------------------------------------------
  35. implementation
  36. // --------------------------------------------------------------
  37. // ------------------
  38. // ------------------ TGLPNGImage ------------------
  39. // ------------------
  40. procedure TGLPNGImage.LoadFromFile(const filename: string);
  41. var
  42. fs: TStream;
  43. begin
  44. if FileStreamExists(filename) then
  45. begin
  46. fs := TFileStream.Create(filename, fmOpenRead);
  47. try
  48. LoadFromStream(fs);
  49. finally
  50. fs.Free;
  51. ResourceName := filename;
  52. end;
  53. end
  54. else
  55. raise EInvalidRasterFile.CreateFmt('File %s not found', [filename]);
  56. end;
  57. procedure TGLPNGImage.SaveToFile(const filename: string);
  58. var
  59. fs: TStream;
  60. begin
  61. fs := TFileStream.Create(filename, fmOpenWrite or fmCreate);
  62. try
  63. SaveToStream(fs);
  64. finally
  65. fs.Free;
  66. end;
  67. ResourceName := filename;
  68. end;
  69. procedure TGLPNGImage.LoadFromStream(AStream: TStream);
  70. var
  71. pngimage: TPngImage;
  72. rowBytes: Cardinal;
  73. begin
  74. try
  75. pngimage := TPngImage.Create;
  76. pngimage.LoadFromStream(AStream);
  77. UpdateLevelsInfo;
  78. ReallocMem(fData, rowBytes * Cardinal(GetHeight));
  79. finally
  80. pngimage.Free;
  81. end;
  82. end;
  83. procedure TGLPNGImage.SaveToStream(AStream: TStream);
  84. var
  85. pngimage: TPngImage;
  86. begin
  87. try
  88. pngimage := TPngImage.Create;
  89. pngimage.SaveToStream(AStream);
  90. finally
  91. pngimage.Free;
  92. end;
  93. end;
  94. procedure TGLPNGImage.AssignFromTexture(textureContext: TGLContext;
  95. const textureHandle: Cardinal; textureTarget: TGLTextureTarget;
  96. const CurrentFormat: Boolean; const intFormat: TGLInternalFormat);
  97. var
  98. oldContext: TGLContext;
  99. contextActivate: Boolean;
  100. texFormat: Cardinal;
  101. residentFormat: TGLInternalFormat;
  102. glTarget: Cardinal;
  103. begin
  104. if not((textureTarget = ttTexture2D) or (textureTarget = ttTextureRect)) then
  105. Exit;
  106. oldContext := CurrentGLContext;
  107. contextActivate := (oldContext <> textureContext);
  108. if contextActivate then
  109. begin
  110. if Assigned(oldContext) then
  111. oldContext.Deactivate;
  112. textureContext.Activate;
  113. end;
  114. glTarget := DecodeTextureTarget(textureTarget);
  115. try
  116. textureContext.GLStates.TextureBinding[0, textureTarget] := textureHandle;
  117. fLevelCount := 0;
  118. fCubeMap := false;
  119. fTextureArray := false;
  120. // Check level existence
  121. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_INTERNAL_FORMAT,
  122. @texFormat);
  123. if texFormat > 1 then
  124. begin
  125. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_WIDTH, @FLOD[0].Width);
  126. gl.GetTexLevelParameteriv(glTarget, 0, GL_TEXTURE_HEIGHT,
  127. @FLOD[0].Height);
  128. FLOD[0].Depth := 0;
  129. residentFormat := OpenGLFormatToInternalFormat(texFormat);
  130. if CurrentFormat then
  131. fInternalFormat := residentFormat
  132. else
  133. fInternalFormat := intFormat;
  134. FindCompatibleDataFormat(fInternalFormat, fColorFormat, fDataType);
  135. Inc(fLevelCount);
  136. end;
  137. if fLevelCount > 0 then
  138. begin
  139. fElementSize := GetTextureElementSize(fColorFormat, fDataType);
  140. ReallocMem(fData, DataSize);
  141. gl.GetTexImage(glTarget, 0, fColorFormat, fDataType, fData);
  142. end
  143. else
  144. fLevelCount := 1;
  145. gl.CheckError;
  146. finally
  147. if contextActivate then
  148. begin
  149. textureContext.Deactivate;
  150. if Assigned(oldContext) then
  151. oldContext.Activate;
  152. end;
  153. end;
  154. end;
  155. class function TGLPNGImage.Capabilities: TGLDataFileCapabilities;
  156. begin
  157. Result := [dfcRead, dfcWrite];
  158. end;
  159. // ---------------------------------------------------
  160. initialization
  161. // ---------------------------------------------------
  162. RegisterRasterFormat('png', 'Portable Network Graphic', TGLPNGImage);
  163. end.