Скачать изображение
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.37] |
|
|
Соблюдайте общие правила форума
MSDN Library
FAQ раздела
Поиск по разделу
Как правильно задавать вопросы
Скачать изображение
|
Сообщ.
#1
,
|
|
|
|
Нужно скачать изображение по УРЛ и передать скаченную матрицу в TImage.
Пытался скачать изображение вот так: ![]() ![]() procedure TDownloader.Load; var I:TidHTTP; S:TMemoryStream; JPEG: TJPEGImage; begin i:=TIdHTTP.Create(nil); S:=TMemoryStream.Create; JPEG:=TJPEGImage.Create; try I.Get(URL,S); S.Position:=0; Jpeg.LoadFromStream(S); Image.Picture.Assign(JPeg); finally i.Free; S.Free; JPeg.Free; end; end; Но даже в потоке ,такой код тормозит перерисовку всей формы.Как быть? |
|
Сообщ.
#2
,
|
|
|
|
1) Что-бы загрузка не тормозила перерисовку, перерисовка должна быть отделена от загрузки.
Подсказка хранить картинку надо в TBitmap; 2) Что-бы загрузка не тор мазила не надо каждый раз устанавливать TCP и HTTP соединения. Держи их открытыми. Тот же принцип отдели загрузку от создания соединения. Добавлено PS. Есть предположение что и загрузка сделана с ошибкой странно что работает. |
|
Сообщ.
#3
,
|
|
|
|
Нужно во главе потока грузить.. Execute; а не в отдельных его процедурках типа .Load;....
тогда ни чего не будет тормозить.. |
|
Сообщ.
#4
,
|
|
|
|
faust777,
Естественно, ![]() ![]() TDownloader = class(TThread) |
|
Сообщ.
#5
,
|
|
|
|
Protector
чтобы развеять сомнения faust777, покажи, откуда вызывается метод Load |
|
Сообщ.
#6
,
|
|
|
|
Цитата Pavia @ PS. Есть предположение что и загрузка сделана с ошибкой странно что работает. ![]() ![]() procedure TDownloader.Load; var I:TidHTTP; S:TMemoryStream; JPEG: TJPEGImage; begin i:=TIdHTTP.Create(nil); S:=TMemoryStream.Create; JPEG:=TJPEGImage.Create; try try I.Get(URL,S); except end; S.Write(Pointer(S)^, SizeOf(S)); S.Position:=0; Jpeg.LoadFromStream(S); try if Assigned(Image)and(@Image<>nil)and(not Self.Terminated) then begin Image.Picture.Assign(Jpeg); end; except end; finally i.Free; S.Free; JPeg.Free; end; end; Добавлено MBo, Каким образом корректно обработать ситуацию ,когда поток еще грузит картинку ,а юзер завершает приложение? У меня такая последовательность действий вызывает AV и Еврика показывает утечку памяти (i:=TIdHTTP.Create(nil); - здесь ). |
|
Сообщ.
#7
,
|
|
|
|
Всё не смотрел, но на будущее не помешает подумать, чему равно SizeOf(S)? (TMemoryStream)
И что должна делать волшебная строка? S.Write(Pointer(S)^, SizeOf(S)); для чего @Image<>nil ? |
|
Сообщ.
#8
,
|
|
|
|
Апдейт:
![]() ![]() procedure TDownloader.Execute; var I:TidHTTP; S:TMemoryStream; JPEG: TJPEGImage; begin inherited; i:=TIdHTTP.Create(nil); S:=TMemoryStream.Create; JPEG:=TJPEGImage.Create; try try I.Get(URL,S); except end; S.Position:=0; Jpeg.LoadFromStream(S); try Image.Picture.Assign(Jpeg); except end; finally i.Free; S.Free; JPeg.Free; end; end; А в чем причина утечки памяти? |
|
Сообщ.
#9
,
|
|
|
|
![]() ![]() Image.Picture.Assign(Jpeg); это как у тебя "поток" определяет Где находиться Image?А в общем, как то так).. ![]() ![]() type TForm1 = class(TForm) Button1: TButton; Image1: TImage; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; TDownloader = class(TThread) private HTTP:TidHTTP; JPEG: TJPEGImage; procedure EndDown; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin TDownloader.Create(False); end; constructor TDownloader.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); end; procedure TDownloader.Execute; var S:TMemoryStream; begin HTTP:= TIdHTTP.Create(nil); S:= TMemoryStream.Create; JPEG:=TJPEGImage.Create; try HTTP.Get('http://forum.sources.ru/uploads/av-150083.jpg',S); S.Position:=0; JPEG.LoadFromStream(S); Synchronize(EndDown); except FreeAndNil(S); FreeAndNil(HTTP); JPeg.Free; end; if Assigned(S) then FreeAndNil(S); if Assigned(JPEG) then JPEG.Free; if Assigned(HTTP) then FreeAndNil(HTTP); end; procedure TDownloader.EndDown; begin Form1.Image1.Picture.Assign(JPEG); end; |
|
Сообщ.
#10
,
|
|
|
|
Цитата faust777 @ ![]() ![]() Image.Picture.Assign(Jpeg); это как у тебя "поток" определяет Где находиться Image?А в общем, как то так).. ![]() ![]() type TForm1 = class(TForm) Button1: TButton; Image1: TImage; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; TDownloader = class(TThread) private HTTP:TidHTTP; JPEG: TJPEGImage; procedure EndDown; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin TDownloader.Create(False); end; constructor TDownloader.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); end; procedure TDownloader.Execute; var S:TMemoryStream; begin HTTP:= TIdHTTP.Create(nil); S:= TMemoryStream.Create; JPEG:=TJPEGImage.Create; try HTTP.Get('http://forum.sources.ru/uploads/av-150083.jpg',S); S.Position:=0; JPEG.LoadFromStream(S); Synchronize(EndDown); except FreeAndNil(S); FreeAndNil(HTTP); JPeg.Free; end; if Assigned(S) then FreeAndNil(S); if Assigned(JPEG) then JPEG.Free; if Assigned(HTTP) then FreeAndNil(HTTP); end; procedure TDownloader.EndDown; begin Form1.Image1.Picture.Assign(JPEG); end; Каждую с n картинок ,загружает отдельный поток .Зачем синхронизация? |
|
Сообщ.
#11
,
|
|
|
|
для VCL например)
А уж чего там каждую или как..извени..не телепат. Вот это ты что показал? ![]() ![]() S.Position:=0; Jpeg.LoadFromStream(S); try Image.Picture.Assign(Jpeg); except end; finally i.Free; Такое в принципе не может работать. компилятор это даже запустить не даст.. Давай тогда больше когда своего, а не не понятные обрывки. |
|
Сообщ.
#12
,
|
|
|
|
faust777,
![]() ![]() constructor TDownloader.Create(const URL: string; var Img: TImage); begin inherited Create(false); Self.Url:=URL; Self.Image:=Img; Self.FreeOnTerminate:=true; end; Это весь код . Добавлено Цитата faust777 @ компилятор это даже запустить не даст.. Не утрируйте .Все работает ,корректно пока не наступает описанная ситуация . |
|
Сообщ.
#13
,
|
|
|
|
Цитата faust777 @ except FreeAndNil(S); FreeAndNil(HTTP); JPeg.Free; end; if Assigned(S) then FreeAndNil(S); if Assigned(JPEG) then JPEG.Free; if Assigned(HTTP) then FreeAndNil(HTTP); end; Если написать вместо except слово finally, то можно обойтись одним экземпляром удалений ресурсов. Единственный ньюанс - ожидается ли подавление исключений? Или это такой side-effect? |
|
Сообщ.
#14
,
|
|
|
|
Цитата Mr.Delphist @ Если написать вместо except слово finally, то можно обо.... Тут уж кому как) да и тема не про то..вроде).. Щас то в чём уже проблема.. ведь очевидно что зависаний ни каких нет.. А утечки..Без них Indy наверно ни когда не будет... Насколько критично это, вот в чём вопрос.. Или как вариант ещё, сделать своё "закрытие программы"... что бы когда "юзер завершает приложение", всё остановливалось..очищалось.. |
|
Сообщ.
#15
,
|
|
|
|
Цитата Protector @ Это весь код . Цитата Protector @ А в чем причина утечки памяти? Деструктор потока покажи. |
|
Сообщ.
#16
,
|
|
|
|
Цитата faust777 @ А в общем, как то так).. А удалять поток кто будет? Добавлено Я бы сделал так (схематично, некомпилируемо): ![]() ![]() const MSG_IMGGOT = WM_APP + 1; TDownThread.Create(URL: string; ResponseWnd: HWND); begin fURL := URL; fResp := ResponseWnd; inherited Create(False); FreeOnTerminate := True; end; TDownThread.Execute; begin ... Str := GetURL(fURL); ... Img := TJPEG.Create; Img.LoadFromStream(S); ... // free idHTTP, Stream... PostMessage(fResp, MSG_IMGGOT, 0, LPARAM(Img)); end; TForm.Click begin TDownThread.Create('blabla.com/1.jpg', Handle); end; TForm.MsgImgGot(Msg: TMessage); // message MSG_IMGGOT; var Img: TJPEG; begin Img := TJPEG(Msg.lParam); Image1.Assign(Img); Img.Free; end; |
|
Сообщ.
#17
,
|
|
|
|
оно не свалится с ошибкой без синхронизации? я бы эвентом сделал передав через него указатель на картинку и вызвав его в методе с синхронизацией. ну а при создании потока обработчик в форме повесил бы
|
|
Сообщ.
#18
,
|
|
|
|
medved_68,
![]() ![]() destructor TDownloader.Destroy; begin inherited; end; Добавлено Fr0sT, Вот обращение к изображению по хендлу -это ,как по мне, выход . Добавлено Цитата antonn @ ,оно не свалится с ошибкой без синхронизации? Нет |
|
Сообщ.
#19
,
|
|
|
|
Fr0sT,
Следуя вашей идеи : ![]() ![]() procedure TDownloader.Execute; var I:TidHTTP; begin inherited; i:=TIdHTTP.Create(nil); try try I.Get(URL,S); except end; SetImg; finally FreeAndNil(i); end; end; procedure TDownloader.SetImg; var copydata:COPYDATASTRUCT; begin ZeroMemory(@copydata, SizeOf(TCopyDataStruct)); copydata.dwData:=0; copydata.cbData:=S.Size; copydata.lpData:=S.Memory; SendMessage(Self.hCanv,WM_COPYDATA,Longint(Self.hCanv),lparam(@copydata)); end; procedure TForm1.RecvData(var Msg: TWMCopyData); var S:TMemoryStream; J:TJPEGImage; Data: COPYDATASTRUCT; begin Data:=Msg.CopyDataStruct^; S:=TMemoryStream.Create; J:=TJPEGImage.Create; try S.Write(Data.lpData^,Data.cbData); S.Position:=0; J.LoadFromStream(S); Image1.Assign(J); finally S.Free; J.Free; end; end; А изображение передается поврежденным. |
|
Сообщ.
#20
,
|
|
|
|
Цитата antonn @ оно не свалится с ошибкой без синхронизации? C чего бы? Изображение создается в потоке и отправляется форме, после этого в потоке не используется. Таким образом у меня передаются объекты и строки и ничего не валится. Цитата Protector @ Следуя вашей идеи : Нет уж, пардоньте, в моей идее не было ничего от приведенной каши. Начать хотя бы с того, что судя по названию поля hCanv оно содержит хэндл явно не главной формы. А оно должно посылаться именно главной форме. Затем, copydata - на фига? Если уж так не хочется делать true асинхронный способ - пожалуйста, SendMessage(MainFormHandle, MSG_IMGGOT, 0, LPARAM(Img)) будет синхронным (пока форма не обработает сообщение - поток ждет). Также можно передать и мемористрим, без необходимости копировать его. Метод в таком случае сокращается до ![]() ![]() Thread.Execute; begin ...download to stream... SendMessage(MainFormHandle, MSG_IMGGOT, 0, LPARAM(Str)); Str.Free; end; MainForm.MsgImgGot; begin Str := TMemoryStream(Msg.lParam); J.LoadFromStream(S); Image1.Assign(J); J.Free; end; Добавлено Тем не менее, это не ТРУ, и я это посоветовал исключительно в образовательных целях. |
|
Сообщ.
#21
,
|
|
|
|
Fr0sT, результат идентичен .
Добавлено Цитата Fr0sT @ Тем не менее, это не ТРУ, и я это посоветовал исключительно в образовательных целях. А что же трю? |
|
Сообщ.
#22
,
|
|
|
|
Цитата C чего бы? Изображение создается в потоке и отправляется форме, после этого в потоке не используется. Таким образом у меня передаются объекты и строки и ничего не валится. я никогда так не делал и не разбирался, но думал что в сообщении придет указатель на объект созданный в потоке |
|
Сообщ.
#23
,
|
|
|
|
Цитата Protector @ medved_68, CollapsedWrap disabledLine numbers off destructor TDownloader.Destroy; begin inherited; end; А. Тогда вопросов нет. Особенно в разрезе:Цитата Protector @ ![]() ![]() i:=TIdHTTP.Create(nil); |
|
Сообщ.
#24
,
|
|
|
|
medved_68,Это локальная переменная .
|
|
Сообщ.
#25
,
|
|
|
|
Вопрос для Protector
Цитата Protector @ medved_68,Это локальная переменная . А напомни, где выделяется память для объектов на стеке или в куче? И когда он освобождается? |
|
Сообщ.
#26
,
|
|
|
|
Pavia,
![]() ![]() procedure TDownloader.Load; var I:TidHTTP; S:TMemoryStream; JPEG: TJPEGImage; begin i:=TIdHTTP.Create(nil); S:=TMemoryStream.Create; JPEG:=TJPEGImage.Create; try I.Get(URL,S); S.Position:=0; Jpeg.LoadFromStream(S); Image.Picture.Assign(JPeg); finally i.Free; //Вот где . S.Free; JPeg.Free; end; end; |
|
Сообщ.
#27
,
|
|
|
|
Цитата Pavia @ И когда он освобождается? Цитата Protector @ finally i.Free; //Вот где . Как там по жанру должно быть? А...Вопросов не имею...Так? |
|
Сообщ.
#28
,
|
|
|
|
Мне кажется ,сама Еврика вызывает утечку. Чем еще можно проверять утечки памяти?
Добавлено medved_68,По жанру , в этом месте идет оператор case. |
|
Сообщ.
#29
,
|
|
|
|
Protector
http://www.gunsmoker.ru/2009/05/blog-post_24.html Советую при поиске утечки потренироваться на примерах. |
|
Сообщ.
#30
,
|
|
|
|
так все таки в #22 я неправ и через сообщение (не copydata) отправляется полная копия (новый экземпляр) или все таки ссылка (и автору кода пока просто светит удача (например, что объект не уничтожился при завершении потока до того как с ним закончилась работа вне потока))?
|
|
Сообщ.
#31
,
|
|
|
|
antonn, ну придет указатель на объект, созданный в потоке. И? Он же динамически создан, а не на стеке. Всё тут нормально.
Цитата Protector @ А что же трю? См. первый мой пост Цитата Protector @ результат идентичен А проверь сначала без потока. Если не сработает - приведи полный код потока и обработчиков формы на данный момент |