• 0
HoShiMin

Загрузка картинки в TBitmap из TResourceStream

Вопросы

Загружаю картинку в 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 аналогично.

Как исправить?

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

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


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

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

  • 0

        Посмотрел у себя  проблем не было делаю так:

.....

   pi := TresourceStream.Create(0, 'neoplach',
                        PChar(RT_RCDATA));
                      imageo[i].LoadFromStream(pi);
                      pi.Free; 

может instance? ))) И курсор я не перевожу, а картинки большие?

....

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

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


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

        Посмотрел у себя  проблем не было делаю так:

.....

   pi := TresourceStream.Create(0, 'neoplach',
                        PChar(RT_RCDATA));
                      imageo[i].LoadFromStream(pi);
                      pi.Free; 

может instance? ))) И курсор я не перевожу, а картинки большие?

....

Картинки в пределах 50 Кб, с hInstance'ом всё нормально. В большинстве случаев всё грузится нормально, но иногда копируется только пара сотен первых байт оригинала.

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


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

Это с одним и тем же ресурсом происходит( картинкой) в одном потоке и под win32?

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


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

Это с одним и тем же ресурсом происходит( картинкой) в одном потоке и под win32?

Один поток, один и тот же ресурс, и под Win32, и под Win64. И ещё раз уточню - это происходит не всегда, а достаточно редко. Причём проблема именно с заполнением битмапа из TStream'a (из любого), а не именно с TResourceStream.

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


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

Еще припоминаю с давних пор были проблемы с другими форматами кроме родного bmp при передаче через поток... Не знаю как сейчас.

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


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

 

Это с одним и тем же ресурсом происходит( картинкой) в одном потоке и под win32?

Один поток, один и тот же ресурс, и под Win32, и под Win64. И ещё раз уточню - это происходит не всегда, а достаточно редко. Причём проблема именно с заполнением битмапа из TStream'a (из любого), а не именно с TResourceStream.

 

Может проблема не в заполнении битмапа из ресурса, а в сохранении битмапа в файл? Из первого Вашего сообщения вроде следует второй вариант.

Может быть проблема в том, что Вы сохраняете битмап в png?

Попробуйте подключить модуль FMX.Types, если еще не подключен. Там есть класс TBitmapCodecManager, предназначенный для конвертирования изображений в разные форматы. Подробнее в книге Осипова "Программирование для Windows, OS X, iOS и Android" на 236 стр.

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

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


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

в fmx проблема с картинками, у меня ни разу не получилось из ресурсов вытащить файл (png к слову сказать).

вообще xx.Bitmap кушает все форматы зарегистрированные в среде. с этим проблем не должно быть. а вот само хранение вызывает интерес.

я поступил по другому, закинул картинки в Deployment и проблема пропала

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


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

в fmx проблема с картинками, у меня ни разу не получилось из ресурсов вытащить файл (png к слову сказать).

вообще xx.Bitmap кушает все форматы зарегистрированные в среде. с этим проблем не должно быть. а вот само хранение вызывает интерес.

я поступил по другому, закинул картинки в Deployment и проблема пропала

Много раз вытаскивал Png из ресурсов, проблем не замечено.

Например загрузка 40 изображений с именами "PngImage_1"..."Png_Image_40" в массив

    for n:=0 to 39 do begin
        rs:=TResourceStream.Create(0,'PngImage_'+inttostr(n+1),PChar(RT_RCDATA));
        setlength(img,n+1); img[n]:=tbitmap.Create; img[n].LoadFromStream(rs); rs.Free;
    end;
Изменено пользователем Alex7wrt

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


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

Может быть проблема в том, что Вы сохраняете битмап в png?

Попробуйте подключить модуль FMX.Types, если еще не подключен. Там есть класс TBitmapCodecManager, предназначенный для конвертирования изображений в разные форматы. Подробнее в книге Осипова "Программирование для Windows, OS X, iOS и Android" на 236 стр.

 

По сети программа получает картинку в png (грузится в TMemoryStream), оттуда загружается во временный TBitmap, из которого потом грузится в TImage на форме. И в промежуточном Bitmap'е она время от времени бьётся: не отрисовывается на форме, а при сохранении получаю лишь несколько первых байт оригинальной картинки, которая в целости и сохранности лежит в TMemoryStream. Метод LoadFromStream в TBitmap'е как раз реализован через BitmapCodecManager, поэтому "ручная" конвертация проблему не решит, ибо получится то же самое.

Меня больше смущает то, что бьётся не всегда, а довольно редко. При этом другие потоки не пытаются получить доступ к промежуточному битмапу, скопировать картинку никто не мешает.

 

С TResourceStream то же самое. Иногда не грузится из него картинка. И если с ним можно замаскировать проблему, закинув картинки в Deployment, то с TMemoryStream так не получится, т.к. картинки приходят по сети.

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

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


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

Наверно не поможет, но все-таки: может попробовать сразу с потока грузить в TImage - TImage.Bitmap.LoadFromStream? А потом с него уже сохранять...

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

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

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

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

    • От 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;  
    • От 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). Спасибо большое!
       
       
  • Последние посетители   0 пользователей онлайн

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