You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

位图转JPEG后调整大小异常:移除SaveToFile触发访问违规原因

问题分析与解决方案

为什么移除SaveToFile会触发访问违规?

当你执行Jpg.Assign(Bmp)时,TJPEGImage并没有立刻把位图转换成JPEG压缩格式——它只是把原始的位图数据暂存到了内部缓冲区,此时组件的内部状态是持有未编码的位图数据,而非已完成压缩的JPEG数据。

而Scale属性的工作原理是基于JPEG的压缩编码数据(DCT系数)进行缩放,它无法直接处理原始位图。当你跳过SaveToFile直接设置Scale时,组件会试图访问还未生成的压缩数据指针,自然就触发了内存访问违规(AV)。

SaveToFile在后台做了什么?

调用SaveToFile时,会强制触发TJPEGImage的完整编码流程:

  • 读取之前暂存的位图数据
  • 按照当前设置的JPEG参数(比如压缩质量、颜色空间)执行压缩编码
  • 将编码后的JPEG数据存储到内部的数据流中
  • 更新组件的内部状态为持有已编码的JPEG数据

这个过程完成后,Scale属性就能找到有效的压缩数据进行操作,不会再出现内存访问问题。

不需要存盘的解决方案

如果你不想把文件写到磁盘,只需要触发编码流程即可,用内存流替代文件流就能实现:

procedure TForm1.Button1Click(Sender: TObject);
var
  Bmp: TBitmap;
  Jpg: TJPEGImage;
  MemStream: TMemoryStream;
begin
  Bmp := TBitmap.Create;
  Bmp.PixelFormat := pf32bit;
  Jpg := TJPEGImage.Create;
  MemStream := TMemoryStream.Create;
  try
    Bmp.LoadFromFile('0C310060.bmp');
    Jpg.Assign(Bmp);
    // 用内存流触发编码,无需写入磁盘
    Jpg.SaveToStream(MemStream);
    Image1.Picture.Assign(Jpg);
    TJPEGImage(Image1.Picture.Graphic).Scale := jsEighth;
  finally
    MemStream.Free;
    Jpg.Free;
    Bmp.Free;
  end;
end;

或者更简洁的方式:部分Delphi版本支持直接调用Jpg.Compress方法触发编码,但用SaveToStream的方式兼容性更好,能适配大多数Delphi版本。

内容的提问来源于stack exchange,提问作者Rudi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:31:58