• 0
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);
 

Кто-то сталкивался? Есть мысли как лечить?

Всем спасибо!

Изменено пользователем Barbanel

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

6 ответов на этот вопрос

  • 0

Проверяйте, что работа идет в основном потоке, В неосоновном ловил такие проблемы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Это основной поток. Голова уже не варит(((

Изменено пользователем Barbanel
Конец рабочего дня, голова не варит

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
21 минуту назад, Barbanel сказал:

В том-то и дело, что это неосновной поток. Менять не вариант, таково ТЗ.

А зачем менять. Можно же просто засинхронизировать:

TThread.ForceQueue(nil, procedure
  begin
    MaxSize := CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize);
  end);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
В 23.06.2017 в 18:31, dnekrasov сказал:

А зачем менять. Можно же просто засинхронизировать:


TThread.ForceQueue(nil, procedure
  begin
    MaxSize := CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize);
  end);

 

ForceQueue не работает под андроидом. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
1 минуту назад, Евгений Корепов сказал:

ForceQueue не работает под андроидом

В чём проблема - используйте Queue или Synchronize

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Похожие публикации

    • Автор: 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;  
    • Автор: Vizit0r
      Delphi Seattle, Android 5.0.1
      Формирую картинку через ScanLine. На выходе полученный битмап рисуется на полотне TImage, на котором перед этим был нарисован Rect.
      GlobalBitmap - формированный tbitmap.
                 with ObjectPreviewImage.Bitmap.Canvas do             begin               BeginScene;               Clear(TAlphaColorRec.White);               DRect := TRectF.Create(0, 0, GlobalBitmap.Width + 8, GlobalBitmap.Height + 8);               DrawRect(DRect, 0, 0, AllCorners,                        StealthForm.ObjectPreviewImage.AbsoluteOpacity);               DRect := TRectF.Create(0, 0, GlobalBitmap.Width, GlobalBitmap.Height);               DrawBitmap(GlobalBitmap,DRect,                  TRectF.Create(2, 2, GlobalBitmap.Width + 2, GlobalBitmap.Height + 2), 1);               EndScene;             end;  
      Проблема собственно в чем - в андроидной версии слева и внизу рамка "съедается". В Win32 версии все отлично. На прилагаемых скриншотах это четко видно.
      Документацию читал, гугл гуглил.
       
      Что я делаю не так? Или это неизвестные подводные камни андроидного рисования на полотне?
       
      P.S. Картинка одинаковая, цвет к определенной области применяется не верно. Походу тоже андроидные приколы. Но с этим я уже разберусь.
      P.P.S. Уже разобрался с цветом - под андроидом Blue и Red в пикселе надо поменять местами. А насчет канвы - не получается никак.
      P

    • Автор: 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:
      Что я делаю не так? Подскажите, пож-та, хороший пример для выполнения такой задачи (желательно с применением потоков - чтобы приложение не висло на период загрузки данных из HTTP). Спасибо большое!
       
       
    • Автор: Navovvol
      Как вывести текст на изображение так, чтобы его можно было сохранить в .jpg формате.
      P.S. Нет метода TextOut у Image.
    • Автор: HoShiMin
      Загружаю картинку в TBitmap из TMemoryStream, но иногда в TBitmap копируется только часть картинки. Загружаю следующим кодом:
      var   ResourceStream: TResourceStream;   Bitmap: TBitmap; begin   ResourceStream := TResourceStream.Create(hInstance, 'IMAGE_NAME', RT_RCDATA);   ResourceStream.Position := 0;   Bitmap.LoadFromStream(ResourceStream);     ResourceStream.SaveToFile('img_res.png');   Bitmap.SaveToFile('img_bitmap.png');     FreeAndNil(ResourceStream); end; В итоге в img_res.png нормальное изображение, а в img_bitmap.png первые N байт оригинала, при одинаковом размере картинки N одинаковое. С TMemoryStream аналогично.
      Как исправить?
    • Автор: Gor777
      Коллеги
      Есть проблема:
      Есть картинка созданная средствами сторонней dll, от нее у меня только HBITMAP Как мне ее перекинуть в TBitmap, и вывести ее например в контрол TImage?  
    • Автор: VirusZ2D
      доброго времени суток подскажите метод как засунуть иконку в bitmap
       
      получаю иконку папки и ума не приложу как ее преобразовать 
      var   infoFile:SHFILEINFO;    flag:Cardinal; begin   try     flag:=SHGFI_ICON;     flag:=flag or SHGFI_SMALLICON;     ZeroMemory(Addr(infoFile),SizeOf(infoFile));     SHGetFileInfo('C:\',0,infoFile,SizeOf(infoFile),flag); //   infofile.hIcon (HICON) как присвоить его картинки     Image1.Bitmap :=
    • Автор: estra
      Метод доступа к пикселям TBitmapData.GetScanline работает быстрее чем TBitmap.Map с последующим циклом? Можете привести пример работы с TBitmapData.GetScanline?
  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу