Создание обтравочной маски с использованием Graphics32 - PullRequest
2 голосов
/ 23 января 2012

Я использую Graphics32 для обработки изображений.Глядя на его возможности, мне кажется, что мне еще предстоит увидеть правильную реализацию обтравочной маски.Я вижу, что термин «отсечение» всплывает здесь и там, но, похоже, он относится к чему-то другому.

Проще говоря, мне нужен один слой, чтобы он функционировал как «заглядывающая дыра» в другом;слой A должен проецироваться на слой B, но только там, где слой B виден.(Я больше не вижу необходимости переопределять, что такое обтравочная маска.)

Если бы это было просто растровое изображение этого другого слоя, которое я хотел бы представить, это было бы не так сложно сделать - тогдаЯ мог бы использовать этот трюк - но что усложняет ситуацию, так это то, что растровое изображение слоя мало что говорит о том, что будет отображаться слоем;слой может быть:

  • (частично) невидимым (когда он не виден)
  • перемещено / растянуто + дополнительно изменено значение
  • повернуто

без влияния на его растровое изображение.

Неужели для этого нет готовой реализации?Любые предложения сделать это самостоятельно?

Прогресс

Я нашел несколько полезных элементов в источнике Graphics32.Например, используя это объявление:

type
  TLayerAccess = class(TBitmapLayer);

, чтобы получить доступ к защищенным методам, я могу вызвать TLayerAccess(ABitmapLayer).Paint(ABitmap32), чтобы нарисовать только этот слой в растровом изображении, точно так же, как на экране.

Ответы [ 2 ]

0 голосов
/ 12 марта 2013

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

Вы хотите соединить один TBitmapLayer с другим и считать его маской. Однако я хочу избежать этих ссылок (и их потенциальных проблем, а также доработки Graphics32) и рассматривать это только как последнее средство.

Есть способ обойтись без выделенного TBitmapLayer, используя свой собственный пиксельный сумматор. Но он не знает о TBitmapLayers и его пикселях XY.

Чтобы правильно перекрыть (или пропустить) части TBitmapLayer во время рисования на экране, вы можете использовать метод создания типа TPixelCombineEvent, назначив его как OnPixelCombine и установив TBitmapLayer.DrawMode до dmCustom.

Внутри этого TPixelCombineEvent метода вы решаете, какие пиксели получаются при заданном фоне B и переднем плане F при текущем M мастер-альфа.

procedure TMyObj.MyPixCombine(F: TColor32; var B: TColor32; M: TColor32);
begin
  if not PseudoThisPixelShouldBeMasked then B := F; // ugly and aliased
end;

Проблема здесь в том, что (псевдокод) PseudoThisPixelShouldBeMasked действительно не знает, к какому пикселю это относится и находится ли он внутри маски. Таким образом, вам придется извлечь это значение из компонента F, например его альфа-значения.

Тогда я выбрал довольно быстрый B := ColorMin(F,B);, где F черный или белый. Этот слой всегда сверху и, тем не менее, получается прозрачным, а не черным. Это потому, что любой рендеринг на TBitmapLayer разрушил бы данные маски, и мне нужно повторно применить их. Однако использование TByteMap, как предложено ниже (кто это отрицал?) От iamjoosy, может быть интересным, возможно, снижение производительности окажется незначительным.

0 голосов
/ 23 января 2012

Посмотрите на TByteMap и его метод writeTo.

...