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

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


AngryOwl

Вопрос

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

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

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

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

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

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