3

如何从 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>
4

1 回答 1

6

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

如果您没有具有该哈希的图像,则请求新的 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;

上面的代码使用Base64Decode来自OmniXML的函数,在使用 Delphi 2007 将 Base64 字符串作为二进制文件保存到磁盘的答案中进行了描述。一旦你有了这个TGraphic值,你就可以把它分配给 aTImage或者做任何你可以用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;
于 2009-09-02T16:15:08.677 回答