2009-09-02 2 views
3

Как я могу прочитать фотографию с VMP XMPP (изображение аватара, которое, как мне кажется, в формате JPEG) и отобразить его в элементе управления Delphi TImage?Как вы показываете фотографию vcard XMPP (Jabber) в Delphi?

-сервер XMPP посылает этот XML:

<presence id="e3T50-75" to="[email protected]/spark" from="[email protected]" 
type="unavailable"> 
    <x xmlns="vcard-temp:x:update"> 
    <photo>897ce4538a4568f2e3c4838c69a0d60870c4fa49</photo> 
    </x> 
    <x xmlns="jabber:x:avatar"> 
    <hash>897ce4538a4568f2e3c4838c69a0d60870c4fa49</hash> 
    </x> 
</presence> 
+0

это пример Фитон, но мне нужно Дельфи http://collincode.wordpress.com/2009/01/31/xmpp-jabber-photo- module-2/ – cvg

+0

Поскольку функция Python 'recieve_vcard()' показывает, что это только данные с кодировкой base64. Используйте поиск «[delphi] base64» в StackOverflow, чтобы найти множество ссылок и пример кода для кодирования и декодирования этого формата. – mghie

+0

@mghie: Почему бы не написать это как ответ, чтобы его можно было принять? –

ответ

6

XML, вы размещены не содержит изображения. Он содержит содержимое SHA-1 hash. Сначала вы получаете хэш, только если вы уже выбрали это изображение раньше, поэтому вы можете отображать кешированную версию вместо запроса ее заново.

Если у вас нет изображения с этим хешем, попросите новый vcard. Когда он поступит, прочитайте элемент PHOTO, если он доступен. Он может иметь два подэлемента: BINVAL и TYPE. BINVAL будет содержать версию изображения с кодировкой Base-64, а TYPE будет содержать идентификатор типа MIME для типа изображения, например image/jpeg или image/png.

Декодировать двоичные данные и хранить их в потоке, таком как TFileStream или TMemoryStream. Затем выберите, какой потомок 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, описанный в ответ на Saving a Base64 string to disk as a binary using Delphi 2007. Если у вас есть значение TGraphic, вы можете назначить его TImage или сделать все, что вы можете сделать с TGraphic s.

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; 
+0

Удивительный ответ, Роб! Предложение: добавьте пример vCard XML. –

+0

Нет. Я никогда такого не видел. Я предполагаю, что люди, которым нужен этот код, уже знают, как получить vcard. Если они этого не сделают, они могут задать здесь новый вопрос. –

+0

Спасибо Rob Kenndy, но у меня есть ошибка Jpeg ошибка # 53 реализация использует omnixmlutils; {$ R * .dfm} ... function SelectGraphicClass (const MimeType: string): TGraphicClass; ... функция CreateGraphicFromVCardPhoto (const BinVal, MimeType: string): TGraphic; процедура TForm1.Button1Click (отправитель: TObject); begin memo1.lines.loadfromfile ('c: \ cvg.bin'); image1.Picture.Graphic: = CreateGraphicFromVCardPhoto (memo1.text, 'image/jpeg'); конец; {cvg.bin файл находится здесь http://www.anasel.com.tr/cvgxml.txt} {http://www.anasel.com.tr/cvg.bin} – cvg

Смежные вопросы