Ниже приведена функция, которая создаёт HRGN из чёрно-белого битмапа. Все чёрные пиксели становятся регионом, а белые становятся прозрачными. Так же не составит труда сделать преобразования для поддержки всех цветов и чтобы один из них был прозрачным.
По окончании необходимо освободить регион при помощи функции DeleteObject.
function BitmapToRgn(Image: TBitmap): HRGN;
var
TmpRgn: HRGN;
x, y: integer;
ConsecutivePixels: integer;
CurrentPixel: TColor;
CreatedRgns: integer;
CurrentColor: TColor;
begin
CreatedRgns := 0;
Result := CreateRectRgn(0, 0, Image.Width, Image.Height);
inc(CreatedRgns);
if (Image.Width = 0) or (Image.Height = 0) then
exit;
for y := 0 to Image.Height - 1 dobegin
CurrentColor := Image.Canvas.Pixels[0,y];
ConsecutivePixels := 1;
for x := 0 to Image.Width - 1 dobegin
CurrentPixel := Image.Canvas.Pixels[x,y];
if CurrentColor = CurrentPixel then
inc(ConsecutivePixels)
elsebegin// Входим в новую зонуif CurrentColor = clWhite thenbegin
TmpRgn := CreateRectRgn(x-ConsecutivePixels, y, x, y+1);
CombineRgn(Result, Result, TmpRgn, RGN_DIFF);
inc(CreatedRgns);
DeleteObject(TmpRgn);
end;
CurrentColor := CurrentPixel;
ConsecutivePixels := 1;
end;
end;
if (CurrentColor = clWhite) and (ConsecutivePixels > 0) thenbegin
TmpRgn := CreateRectRgn(x-ConsecutivePixels, y, x, y+1);
CombineRgn(Result, Result, TmpRgn, RGN_DIFF);
inc(CreatedRgns);
DeleteObject(TmpRgn);
end;
end;
end;
Переведенный текст:
Функция BitmapToRgn принимает объект TBitmap в качестве входного параметра и возвращает регион HRGN, созданный на основе пиксельных значений битмапа. Функция перебирает каждый пиксел в битмапе и проверяет, является ли он черным или белым.
Сюда включается разбор того, что код делает:
Он инициализирует некоторые переменные: CreatedRgns, Result, TmpRgn, x, y, ConsecutivePixels и CurrentPixel.
Создает начальный регион (Result) с теми же размерами, что и входной битмап.
Функция затем перебирает каждый пиксел в битмапе, начиная от верхнего левого угла.
Для каждого пиксела она проверяет, является ли текущий цвет тем же, что и предыдущий (ConsecutivePixels увеличивается). Если нет, то это означает, что новый регион был найден.
Если текущий цвет белый и есть последовательность пикселей с тем же цветом (ConsecutivePixels > 0), она создает прямоугольник для этого региона с помощью CreateRectRgn и комбинирует его с существующим регионом (Result) с помощью CombineRgn. Затем она удаляет временный регион (TmpRgn) для освобождения памяти.
Функция также включает в себя некоторые обработчики ошибок: если входной битмап имеет ширину или высоту равную нулю, функция просто выходит без создания региона.
Чтобы поддерживать все цвета и сделать один цвет прозрачным, вам нужно модифицировать код для перебора каждого пикселя RGB-значений (или ARGB в случае alpha-каналов), а не только для черного или белого. Вы можете использовать схожий подход, но с более сложной логикой для обработки различных комбинаций цветов.
В отношении последнего шага DeleteObject(TmpRgn), он действительно необходим для освобождения памяти, выделенной CreateRectRgn. Функция DeleteObject делает именно это.
Альтернативная функция создает регион, перебирая каждый пиксел в битмапе и комбинируя прямоугольники для прозрачных пикселей с помощью CombineRgn с флагом RGN_OR. Обратите внимание, что этот подход отличается от оригинального кода, так как он не зависит от последовательности пикселей для создания регионов.
Функция BitmapToRgn преобразует чёрно-белый битмап в регион (HRGN), где все чёрные пиксели образуют регионы, а белые - прозрачные.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.