【问题标题】:How do you display an XMPP (Jabber) vcard photo in Delphi?如何在 Delphi 中显示 XMPP (Jabber) 电子名片照片?
【发布时间】:2010-11-24 21:12:45
【问题描述】:

如何从 XMPP vcard(头像图片,我认为是 JPEG 格式)中读取照片并将其显示在 Delphi TImage 控件中?

XMPP 服务器发送这个 XML:

<presence id="e3T50-75" to="cvg@esx10-2022/spark" from="semra@esx10-2022" 
 type="unavailable">
  <x xmlns="vcard-temp:x:update">
    <photo>897ce4538a4568f2e3c4838c69a0d60870c4fa49</photo>
  </x>
  <x xmlns="jabber:x:avatar">
    <hash>897ce4538a4568f2e3c4838c69a0d60870c4fa49</hash>
  </x>
</presence>

【问题讨论】:

  • 这是一个 phyton 示例,但我需要 delphi collincode.wordpress.com/2009/01/31/xmpp-jabber-photo-module-2
  • 正如 Python 函数 recieve_vcard() 所示,这只是 base64 编码的数据。使用 StackOverflow 上的“[delphi] base64”搜索来查找用于编码和解码这种格式的大量链接和示例代码。
  • @mghie:为什么不把这个写成答案,这样它才能被接受?
  • @Lars:我不认为这是一个答案,只是对正确方向的帮助。希望有人(甚至可能是 OP)发布一些回答问题的代码。我只是快速浏览了链接的 Python 代码。
  • 感谢 Rob Kenndy,但我收到了一些错误 Jpeg error #53 implementation uses omnixmlutils; {$R *.dfm} ...function ChooseGraphicClass(const MimeType: string): TGraphicClass; ...函数 CreateGraphicFromVCardPhoto(const BinVal, MimeType: string): TGraphic;过程 TForm1.Button1Click(Sender: TObject);开始 memo1.lines.loadfromfile('c:\cvg.bin'); image1.Picture.Graphic := CreateGraphicFromVCardPhoto(memo1.text,'image/jpeg');结尾; { cvg.bin 文件在这里 anasel.com.tr/cvgxml.txt } { anasel.com.tr/cvg.bin}

标签: xml delphi xmpp vcf-vcard


【解决方案1】:

您发布的 XML 不包含图片。它包含图片内容的SHA-1 hash。最初,您只会获得哈希值,以防您之前已经获取过该图像一次,因此您可以显示缓存版本而不是重新请求它。

如果您没有包含该哈希的图像,请申请新的 vcard。当它到达时,请阅读PHOTO 元素(如果可用)。它可能有两个子元素BINVALTYPEBINVAL 将包含图像的 Base-64 编码版本,TYPE 将包含图像类型的 MIME 类型标识符,例如 image/jpegimage/png .

解码二进制数据并将其存储在流中,例如TFileStreamTMemoryStream。接下来,选择适合您拥有的图像类型的TGraphic 后代。可能是TPngImage,也可能是TBitmap。实例化该类,并告诉它加载流的内容。它会是这样的:

function CreateGraphicFromVCardPhoto(const BinVal, MimeType: string): TGraphic;
var
  Stream: TStream;
  GraphicClass: TGraphicClass;
begin
  Stream := TMemoryStream.Create;
  try
    if not Base64Decode(BinVal, Stream) then
      raise EBase64Decode.Create;
    Stream.Position := 0;
    GraphicClass := ChooseGraphicClass(MimeType);
    Result := GraphicClass.Create;
    try
      Result.LoadFromStream(Stream);
    except
      Result.Free;
      raise;
    end;
  finally
    Stream.Free;
  end;
end;

上面的代码使用来自OmniXMLBase64Decode 函数,在Saving a Base64 string to disk as a binary using Delphi 2007 的答案中描述。获得TGraphic 值后,您可以将其分配给TImage 或使用TGraphics 执行任何其他操作。

ChooseGraphicClass 函数可能像这样工作:

function ChooseGraphicClass(const MimeType: string): TGraphicClass;
begin
  if MimeType = 'image/bmp' then
    Result := TBitmap
  else if MimeType = 'image/png' then
    Result := TPngImage
  else if MimeType = 'image/gif' then
    Result := TGifImage
  else if MimeType = 'image/jpeg' then
    Result := TJpegImage
  else
    raise EUnknownGraphicFormat.Create(MimeType);
end;

【讨论】:

  • 太棒了,罗布!建议:添加一个示例 vCard XML。
  • 不行。我从来没有见过这样的事情。我假设需要此代码的人已经知道如何获得电子名片。如果他们不这样做,他们可以在这里提出一个新问题。
  • 感谢 Rob Kenndy,但我收到了一些错误 Jpeg error #53 implementation uses omnixmlutils; {$R *.dfm} ...function ChooseGraphicClass(const MimeType: string): TGraphicClass; ...函数 CreateGraphicFromVCardPhoto(const BinVal, MimeType: string): TGraphic;过程 TForm1.Button1Click(Sender: TObject);开始 memo1.lines.loadfromfile('c:\cvg.bin'); image1.Picture.Graphic := CreateGraphicFromVCardPhoto(memo1.text,'image/jpeg');结尾; { cvg.bin 文件在这里 anasel.com.tr/cvgxml.txt } { anasel.com.tr/cvg.bin}
  • Delphi 的 JPEG 库不能处理所有的 JPEG 文件。 newsgroups.archived.at/borland/public.delphi.graphics/200608/…
  • 是的 Robert,delphi 无法处理所有类型的 jpeg。我使用这个程序和 memo1.lines.savetofile... savetodisk 然后看右图。过程 SaveBase64ToFile(常量编码,文件名:字符串); var fs: TFileStream;开始 fs := TFileStream.Create(fileName, fmCreate);尝试如果不是 Base64Decode(encoded, fs) 然后引发 Exception.Create('Invalid data!');最后 FreeAndNil(fs);结尾;结束;
猜你喜欢
  • 2019-11-06
  • 2015-02-22
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多