【问题标题】:Delphi TImage: How do I display images that are larger than the TImage component they are being loaded in or assigned to?Delphi TImage:如何显示大于它们正在加载或分配给的 TImage 组件的图像?
【发布时间】:2017-06-02 01:06:24
【问题描述】:

Delphi 的TImage 控件中不显示某些具有以下格式的 JPEG 文件。

并将速度与我现有的灰度代码进行比较。他们使用的扫描线过程似乎比我目前使用的扫描线过程稍快。对于使用图像的人来说,这是一个很好的起点。当我遇到问题并注意到文件大小时,我添加了标准的 jpeg 转换代码和滚动框。我相信这个问题是有效的,但我改写了它。如果我找到另一个更容易找到问题的相关答案,我会拉这个帖子。如果没有,我会离开它。

例如,来自尼康数码相机。

尺寸:宽 5184 x 高 3888
垂直分辨率:300 dpi
颜色表示:sRGB
压缩位/像素:2
位深:24
EXIF 版本:0230
属性:N

来自三星手机摄像头:

尺寸:宽 4128 x 高 2322
水平和垂直分辨率:72 dpi
颜色表示:sRGB
分辨率单位:2
压缩位/像素:[空白]
位深:24
EXIF 版本:0220
属性:A

来自 Adob​​e Photoshop 的灰度文件:

尺寸:宽 1800 x 高 3600
水平和垂直分辨率:300 dpi
颜色表示:未校准
压缩位/像素:[空白]
位深:8
EXIF 版本:[空白]
属性:A

文件格式与上一个文件完全相同,但尺寸要小得多。

一个工作文件的尺寸:宽 570 x 高 248

具有 24 位深度、较小尺寸且没有分辨率或压缩设置的文件也可以正常工作。

当我尝试使用下面的代码显示图片时,失败文件上的图片始终为空白,并且不返回任何错误。它与许多其他 jpgbmp 文件完美配合。

sRGB 格式的文件是否需要转换?控件可以在屏幕上显示的内容是否有大小限制?如果是这样,有没有办法显示更大的文件?

procedure TForm1.btnBrowseClick(Sender: TObject);
var
  bmp: TBitmap;
  c2g: TColor2Grayscale;
  ba: TBitmapAccess;
  sw: TStopwatch;
  jpg : TJPEGImage; // jpeg does not show 32-bit support in Delphi, only 24 and 8.
  path, name, ext : string;
  alreadyGray : boolean;
begin
  bmp := TBitmap.Create;
  jpg := TJPEGImage.Create;

  OpenPicturedialog1.InitialDir := FindImageFolder(true);
  if OpenPictureDialog1.Execute() then
  try
    name := OpenPictureDialog1.FileName;
    path := ExtractFilePath(name);
    ext := Lowercase ( ExtractFileExt(name) );

    alreadyGray := false;

    try
      if ( ext = '.jpg' ) or ( ext = '.jpeg' ) then
      begin
        jpg.LoadFromFile(name);
        bmp.Assign(jpg);
        alreadyGray := jpg.Grayscale;
      end
      else
        bmp.LoadFromFile( name );
    except
      on err: Exception do
      begin
        ShowMessage(err.Message);
        Exit;
      end;
    end;

    if bmp.PixelFormat = pfDevice then
      bmp.PixelFormat := pf32bit;

    Image1.Picture.Assign(bmp);

    if alreadyGray then
    begin
      Image2.Picture.Assign(bmp);
      Exit;
    end;

  finally
    jpg.Free;
    bmp.Free;
  end;
end;

【问题讨论】:

  • 您能否添加指向不起作用的示例 jpg 文件的链接
  • 您使用的是哪个版本的 Delphi?
  • 我可以确认它甚至在 Delphi 10.1 更新 2 上也不起作用。不过,如果这是一个可接受的解决方法,它可以在 FMX 中工作。
  • 10.1 西雅图,我相信。我还没有加载最新的服务包。
  • 另请注意。操作系统是Windows 10。虽然我有点怀念Win7的界面,但我觉得10对大多数用户来说更安全。

标签: image delphi bitmap jpeg srgb


【解决方案1】:

由于您在加载 JPEG 图像时没有收到错误,我怀疑问题可能出在从 TJPEGImageTBitmap 的转换中。除非您要处理图像像素,否则根本不需要转换,您可以将原始的TJPEGImage 直接分配给TImage。 VCL 的 TPicture 类使用派生的 TGraphic 类,因此它可以以其原生格式显示图像,您应该利用该功能,例如:

procedure TForm1.btnBrowseClick(Sender: TObject);
var
  jpg: TJPEGImage;
  bmp: TBitmap;
begin
  OpenPicturedialog1.InitialDir := FindImageFolder(true);
  if OpenPictureDialog1.Execute then
  begin
    Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);

    if Image1.Picture.Graphic is TJPEGImage then
    begin
      if TJPEGImage(Image1.Picture.Graphic).Grayscale then
      begin
        Image2.Picture.Assign(Image1.Picture.Graphic);
      end else
      begin
        jpg := TJPEGImage.Create;
        try
          jpg.Assign(Image1.Picture.Graphic);
          jpg.Grayscale := True;
          Image2.Picture.Assign(jpg);
        finally
          jpg.Free;
        end;
      end;
    end else
    begin
      bmp := TBitmap.Create;
      try
        bmp.PixelFormat := pf32bit;
        bmp.Assign(Image1.Picture.Graphic);
        ...
        Image2.Picture.Assign(bmp);
      finally
        bmp.Free;
      end;
    end;
  end;
end;

更新:我在 Windows 7 上的 XE2 中进行了一些测试,发现了与您相同的问题。

如果我使用TImage.Picture.LoadFromFile() 按原样加载 JPG,它们会显示良好只有当TImage.StretchTImage.Proportional 属性为True 时。如果它们都设置为 False(默认值),则图像显示为空白。

如果我首先将 JPG 加载到 TJPEGImage,然后将其分配给 TBitmap,则转换本身可以正常工作(通过将 TBitmap 保存到 .bmp 文件来证明),并且位图可以正常显示 仅当StretchProportional 为True,否则显示为空白。

因此,作为另一个测试,我尝试使用TPaintBox,在其OnPaint 事件中手动绘制图像。如果我使用TCanvas.Draw() 按原样绘制完整尺寸的图像,它们将显示为空。如果我使用TCanvas.StretchDraw() 使图像适合`PaintBox 的客户区域,它们显示得很好。

所以,我认为TCanvas 在尝试以如此大的尺寸显示图像时可能会遇到内存问题。它与所使用的特定类型的 JPG 无关(加载正常)。


更新:别在意我上面说的。我看到所提供的 JPG 具有非常大的 DPI,并且 碰巧 在它们的左上角都是白色的。如果TImage/TPaintBox 的尺寸很大以进行补偿,我现在可以看到完整尺寸的图像(更容易看到TImage 是否放置在TScrollBox 上,TImage.AutoSize 设置为 True )。这可以解释为什么拉伸/比例绘图会起作用,方法是在需要时拉伸图像以匹配TImage 的尺寸。

【讨论】:

  • 嗨,Remy...我是先这样做的,它正在做同样的事情,只是在一些照片上。所以我重新测试以验证,仍然是空白。将三个图像的压缩文件夹推送到下载文件夹进行测试。我将此代码行 [Image1.Picture.LoadFromFile(name);] 移动到 try 代码中的顶部,并删除了 [Image1.Picture.Assign(bmp)] 以重新测试它。
  • 我之前在这篇文章中看到了您的评论 [stackoverflow.com/questions/22291162/…,我想知道 sRGB 与常规 RGB 文件的格式是否发生了变化,就像 24 位文件与 32 位文件一样。如果有它并且它没有包含在组件或 JPEG 文件中,我可以看到它会在哪里显示为空白。
  • 感谢更新,我之前尝试了stretchDraw 和滚动框,但我可能错过了Autosize 选项。我会试试看的。
  • AutoSize 默认关闭。只需要在表单图像组件中检查该选项,它就可以按预期工作。太感谢了。明天,我将推出我今天测试的较新的灰度程序,我们的软件版本将完成。我不敢相信我错过了那个复选框。附言。 .Assign(bmp) 与 .Picture.LoadFromFile(name) 一样有效,复选框设置为 [True]
猜你喜欢
  • 1970-01-01
  • 2011-04-26
  • 1970-01-01
  • 2014-07-14
  • 2013-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多