将Jpeg图像转换为Bmp - 一些图像呈蓝色

Jer*_*dge 10 delphi graphics jpeg image-processing

Delphi似乎不喜欢一些Jpg图像.它似乎特定于我正在加载的文件.并且过程很简单 - a)将Jpg图像加载到TJpegImage,b)将Jpg对象分配给TBitmap对象,以及c)保存和/或显示Bmp图像.出于某种原因,这些图片不断出现蓝色调.

这些图像完美地展示了我装载它们的任何地方和任何地方(windows picture viewer,paint,photoshop等).

我正在做的很简单......

procedure Load;
var
  J: TJpegImage;
  B: TBitmap;
begin
  J:= TJpegImage.Create;
  B:= TBitmap.Create;
  J.LoadFromFile('C:\SomeFile.jpg');
  B.Assign(J);
  //Either save or display `B` and it appears blueish at this point
....
Run Code Online (Sandbox Code Playgroud)

我想尽可能避免收到任何第三方的东西.Delphi版本7,2010和XE2中存在此问题.至少XE2中的TImage控件正确显示它(而不是旧的两个),但是如果TBitmap仍然不起作用则无关紧要.这个文件有什么问题?和/或,Delphi的渲染有什么问题?

添加了信息

我最近发现了一些关于这些图像的东西.当他们来自供应商(产品图片)时,他们采用CMYK格式.那时,Delphi 7没有正确支持这些文件(具有访问冲突和坏图像),因此所有图片都通过转换器过滤为RGB颜色格式.许多原始图像也是TIFF并转换为JPG.因此,软件似乎FastStone Image Resizer无法正常保存这些文件.所有这些都不会发生蓝色图像,一次只能进行一些随机批次.该软件处理数千种产品,因此有数千种可能的图片.

Fra*_*ois 11

你的文件是蓝色的原因是因为编码是BGR而不是RGB.
如果修改了jpeg.pas源文件,并使用像素交换(除去{.$IFDEF JPEGSO}TJPEGImage.GetBitmap),你会看到你的示例文件正确褐色.

所以,我想底线是股票jpeg源没有检测到正确的(反向)编码; 可能在jc.d.out_color_space......

更新:
C源文件(和jpeg.pas)应该使用新扩展JCS_EXT _...声明(并使用)Color Spaces:

enum J_COLOR_SPACE {
  JCS_UNKNOWN, JCS_GRAYSCALE, JCS_RGB, JCS_YCbCr,
  JCS_CMYK, JCS_YCCK, JCS_EXT_RGB, JCS_EXT_RGBX,
  JCS_EXT_BGR, JCS_EXT_BGRX, JCS_EXT_XBGR, JCS_EXT_XRGB
}
Run Code Online (Sandbox Code Playgroud)

更新2:
jpeg.pas可以C:...\RAD Studio\8.0\source\vcljpg子文件夹中的C文件中找到(XE).

如果您准备打赌所有具有RGB色彩空间的Adobe文件需要交换它们的位,您可以轻松地破解jpeg.pas源以检测您的特殊文件并有条件地执行上面提到的交换 TJPEGImage.GetBitmap

{.$IFDEF JPEGSO}
          if (jc.c.in_color_space=JCS_RGB)and
            (smallint(jc.c.jpeg_color_space)=Ord(JCS_UNKNOWN))and   //comes 1072693248 = $3FF00000 = 111111111100000000000000000000
            jc.d.saw_Adobe_marker  and
            (PixelFormat = jf24bit) then
          begin
Run Code Online (Sandbox Code Playgroud)


Dav*_*nan 8

WIC(适用于XP及以上版本)可以处理此图像.这个组件很好地包含在Delphi 2010及更高版本中.对于早期的Delphi版本,使用COM接口调用WIC很容易.

这是我的概念证明代码:

var
  Image: TWICImage;
  Bitmap: TBitmap;
begin
  Image := TWICImage.Create;
  Image.LoadFromFile('C:\desktop\ABrownImage.jpg');
  Bitmap := TBitmap.Create;
  Bitmap.Assign(Image);
  Bitmap.SaveToFile('C:\desktop\ABrownImage.bmp');
end;
Run Code Online (Sandbox Code Playgroud)

注1:WIC随Vista一起提供,但必须为XP重新分发.一个明显的选择是使用WIC(如果可用),但是否则返回Delphi JPEG解码器.

注2:我找不到WIC的可重新分发包.我怀疑它可能需要最终用户下载XP.这就是说,如果绝大多数XP机器现在安装它,我都不会感到惊讶.


Mar*_*ams 5

我想出了这个问题.它很可能是Delphi中的一个错误.

提供的图像是一种称为Adobe JPEG的JPEG文件的特殊格式.关于Adobe JPEG最奇怪的可能是它允许以RGB格式存储图像,尽管它也允许其他格式.大多数JPEG是JFIF或EXIF格式,不使用RGB.

当复制RGB数据时,无论Delphi做什么,它都会在将红色和蓝色数据加载到画布上时将其反转.它将其加载为BGR而不是RGB.这可能是因为Windows(24位和32位)DIB(BMP)以BGR格式存储.

我猜这个bug会出现在任何RGB JPEG的Delphi中.由于大多数JPEG不使用RGB,因此bug的发生率很低.如果您有JPEG单元的源,那么轻松修复是在加载RGB JPEG时反转顺序.

如果您没有源,请继续.

Adobe JPEG 43 11 00 47 11 00 42 11 00以十六进制编辑器中的这种格式(十六进制)指定颜色的顺序R..G..B.如果您通过十六进制编辑器反转RB在此处,它在Windows中显示错误,在Delphi中显示错误.

为了识别一个Adobe JPEG,前四个字节或者是(在己烷中)FF D8 FF EDFF D8 FF EEEDEE被微分字节.所有JPEG文件都以FF D8 FF.

在这些字节之后是两个字节,表示类型标记的长度,然后是(在ASCII中)Adobe,接着是六个字节(表示版本等),最后,(第18个字节)是指定格式的字节.0意味着RGB.因此,检查那些重要的字节,然后相应地采取行动.

你必须反转文件头中的RGB顺序(骗到Delphi),或者将它复制到TBitmap并使用ScanLine将RGB反转到正确的顺序.

格式细节来自于读取C中的libJPEG源.

  • 不是不同意,而是好奇......你怎么认为Adobe的非标准格式(用你自己的话说,"特殊的东西")构成了Delphi中的一个bug?如果"大多数JPEG是JFIF或EXIF",并且Adobe做了不同的事情,那是不是意味着Adobe JPEG中存在错误? (2认同)