• 0
Alex7wrt

Область, занимаемая TBitmap

Вопрос

Часто при отрисовке битмапа на холсте используется метод 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)

Прав ли я или не прав? Если нет, то почему?

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

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


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

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

  • 0

Не верно) поскольку, как правильно отмечено отмечено, нумерация с нуля, то битмап, имеющий размер 100 пиксел, заканчивается на числе 99 (0 - 99 = 100). Отсюда и такое указание. То бишь при размере 100 указывается фактически размер 0 - 99, и последний пиксел 99.

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

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


Ссылка на сообщение
Поделиться на других сайтах
  • 0
7 часов назад, Alex7wrt сказал:

Прав ли я или не прав? Если нет, то почему?

потому что вы видите Width/Height,  а рассуждаете про Right/Bottom

в GDI, где указывались именно координаты, а не ширина/высота, тем не менее, эта единичка тоже отнималась внутри функции, так что самому это делать было также не нужно))

Alex7wrt понравилось это

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


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

У TBitmap есть метод BoundsF, достаточно посмотреть его реализацию

property BoundsF: TRectF read GetBoundsF;
...
function TBitmap.GetBoundsF: TRectF;
begin
  Result := TRectF.Create(0, 0, Width, Height);
end;

 

Alex7wrt понравилось это

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


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

То есть все-таки вопреки подсказке в SrcRect нужно вводить не (Left, Top, Right, Bottom), а (Left, Top, Width, Height)?

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


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

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

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

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

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


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

Войти

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


Войти сейчас

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

    • Автор: 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, и я не очень понимаю как это сделать.
       
    • Автор: 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 :=
  • Сейчас на странице   0 пользователей

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