Перейти к содержанию
  • Регистрация
  • 0
AlexG

Как определить отсутствие изображения как такового в TBitmap?

Вопрос

Привет, друзья!

Подскажите - как, с максимально возможной скоростью, определить отсутствие изображения как такового в 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;

 

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

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


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

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

  • 0

А зачем вам подряд все пиксели перебирать. Можно по диагонали перебрать к примеру 20-30 пикселей (5%-10% из всех пикселей из этой диагонали-линии).

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


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

А зачем вам подряд все пиксели перебирать. Можно по диагонали перебрать к примеру 20-30 пикселей (5%-10% из всех пикселей из этой диагонали-линии).

Я об этом думал. Однако, возможно есть другое решение? Более "правильное"...

Может можно как-то быстро обработать фрагмент памяти, в котором находится битмап, а не бегать циклом по пикселям, сравнивая цвета.

Потому и задал такой вопрос - возможно кто-то знает как это сделать.

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


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

Странная потребность, если не вариант пробежать по диагонали, тогда, возможно как вариант)):

создайте массив размера Width * Height * глубину (на 4 в случае  32 bit);

Глубина в данном случае не совсем корректно, чтоб было понятно: на R+G+B+Alpha

обнулите его через, увы не силен в Delphi на ++ через ZeroMemory;

Byte *destPtr;
destPtr = (Byte*)bitmap->ScanLine[bitmap->Height - 1]

это указатель на начало dib битмапа;

ну а дальше сравните просто сравните два участка памяти через memcmp или как угодно.

Не факт что сработает, но попробовать можно. Я таким макаром сравнивал изображения, когда нужно было очень быстро.

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

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


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

1) Какие размеры у битмапа?

2) Как и кто заполняет или не заполняет Bitmap

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


Ссылка на сообщение
Поделиться на другие сайты
  • 0
12 минут назад, Равиль Зарипов (ZuBy) сказал:

1) Какие размеры у битмапа?

2) Как и кто заполняет или не заполняет Bitmap

1. Размеры: 320*240, 640*480, 640*360 и др.

2. Заполняет битмапы декодер (в потоках формируется битмап, который копируется, в итоге, в конечный битмап, который и нужно проверить). НЕ заполняться он не может, в нем всегда есть изображение. Другой вопрос, что весь битмап может быть абсолютно "пустым"-черным.

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


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

У TBitmap есть такой метод, посмотрите его

function TBitmap.EqualsBitmap(const Bitmap: TBitmap): Boolean;
var
  MyMap, BitmapMap: TBitmapData;
  I: Integer;
begin
  if IsEmpty or Bitmap.IsEmpty then
  begin
    Result := IsEmpty and Bitmap.IsEmpty;
    Exit;
  end;
  Result := (Width = Bitmap.Width) and (Height = Bitmap.Height) and (PixelFormat = Bitmap.PixelFormat);
  if Result then
  begin
    if Map(TMapAccess.Read, MyMap) then
    try
      if Bitmap.Map(TMapAccess.Read, BitmapMap) then
      try
        for I := 0 to Height - 1 do
          if not CompareMem(MyMap.GetScanline(I), BitmapMap.GetScanline(I), MyMap.BytesPerLine) then
          begin
            Result := False;
            Exit;
          end;
      finally
        Bitmap.Unmap(BitmapMap);
      end;
    finally
      Unmap(MyMap);
    end;
  end;
end;

 

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


Ссылка на сообщение
Поделиться на другие сайты
  • 0
6 минут назад, Равиль Зарипов (ZuBy) сказал:

У TBitmap есть такой метод, посмотрите его


function TBitmap.EqualsBitmap(const Bitmap: TBitmap): Boolean;
var
  MyMap, BitmapMap: TBitmapData;
  I: Integer;
begin
  if IsEmpty or Bitmap.IsEmpty then
  begin
    Result := IsEmpty and Bitmap.IsEmpty;
    Exit;
  end;
  Result := (Width = Bitmap.Width) and (Height = Bitmap.Height) and (PixelFormat = Bitmap.PixelFormat);
  if Result then
  begin
    if Map(TMapAccess.Read, MyMap) then
    try
      if Bitmap.Map(TMapAccess.Read, BitmapMap) then
      try
        for I := 0 to Height - 1 do
          if not CompareMem(MyMap.GetScanline(I), BitmapMap.GetScanline(I), MyMap.BytesPerLine) then
          begin
            Result := False;
            Exit;
          end;
      finally
        Bitmap.Unmap(BitmapMap);
      end;
    finally
      Unmap(MyMap);
    end;
  end;
end;

 

Интересно!

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

Гуд. Попробую. Спасибо!

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


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

да, именно так! на счёт скорости конечно незнаю, не пробовал/не сравнивал.

потом отпишитесь, если все получится

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


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

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

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

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

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

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

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

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

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


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

    • От slav_z
      Показать/скрыть сенсорную клавиатуру Windows.
      unit Lib.Keyboard; interface uses Winapi.Windows, Winapi.ActiveX, System.Win.ComObj, FMX.Forms, FMX.Platform.Win; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); implementation const CLSID_UIHostNoLaunch: TGUID = '{4CE576FA-83DC-4F88-951C-9D0782B4E376}'; type ITipInvocation = interface ['{37C994E7-432B-4834-A2F7-DCE1F13B834B}'] procedure Toggle(WND: HWND); safecall; end; procedure ToggleSensorKeyboard(Form: TCommonCustomForm); var TipInvocation: ITipInvocation; begin OleCheck(CoCreateInstance( CLSID_UIHostNoLaunch,nil,CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, ITipInvocation,TipInvocation)); TipInvocation.Toggle(FormToHWND(Form)); end; end. C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe - Сенсорная клавиатура Windows. В Windows 10 простой запуск уже не работает.
      Кто как делал? Очень интересны примеры кода.
       
    • От genakust
      добрый день,
      у меня есть несколько TabItems in FMX- TabControl (как на вложенной картинке) один из которых заполняется динамически:
      FindAndDeleteItemContext; frameIndex:= GetFrameIndexByText(item); {factory} FFramesFactory:= TFramesFactory.DefaultFactory; {Index-> Frame} aktFrame:= FFramesFactory.GetFrame(frameIndex); {add to layout} aktFrame.Parent:= LyContent; aktFrame.Align:= TAlignLayout.Client; LyContent.AddObject(aktFrame); {open tab} ActionToContentTabExecute(Sender); я пытаюсь найти фрейм и удалить его только из TabItem но не как Object обследующим способом:
      procedure Txxx.FindAndDeleteItemContext; var   i: Integer; begin   for i:= 0 to Pred(LyContent.ComponentCount) do   begin     if LyContent.Controls.Items[i] is TFrame then       LyContent.RemoveObject(i);   end; end но почему- то LyContent.ComponentCount всегда равен 0.
      Подскажите пожалуйста что неправильно?
      Спасибо.

    • От genakust
      Здравствуйте,
      я создал свой ListBoxItem (FMX) который выглядит следующим образом:

      затем я добавил Items динамически в ListBox и получилось следующее:

      Когда я запускаю программу на Windows 10 и выбираю мышкой Item он селектируется, а если запускаю на Андроид- таблете, то я не могу выбрать (селектировать) Item.
      Подскажите пожалуйста, какие могут быть причины длы такого поведения.
      Заранее спасибо.
       
    • От Mohamed BEN AMMAR
      hello 
      i'm using delphi fmx for building android App
      i have this code for Activating The WI-FI icon from android device:
      This could be found here .
      =========== code ==================
      uses
        Androidapi.Helpers,
        Androidapi.JNI.JavaTypes,
        Androidapi.JNI.GraphicsContentViewText,
        Androidapi.JNIBridge,
        Androidapi.JNI.WifiManager;
        procedure SetWifiEnabled (AEnable: Boolean); var   Obj: JObject;   WifiManager: JWifiManager; begin   Obj: = SharedActivityContext.getSystemService (TJContext.JavaClass.WIFI_SERVICE);   if Obj = nil then     Exit;     WifiManager: = TJWifiManager.Wrap ((Obj as ILocalObject) .GetObjectID);   WifiManager.setWifiEnabled (AEnable); end; 
       
       My question is About Activating Android location:
        Is it possible to activate the service location icon from android device
       programatically without using the Location or TLocationSensor component ....?
      however I know exactly that google has been Deactivate this API since android "4" just for security reasons .....
      but i have seen many apps in playstore can activate the service without using 
      this code here ask the user for activate the location manually .... procedure TForm1.GPSSettings; {$IFDEF ANDROID} var Intent: JIntent; {$ENDIF} begin {$IFDEF ANDROID} Intent := TJIntent.Create; Intent := TJIntent.JavaClass.init(TJSettings.JavaClass.ACTION_LOCATION_SOURCE_SETTINGS); TAndroidHelper.Activity.startActivity(Intent); {$ENDIF} end; in other versions like lolipopup can show just the Allow Permission system dialog timer ....( Asking the user for Allowing this App to Activate the service location ......) 
      I have an android device with lolipopup version and i try to execute the location EMBARCADERO sample but 
      this one can not activate the service location ICON even  my device show me the Allow permission dialog where i choose yes allow
      with never ASK....
      Finally ,  I like the WI-FI code above .....
      and i'm wondering if someone here can do this task for me (i need a unit as the WI-FI code above which can offer me
      the option to activate the Service Location ICON )
      I'm ready to paid for that task .....
       
      Sincerelly: Brave.
    • От PavelS
      Здравствуйте! Начал изучать FireMonkey  и столкнулся с тем, что TBitmap не поддерживает размер изображения больше 8132, кажется. Т.е. большие размеры рисунка он грузит, но за счёт потери качества, размер пиксела растёт, а размер рисунка по оси всё равно не превышает 8132. В то же время в простом дельфи можно грузить и работать с гораздо большими размерами, например, один из файлов имеет размер 61216 х 1486 точек. Подскажите пожалуйста, есть ли возможность работать с большими файлами в FireMоnkey и как это можно организовать? Программа создаётся для работы только в Windows.
    • От Tot999
      Добрый день! 
      Решил покопаться в своей старой спрайтовой игрушке, чтобы освежить в памяти знания и состряпать что-нибудь новое. Возникли сомнения, нормально ли сделано графическое отображение, можно ли доработать.
      Все спрайты в дизайнтайме распиханы по Timagelist-ам.  На старте приложения я загружаю битмапы из имэджлистов в свои обджектлисты, подгоняя под нужный размер. 
      MeduzasBitmpAr : array [1..numofMeduzas] of TObjectList<Tbitmap>;  
      Дальше рисую по таймеру в основном окне игры Tpaintbox.OnPaint:
               
      В принципе, даже на слабеньких телефончиках, всё вроде бодро. Но может, опытные товарищи чего подскажут, а то я 3ий день в собственном соку варюсь, ничего толкового.
    • От SIARHEI RAHOUSKI
      Создал проект там куча компонентов. Но разворачивании формы на весь экран компоненты размер не меняют:
      Прочитал про свойства align Но как только я выставлю Group box например left другим right все сбивается в кучу и поправить это не могу. 
      Как настроить align ?

    • От SIARHEI RAHOUSKI
      Как сделать форму с компонентами под все разрешения?

    • От SIARHEI RAHOUSKI
      Как сделать мозаику (drag/drop) ? Получается есть 2 прямоугольника (которые надо перетаскивать)  и есть ещё 2 прямоугольника (которые должны принимать) и ещё есть кнопка проверки. При нажатии определяет правильно ли разместили прямоугольники.
    • От Антон Емельянов
      Приложение не даёт DeviceToken...  ,  (DeviceID есть)
      FDeviceToken := FPushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken];

      Тест пример реализован по статье нашего замечательного модератора
      http://blog.rzaripov.kz/2017/02/firebase-android-ios-2.html

      Используется:
      Компиляция SDK Android 5.1
      Среда-разработки Delphi XE 10.2 

      Пожалуйста запустите проект на своей версии Delphi..
      Посмотрите будет  сгенерирован ТОКЕН или нет.. 
      в случае удачи ,  напишите какая у вас версия Дельфи..

      Исходник-проекта:  https://drive.google.com/open?id=1mCPvYYd0tXBALt-J_ymVuzChj_TtztC0
      Только APK: https://drive.google.com/open?id=1x8q4RyVylpGOMjcQYjlvFxFBSQaYs7NL 


      Помогите люди добрые 
      За помощь и консультацию отблагодарю..
       

  • Последние посетители   0 пользователей онлайн

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

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