某些具有以下格式的JPEG文件未显示在Delphi的TImage
控件中。
并将速度与我现有的灰度代码进行比较。他们使用的扫描线过程似乎比我现有的扫描线过程略快。对于使用图像的人来说,这是一个很好的起点。当我遇到问题并注意到文件大小时,我添加了标准的jpeg转换代码和滚动框。我相信这个问题是有效的,但我重写了它。如果我找到另一个相关答案,问题更容易找到,我会拉这个帖子。如果没有,我会离开它。
例如,使用尼康数码相机。
尺寸:宽5184 x高3888
垂直分辨率:300 dpi
颜色表示:sRGB
压缩位/像素:2
钻头深度:24
EXIF版本:0230
属性:N
来自三星手机相机:
尺寸:宽度4128 x高度2322
水平&垂直分辨率:72 dpi
颜色表示:sRGB
分辨率单位:2
压缩位/像素:[空白]
钻头深度:24
EXIF版本:0220
属性:A
Adobe Photoshop的灰度文件:
尺寸:宽1800 x高3600
水平和垂直分辨率:300 dpi
颜色表示:未校准的
压缩位/像素:[空白]
钻头深度:8
EXIF版本:[空白]
属性:A
具有确切格式的文件作为最后一个,但尺寸小得多的文件有效。
一个工作文件的尺寸:宽度570 x高度248
24位深度,更小尺寸,无分辨率或压缩设置的文件也能正常工作。
当我尝试使用下面的代码显示图片时,失败文件上的图片始终为空白,并且不会返回任何错误。它与许多其他jpg
和bmp
文件完美配合。
是否存在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;
答案 0 :(得分:2)
由于您在加载JPEG图像时没有收到错误,我怀疑问题可能出在从TJPEGImage
到TBitmap
的转换中。除非您要操纵图像像素,否则根本不需要转换,您可以将原始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.Stretch
或TImage.Proportional
属性为True时,它们才会显示正常的。如果它们都设置为False(默认值),则图像显示为空白。
如果我先将JPG加载到TJPEGImage
然后再将其分配给TBitmap
,转换本身就可以正常工作(通过将TBitmap
保存到.bmp
文件来证明) ,只有当 Stretch
或Proportional
为True时,位图才会正常显示,否则它们会显示为空白。
因此,作为另一项测试,我尝试使用TPaintBox
,在OnPaint
事件中手动绘制图像。如果我使用TCanvas.Draw()
按原样绘制图像,则显示为空。如果我使用TCanvas.StretchDraw()
来适应`PaintBox的客户区域内的图像,它们显示正常。
所以,我认为TCanvas
可能会遇到内存问题,试图以更大的尺寸显示图像。它与正在使用的特定类型的JPG(正在加载正常)无关。
更新:没关系我上面说的话。我看到提供的JPG只有非常大的DPI,并且发生在它们的左上角都是白色的。如果TImage
/ TPaintBox
的大小足以弥补,我现在可以看到完整维度的图片(更容易看出TImage
是否放在TScrollBox
上将TImage.AutoSize
设置为True)。这可以解释为什么拉伸/比例绘制有效,通过在需要时拉伸图像以匹配TImage
的尺寸。