Перейти к содержанию
Fire Monkey от А до Я
  • 0

[TBitmap] Загрузка изображений из интернета в приложение


ra.eremeev

Вопрос

Друзья, выручайте!

 

Уже на сутки "завис"...

 

Приложение под Android должно загружать картинки в TListViewItem (аватарки) с HTTP.

Ресурс доступен. Картинки на нем тоже.

 

Использую iDHTTP (iDHTTP тоже "кидал" на форму и создавал динамически - результат один) и TMemoryStream.

Код ниже.

 

Само приложение на устройстве выдает ошибку: Access violation at address 559E45CC accessing address 00000000

Отладчик выдает: class segmentation fault 11

 

Опытным путем установил, что ошибка, скорее всего, возникает при попытке заполнения TMemoryStream (пробовал TMemoryStream.LoadFromFile - то же самое, хотя приложением TListViewItem.BitMap.LoadFromFile с этим же файлом проходит на ура и все работает).

 

Во всех случаях используются PNG-картинки небольшого размера и разрешения: 20-25 кБ.

В коде адрес картинки указан тестовый осознанно (в приложение картинка по используемому адресу доступна).

 

 

Часть кода:

var item:TListViewItem;
      pic:TMemoryStream;
      idhttp1:tidhttp;
...
idhttp1.Create(Application);
pic:=TMemoryStream.Create;
try
 IdHTTP.Get('http://site.ru/icons/icon.png, pic);
    try
     Item.Bitmap.LoadFromStream(pic);
     except
    end;
    finally
    pic.Free;
    IdHTTP1.Free;
   end;

Вопроса 2:

  1. Что я делаю не так?
  2. Подскажите, пож-та, хороший пример для выполнения такой задачи (желательно с применением потоков - чтобы приложение не висло на период загрузки данных из HTTP).

Спасибо большое!

 

 

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Модераторы

idhttp1.Create(Application); - что это за бред?

IdHTTP - это откуда взялось?

никогда и никому этот код не показывай

 

берем файлик во вложении подключаем в проекте и пишем

with ListView1.Items.Add do
begin
  Text := 'Text';
  Bitmap.LoadFromUrl('http://site.ru/icons/icon.png');
end;

не проверял, но должно работать. не нужно пихать в поток, там итак уже используется

FMX.Features.Bitmap.Helpers.zip

Изменено пользователем ZuBy
Ссылка на комментарий
  • 0

ZuBy, спасибо очередной раз!

 

Все прекрасно работает :)

Обрати внимание, пож-та, в представленном тобой модуле необходимо скорректировать наименование в первой строке Unit...

Ссылка на комментарий
  • 0

Использование данной процедуры для загрузки большого числа файлов способно сойти за DDOS-атаку и вызвать блокировки сервером.

Вдруг пригодится...

 

Требует допиливания и исключения инциализаций/разрывов соединений...

 

Здесь затрагивал: http://fire-monkey.ru/topic/2170-zagruzka-failov-iz-interneta/?p=11778 

Ссылка на комментарий
  • 0

У меня почему то не работает. Помимо FMX.Features.Bitmap.Helpers пробовал и другие подобные. Ни один на андроид не работает, хотя под Windows все нормально! Приложение либо подвисает, либо вообще ничего не происходит! 

Использую Delphi 10 Seattle, Android 6.0.1

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Похожий контент

    • Автор Barbanel
      Всем здравствуйте, и мое почтение!
      Возникла сильная необходимость передать объект JImage в so-библиотеку, написанную на c++
      Суть - нужно передать изображение в библиотеку распознавания лиц и ориентации головы.
      В библиотеке есть функция, объявленная так:
      jint JNIEXPORT JNICALL DLIB_JNI_METHOD(jniBitmapExtractFaceGazes)(JNIEnv* env, jobject thiz, jobject bitmap) {...} В Delphi я описал эту функцию следующим образом:
      var jniExtractGazes : function(PVM: PJNIEnv; Reserved: Pointer; bitmap: JObject): INT; cdecl; Гружу/ищу ее так:
      function HPELoadLibrary: boolean; var lJNIInt : JNIInt; begin Result := False; HPEMode := MODE_ITERATIVE; {$IFDEF ANDROID} HPEDocDir := IncludeTrailingPathDelimiter(System.IOUtils.TPath.GetDocumentsPath); {$ELSE} exit; {$ENDIF} HPELibraryHandle := LoadLibrary(PChar(HPEDocDir + 'libhead_pose_det.so')); if ( HPELibraryHandle = 0 ) then Exit; PEnv := TJNIResolver.GetJNIEnv; PVM := PJavaVM(System.JavaMachine); if HPELibraryHandle <> 0 then begin @OnLoadFunc := GetProcAddress(HPELibraryHandle, 'JNI_OnLoad'); if not Assigned(OnLoadFunc) then begin FreeLibrary(HPELibraryHandle); Exit; end; lJNIInt := OnLoadFunc(PVM, nil); @jniInit := GetProcAddress(HPELibraryHandle, 'Java_com_beraldo_hpe_dlib_HeadPoseDetector_jniInit'); //jniInit @jniDeInit := GetProcAddress(HPELibraryHandle, 'Java_com_beraldo_hpe_dlib_HeadPoseDetector_jniDeInit'); //jniDeInit @jniExtractGazes := GetProcAddress(HPELibraryHandle, 'Java_com_beraldo_hpe_dlib_HeadPoseDetector_jniBitmapExtractFaceGazes'); Result := True; end; end; Адреса всех функций находятся, jniInit и OnLoadFunc отрабатывают корректно.
      Проблема с функцией jniExtractGazes.
      function HPEDetect(ABitmap: TBitmap): INT; var lBitmap : jBitmap; begin result := 0; if ( HPELibraryHandle = 0 ) then exit; lBitmap := BitmapToJBitmap(ABitmap); result := jniExtractGazes(PEnv, nil, lBitmap); <===== Project FaceLockClientMobile.apk raised exception class Aborted (6). end; На указанной строке всегда вылетает Exception Aborted. Стек ничего внятного не показывает.
      Путем долгих проб и ошибок прихожу к подозрению что я неправильно передаю Java-объект в библиотеку.
      Как его передавать из Дельфи правильно - не могу найти.
      Буду очень признателен за любые подсказки и догадки.
       
      PS речь идет о этой библиотеке: https://github.com/beraldofilippo/android-hpe-library
       
       
    • Автор Евгений Корепов
      Для одного своего проекта сделал, поделюсь, вдруг кому пригодится. Тестировал под Windows и Android.
      Для использования просто добавьте BitmapAsyncLoader в uses, а дальше все просто:
      ImageControl.Bitmap.LoadFromURLAsync('https://bipbap.ru/wp-content/uploads/2017/10/0_8eb56_842bba74_XL-640x400.jpg'); Код юнита хелпера:
      unit BitmapAsyncLoader; interface uses FMX.Graphics, System.Net.HttpClient, System.Types, System.Classes; type TBitmapAsyncLoader = class helper for TBitmap procedure LoadFromUrlAsync(const AUrl : String); end; implementation var AHTTPClient : THTTPClient; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then TThread.Synchronize(Nil, procedure begin try Self.LoadFromStream(AHTTPResponse.ContentStream); except end; end ); end, AURL ); except end; end; initialization AHTTPClient:=THTTPClient.Create; finalization if Assigned(AHTTPClient) then begin AHTTPClient.DisposeOf; end; end. Архив с тестовым проектом прилагаю.
      BitmapAsyncLoader.7z
    • Автор PavelS
      Здравствуйте! Начал изучать FireMonkey  и столкнулся с тем, что TBitmap не поддерживает размер изображения больше 8132, кажется. Т.е. большие размеры рисунка он грузит, но за счёт потери качества, размер пиксела растёт, а размер рисунка по оси всё равно не превышает 8132. В то же время в простом дельфи можно грузить и работать с гораздо большими размерами, например, один из файлов имеет размер 61216 х 1486 точек. Подскажите пожалуйста, есть ли возможность работать с большими файлами в FireMоnkey и как это можно организовать? Программа создаётся для работы только в Windows.
    • Автор Tot999
      Добрый день! 
      Решил покопаться в своей старой спрайтовой игрушке, чтобы освежить в памяти знания и состряпать что-нибудь новое. Возникли сомнения, нормально ли сделано графическое отображение, можно ли доработать.
      Все спрайты в дизайнтайме распиханы по Timagelist-ам.  На старте приложения я загружаю битмапы из имэджлистов в свои обджектлисты, подгоняя под нужный размер. 
      MeduzasBitmpAr : array [1..numofMeduzas] of TObjectList<Tbitmap>;  
      Дальше рисую по таймеру в основном окне игры Tpaintbox.OnPaint:
               
      В принципе, даже на слабеньких телефончиках, всё вроде бодро. Но может, опытные товарищи чего подскажут, а то я 3ий день в собственном соку варюсь, ничего толкового.
    • Автор x11
      Можно ли получить TBitmap из TBitmapImage? Конвертировать.
    • Автор Freezer_86
      Пишу кроссплатформенное приложение. Результат поиска отображается в TGrid. Стал вопрос отображения картинки в одной из колонок.
      На Windows все ок, но на планшете происходят просто чудеса: при первом отображение все корректно, но если простоколить вверх-вниз как картинки одни перетираются другими, часть вообще отображается вверх ногами.
      Код для сохранение картинки(jpg) в базу:
      if Assigned(sm) then begin sm.Position := 0; //TBlobField(dmData.cdsPlayerData.FieldByName('Photo')).LoadFromStream(sm); vImage := TImage.Create(nil); try sm.Position := 0; vImage.Bitmap.LoadFromStream(sm); vKoef := vImage.Bitmap.Height / 64; vImage.Bitmap.Resize(Trunc(vImage.Bitmap.Width / vKoef), Trunc(vImage.Bitmap.Height / vKoef)); sm.Free; sm := TMemoryStream.Create(); try vImage.Bitmap.SaveToStream(sm); TBlobField(dmData.cdsPlayerData.FieldByName('SmallPhoto')).LoadFromStream(sm); finally sm.Free; end; finally vImage.Free; end; end{if}; До скрола:

      После скрола:

      Пробовал и LiveBinding, и ручную прорисовку - результат один и тот же. Есть идеи что не так?
      P.S. Знаю что нужно делать через TListView, но заказчик хочет «сеточку как в старой программе», так как на android будет работать только на планшетах – я согласился.
       
    • Автор Barbanel
      Здравствуйте!
      Стоит задача загружать фотографии и отображать их в списке. Казалось бы, как два пальца, но...
      Код работал долгое время, все грузилось и отображалось. Спустя какое-то время, фото грузиться перестали. Дебаггинг выявил, замкнутый бесконечный цикл в этой процедуре:
      procedure TBitmap.AssignFromSurface(const Source: TBitmapSurface); var BitmapData: TBitmapData; MaxSize: Integer; ResampledSurface: TBitmapSurface; I: Integer; SourceRect: TRectF; begin MaxSize := CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize); <-- MaxSize = 0 if (Source.Width > MaxSize) or (Source.Height > MaxSize) then begin SourceRect := TRectF.Create(0, 0, Source.Width, Source.Height); SourceRect.Fit(TRectF.Create(0, 0, MaxSize, MaxSize)); ResampledSurface := TBitmapSurface.Create; try ResampledSurface.StretchFrom(Source, Trunc(SourceRect.Width), Trunc(SourceRect.Height), PixelFormat); AssignFromSurface(ResampledSurface); <-- infinity loop here finally ResampledSurface.Free; end; end else begin SetSize(Source.Width, Source.Height); if Map(TMapAccess.Write, BitmapData) then try for I := 0 to TBitmapSurface(Source).Height - 1 do Move(TBitmapSurface(Source).Scanline[I]^, BitmapData.GetScanline(I)^, BitmapData.BytesPerLine); finally Unmap(BitmapData); end; end; end; В самом начале процедуры MaxSize получает значение 0 (ноль!), размеры картинки больше нуля и процедура влетает в бесконечный цикл на строке
            AssignFromSurface(ResampledSurface);
       
      Кто-то сталкивался? Есть мысли как лечить?
      Всем спасибо!
    • Автор hryasch
      Добрый день. Существует одна проблема, с которой уже несколько недель не могу справиться. Есть старый код под WinAPI, его нужно переделать под Android через firemonkey. И главная проблема - есть код, который из собственного формата делает HBITMAP из WinAPI. Фактически это структура, где последнее поле - указатели на биты. Это переделать легко, создав собственную копию такой структуры. Но теперь мне нужно перевести ее в TBitmap, и я не очень понимаю как это сделать.
       
    • Автор Alex7wrt
      Часто при отрисовке битмапа на холсте используется метод DrawBitmap, где, в частности, в качестве аргумента необходимо указать прямоугольные области источника (SrcRect) и приемника (DestRect). Эти прямоугольники имеют формат записи (Left, Top, Right, Bottom).
      При указании в качестве SrcRect всего битмапа целиком как здесь на формуме так и в книге Осипова я встречал такую запись:
      RectF(0,0,ABitmap.Width,ABitmap.Height) Но моя логика подсказывает, что такой битмап должен иметь размеры на 1 пиксель по горизонтали и вертикали больше, чем на самом деле, ведь первый пиксель имеет координаты (0;0), а последний (ABitmap.Width,ABitmap.Height). Что, наверное, приводит к искажениям при отображении битмапа на холсте.
      Мне думается, что при рисовании целого битмапа следует писать так:
      RectF(0,0,ABitmap.Width-1,ABitmap.Height-1) Прав ли я или не прав? Если нет, то почему?
    • Автор AlexG
      Привет, друзья!
      Подскажите - как, с максимально возможной скоростью, определить отсутствие изображения как такового в TBitmap?
      Т.е. - есть TBitmap. Он либо заполнен изображением (картинка), либо он - абсолютно черный прямоугольник.
      Каким способом можно узнать - что в нем именно изображение? Т.е. - НЕ абсолютно черный прямоугольник...
      И определить это нужно "мгновенно" (условно выражаясь).
      Заранее всем благодарен за участие!
      P.S. Варианты типа того что ниже - не предлагать)) Хотелось бы что-то "побыстрее"! Еще раз спасибо!
      function IsBitmapEmpty(Bmp: TBitmap): Boolean; var X, Y : Integer; BmpData: TBitmapData; yAddr : Integer; AlphaCount : integer; begin Result := False; try AlphaCount := 0; Bmp.Map(TMapAccess.Read, BmpData); for Y := 0 to Bmp.Height div 2 do begin YAddr := Y * Bmp.Height; for X := 0 to Bmp.Width - 1 do if (PAlphaColorArray(BmpData.Data)^[YAddr + X] <> TAlphaColorRec.Null) and (PAlphaColorArray(BmpData.Data)^[YAddr + X] <> TAlphaColorRec.Black) then begin inc(AlphaCount); Break; end; if AlphaCount > 0 then Break; end; finally Bmp.Unmap(BmpData); Result := AlphaCount = 0; end; end;  
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...