Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Передача картинки по UDP одним пакетом


Автор: Max_Rendel 10.5.2008, 09:17
Поправте пожалуйста!
Задумка: По нажатию кнопки, клиент предаёт картинку серверу одним пакетом (!!!обязательно не сохраняя её предварительно на диске!!! размер картинки от 3кб до 20кб), после принятия картинки сервер помещает её в Image1.


Вот клиент:
Код

procedure TForm1.Button1Click(Sender: TObject);
var
  TM: TMemoryStream;
  jpg: TJPEGImage;
begin
  TM := TMemoryStream.Create;
  jpg := TJPEGImage.Create;

  jpg.Assign(Image1.Picture.Bitmap);
  jpg.CompressionQuality := 10;
  jpg.Compress;
  jpg.SaveToStream(TM);
  jpg.free;

  IdUDPClient1.SendBuffer(TM, TM.Size);

  TM.Free;
end;


Вот сервер:
Код

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  TM: TMemoryStream;
  jpg: TJPEGImage;
begin
  TM := TMemoryStream.Create;
  jpg := TJPEGImage.Create;

  if AData.Size > 0 then
  begin
    TM.CopyFrom(AData, AData.Size);

    jpg.LoadFromStream(TM);

    image1.Picture.Graphic := jpg;
  end;

  TM.Free;
  jpg.free;
end;


На сервре выскакиает ошибка: JPEG error #42

Что я делаю не так? smile 

Автор: Exai1e 11.5.2008, 16:06
а размер посланный и принятый сверял ?
мб теряется заголовок

Добавлено @ 16:07
попробуй сохранить принятые данные в стим/фаил и открыть win средствами

Автор: Max_Rendel 12.5.2008, 02:05
Exai1e, да размер замерял перед отправкой и после. Самое интересное, что всё в порядке...
Пробывал сохранять в TFileStream (на диск), его размер 0.


Может что не так с отправкой и приёмом делаю?????? smile 
Может каким другим способом сделать???? Но без сохранения файла на диск!

Автор: MetalFan 12.5.2008, 07:58
1. какой компонент для UDP пользуется?
2.
Цитата(Max_Rendel @  10.5.2008,  09:17 Найти цитируемый пост)
if AData.Size > 0 then
  begin
    TM.CopyFrom(AData, AData.Size);
    jpg.LoadFromStream™;
    image1.Picture.Graphic := jpg;
  end;

Цитата(Max_Rendel @  12.5.2008,  02:05 Найти цитируемый пост)
Пробывал сохранять в TFileStream (на диск), его размер 0.

что-то не совсем совместимо утверждение....

попробуй после CopyFrom перед загрузкой в jpg сделать Seek( 0, soFromBeginning )

Добавлено через 43 секунды
что-то сомнение берет, что под буфером подразумевается TStream
Цитата(Max_Rendel @  10.5.2008,  09:17 Найти цитируемый пост)
IdUDPClient1.SendBuffer(TM, TM.Size);


Автор: Max_Rendel 12.5.2008, 11:05
MetalFan,

1) Indy (кот. по умолчанию стоит в Delphi7)

2) 
Цитата(MetalFan @  12.5.2008,  13:58 Найти цитируемый пост)
что-то не совсем совместимо утверждение....


не понял замечания???? Поподробней пожалуйста…

3)
Цитата(MetalFan @  12.5.2008,  13:58 Найти цитируемый пост)
попробуй после CopyFrom перед загрузкой в jpg сделать Seek( 0, soFromBeginning )

Пробывал делать так после сохранения в стрим:
Код

TM.Position := 0;

4) 
Цитата(MetalFan @  12.5.2008,  13:58 Найти цитируемый пост)
что-то сомнение берет, что под буфером подразумевается TStream

Тогда что????

Автор: ksili 12.5.2008, 11:15
Может между
Код

  IdUDPClient1.SendBuffer(TM, TM.Size);

и
Код

  TM.Free;

надо сделать задержку? А-то оно ещё отправляется, а вы его сразу удаляете...

Автор: Max_Rendel 12.5.2008, 11:38
ksili сделал, и не чего не поменялось.

Я уже немного изменил вид кода и избавился от JPG (пока не разберусь), вместо него отправляю маленький Bitmap.

Вот как он выглядит:

Код

procedure TForm1.Button1Click(Sender: TObject);
var
  TM: TMemoryStream;
begin
  TM := TMemoryStream.Create;

  Image1.Picture.Bitmap.SaveToStream(TM);
  TM.Position := 0;

  Label1.Caption := IntToStr(TM.Size);

  IdUDPClient1.SendBuffer(TM, TM.Size);

  Sleep(500);
  TM.Free;
end;

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  TM: TMemoryStream;
begin
  TM := TMemoryStream.Create;

  if AData.Size > 0 then
  begin
    TM.CopyFrom(AData, AData.Size);

    Label2.Caption := IntToStr(TM.Size);

    Image2.Picture.Bitmap.LoadFromStream(TM);
    Image2.Refresh;
  end;

  Sleep(500);
  TM.Free;
end;


Ошибка больше не вылетает, но Image всё равно не отображает картинку.
Но пока всё без результатно...
  smile 

Автор: ksili 12.5.2008, 11:47
TM.Size в клиенте и в сервере одинаковый?

Добавлено через 34 секунды
А это всё на одном компе происходит?

Автор: Max_Rendel 12.5.2008, 12:05
Цитата(ksili @  12.5.2008,  17:47 Найти цитируемый пост)
TM.Size в клиенте и в сервере одинаковый?

Да.

Цитата(ksili @  12.5.2008,  17:47 Найти цитируемый пост)
А это всё на одном компе происходит?

Для отладки я сделал всё в одной проге, но пробывал и на сервер - клиент.

Автор: ksili 12.5.2008, 12:15
А проверял в TMemoryStream->Memory и AData именно байты твоей картинки после чтения? можно проверить несколько первых байт.

Может ещё попробовать использовать не метод UDPRead, а событие OnUDPRead?

Добавлено @ 12:20
С потоками ещё вроде такой косяк, что нулевой байт считается концом потока (а в BMP это просто чёрный цвет). Так что может быть при загрузке
Код

Image2.Picture.Bitmap.LoadFromStream(TM);

до конца не грузится из-за того, что встречается именно такой байт. Тогда надо будет грузить не так, а копируя блок памяти, например при помощи memcpy. Только не забудь тогда выделить вручную память под Image2.Picture.Bitmap.

Автор: ksili 12.5.2008, 12:34
Кстати, до чтения картинки, размеры Image2 не нулевые случайно? Если так, то возможно придётся вручную выставлять размеры его канвы, а возможно и самого битмапа

Автор: Max_Rendel 12.5.2008, 16:06
Цитата(ksili @  12.5.2008,  18:15 Найти цитируемый пост)
Может ещё попробовать использовать не метод UDPRead, а событие OnUDPRead?

Это как?

Автор: MetalFan 12.5.2008, 18:09
Цитата(Max_Rendel @  12.5.2008,  11:05 Найти цитируемый пост)
Indy (кот. по умолчанию стоит в Delphi7)

так там багов выше крыши. скачай и поставь по-свежее.

Добавлено через 6 минут и 34 секунды
Цитата(Max_Rendel @  12.5.2008,  11:05 Найти цитируемый пост)
не понял замечания???? Поподробней пожалуйста…

ты говоришь, что выскакивает jpeg error, т.е. выполняется приведенная мной венка твоего кода
но при сохранении в файл размер 0. значит не так сохраняешь.

Цитата(Max_Rendel @  12.5.2008,  11:05 Найти цитируемый пост)
Тогда что???? 

не знаю что там было в древних индейцах, но наверняка не TStream

Автор: Max_Rendel 13.5.2008, 03:48
У кого не будь есть пример отправки по UDP файла без предварительного сохранения на диск???????
(в любой версии Indy, только укажите её)

PLZ
 smile 
А товсем нечего не получается......  smile 

Автор: Max_Rendel 14.5.2008, 10:04
Ну вроде дела сдвинулись.  smile 
Но опять же с проблемами…
Вот код:


Код

procedure TForm1.Button1Click(Sender: TObject);
var
  Msg: String;
begin
  Msg := String(Image1.Picture.Bitmap);

  IdUDPClient1.Send(Msg);
end;

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  Msg: String;
begin
  if AData.Size > 0 then
  begin
    SetLength(Msg, AData.Size);
    AData.ReadBuffer(Msg[1], Length(Msg));

    Image2.Picture.Bitmap := TBitmap(Msg);
  end;
end;


Всё работает, но в этой программе и сервер и клиент находятся на одной форме, т.е. в одной программа. А когда я делаю отдельно сервер и клиент, те ничего не работает. На сервере выскакивает ошибка (Вот она http://ipicture.ru/uploads/080514/gxtqW9itSY.jpg), в тот момент когда я начинаю грузить принятые данные в Image2.

Код

Image2.Picture.Bitmap := TBitmap(Msg);


Замерял размер до отправки и после, всё OK. Проверял побайтно, всё OK.
Что я не так делаю?????
  smile 

Автор: MetalFan 14.5.2008, 11:14
Цитата(Max_Rendel @  14.5.2008,  10:04 Найти цитируемый пост)
    
Image2.Picture.Bitmap := TBitmap(Msg)

кто тебе такой бред подсказал?

Автор: Max_Rendel 14.5.2008, 12:45
Цитата(MetalFan @  14.5.2008,  17:14 Найти цитируемый пост)
кто тебе такой бред подсказал?

Сам придумал.  smile 

А как правельно загрузить данные в Image2.Picture.Bitmap?

Автор: Max_Rendel 15.5.2008, 03:40
ВСЁ ПОЛУЧИЛОСЬ!!! smile ТЕМУ МОЖНО ЗАКРЫВАТЬ!!!!!!!  smile 

Клиент:
Код

procedure TForm1.Button1Click(Sender: TObject);
var
  MemStream: TMemoryStream;
  jpg: TJPEGImage;
begin
  MemStream:= TMemoryStream.Create;
  jpg := TJPEGImage.Create;

  jpg.Assign(Image1.Picture.Bitmap);
  jpg.ProgressiveEncoding := True;
  jpg.CompressionQuality := 30;
  jpg.Compress;

  jpg.SaveToStream(MemStream);;
  MemStream.Position := 0;

  IdUDPClient1.SendBuffer(MemStream.Memory^,MemStream.Size);

  MemStream.Free;
  jpg.Free;
end;


Сервер:
Код

procedure TForm1.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
  ABinding: TIdSocketHandle);
var
  jpg:       TJPEGImage;
  MemStream: TMemoryStream;
begin
  if AData.Size > 0 then
  begin
    jpg :=      TJPEGImage.Create;
    MemStream:= TMemoryStream.Create;

    MemStream.CopyFrom(AData, AData.Size);
    MemStream.Position := 0;

    jpg.LoadFromStream(MemStream);
    Image1.Picture.Graphic := jpg;

    MemStream.Free;
    jpg.Free;
  end;
end;


Один нюанс: Размер буфера должен быть больше чем передаваемый файл.

Всем кто принимал участие, БОЛЬШОЕ СПОСИБО! smile 

Автор: LeonW 14.11.2011, 08:49
Здравствуйте! может кто подсказать как правельно отправить хотябы по 64кб через УДП Спасибо!. smile 
Код

begin
bmp:= TBitmap.Create;
Jpg:= TJpegImage.Create;
bmp.Height:=Screen.Height;
bmp.Width:=Screen.Width;
DC:=GetDC(0);
PatBlt(Form1.Canvas.Handle, 0, 0, Form1.ClientWidth, Form1.ClientHeight, WHITENESS);
bitblt(bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DC, 0, 0, SRCCOPY);
  Jpg.Assign(Bmp);
  jpg.CompressionQuality:=12;
  jpg.Compress;
ReleaseDC(0, DC);
  try
MemStream:= TMemoryStream.Create;
  jpg.SaveToStream(MemStream);
  MemStream.Position := 0;
IdUDPClient1.SendBuffer(MemStream.Memory^,MemStream.Size);
 finally
MemStream.Free;
jpg.Free;
Bmp.Free;
end;

с этим кодом будут ошибки вылетать  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)