Как соединяются части конвейера рисования на холсте Android (2D)? - PullRequest
60 голосов
/ 23 апреля 2011

Мне бы хотелось лучше понять, как компоненты конвейера рисования Canvas в Android (2D) сочетаются друг с другом.

Например, как сделать XferMode , Shader , MaskFilter и ColorFilter взаимодействуют?Справочные документы для этих классов довольно редки, и документы для Canvas и Paint действительно не добавляют никакого полезного объяснения.

Мне это также не совсем понятнокак операции рисования, которые имеют собственные цвета (например: drawBitmap, по сравнению с «векторными» примитивами, такими как drawRect), вписываются во все это - они всегда игнорируют цвет Paint и используют вместо этого свой собственный цвет?

Меня также удивил тот факт, что можно сделать что-то вроде этого:

Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);

Это стирает овал.До того, как я это заметил, моей ментальной моделью было то, что рисование на холсте (концептуально) рисует в отдельный «слой», а затем этот слой составляется с растровым изображением холста с использованием режима переноса Paint.Если бы это было так просто, то вышеприведенный код стер бы весь битовый массив (в пределах области отсечения), так как CLEAR всегда устанавливает цвет (и альфа) в 0 независимо от альфа-канала источника.Таким образом, это подразумевает, что существует дополнительная разновидность маскирования, чтобы ограничить стирание овалом.

Я нашел API-демо , но каждая демонстрация работает "в вакууме" и не 'Я не могу показать, как объект, на котором он фокусируется (например, XferModes), взаимодействует с другими вещами (например, ColorFilters).

При достаточном времени и усилиях я мог бы эмпирически выяснить, как эти части связаны или идут расшифровывать источник, ноЯ надеюсь, что кто-то еще уже разработал это, или еще лучше, что есть некоторая фактическая документация модели конвейера / чертежа, которую я пропустил.

Этот вопрос был вдохновлен увидением кода в этот ответ на другой вопрос SO .

Обновление

Когда я искал какую-то документацию, мне пришло в голову, что, поскольку многие вещи, которые меня интересуют, кажутся довольно тонкимифанера поверх skia , возможно, есть какая-то документация skia, которая будет полезна.Лучшее, что я могу найти, это документация для SkPaint, в которой говорится:

Существует 6 типов эффектов, которые можно назначить краске:

  • SkPathEffect - изменение геометрии (пути) до создания альфа-маски (например, штриховка)
  • SkRasterizer - создание пользовательских слоев маски (например, теней)
  • SkMaskFilter - изменения вальфа-маска до ее раскрашивания и рисования (например, размытие, тиснение)
  • SkShader - например, градиенты (линейный, радиальный, развертка), растровые рисунки (зажим, повтор, зеркало)
  • SkColorFilter - изменитьисходный цвет (цвета) перед применением xfermode (например, цветовой матрицы)
  • SkXfermode - например, режимы переноса портера, режимы наложения

Не указано явно,но я предполагаю, что порядок эффектов здесь - это порядок их появления в конвейере.

Ответы [ 3 ]

48 голосов
/ 10 мая 2011

Как сказал Ромен Гай: «На StackOverflow трудно ответить на этот вопрос». На самом деле не было какой-либо полной документации, и полную документацию можно было бы добавить сюда.

В итоге я прочитал источник и провел кучу экспериментов. По пути я делал заметки и в итоге превратил их в документ, который вы можете увидеть здесь:

а также эта диаграмма:

enter image description here

Это "неофициально", очевидно, поэтому применяются обычные предостережения.

Исходя из вышеизложенного, здесь приведены ответы на некоторые «подвопросы»:

Мне также не совсем понятно, как операции рисования, которые свойственны цвета (например: drawBitmap, по сравнению с "векторные" примитивы типа drawRect) вписаться во все это - всегда ли они игнорировать цвет Paint и использовать его их собственный цвет вместо?

«Исходные цвета» происходят от Shader. В drawBitmap Shader временно заменяется на BitmapShader, если используется не ALPHA_8 Bitmap. В других случаях, если не указан Shader, Shader, который просто генерирует сплошной цвет, используется цвет Paint.

Меня также удивил тот факт, что можно сделать что-то вроде этого:

Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);

Это стирает овал. Прежде чем я заметил это моя ментальная модель, что рисунок на холсте (концептуально) рисует на отдельный «слой», а затем этот слой состоит из растрового изображения холста используя режим передачи краски. Если оно было так просто, как то выше код будет стереть весь растровое изображение (в пределах области отсечения) как CLEAR всегда устанавливает цвет (и альфа) на 0 независимо от альфа-канала источника. Так это подразумевает, что есть дополнительный вид маскировки происходит стереть стирание до овала.

XferMode применяется к "исходным цветам" (от Shader) и к "цветам назначения" (от Canvas * Bitmap). Затем результат смешивается с пунктом назначения, используя маску, вычисленную в растеризации. Для получения дополнительной информации см. Фазу передачи в приведенном выше документе.

11 голосов
/ 01 мая 2011

На этот вопрос сложно ответить на StackOverflow. Однако прежде чем начать, обратите внимание, что фигуры (например, drawRect ()) НЕ имеют внутреннего цвета. Информация о цвете всегда поступает из объекта Paint.

Это стирает овал. Прежде чем я заметил это моя ментальная модель, что рисунок на холсте (концептуально) рисует на отдельный «слой», а затем этот слой состоит из растрового изображения холста используя режим передачи краски. Если оно было так просто, как то выше код будет стереть весь растровое изображение (в пределах области отсечения) как CLEAR всегда устанавливает цвет (и альфа) на 0 независимо от альфы источника. Так это подразумевает, что есть дополнительный вид маскировки происходит ограничить стирание до овала.

Ваша модель немного не в порядке. Овал не рисуется в отдельном слое (если только вы не вызываете Canvas.saveLayer ()), он рисуется непосредственно на фоновое растровое изображение Canvas. Режим переноса Paint применяется к каждому пикселю, нарисованному примитивом. В этом случае только результат растеризации овала влияет на растровое изображение. Особой маскировки не происходит, сам овал - это маска.

Во всяком случае, вот упрощенный вид конвейера:

  1. Примитив (прямоугольник, овал, путь и т. Д.)
  2. PathEffect
  3. растеризации
  4. MaskFilter
  5. Цвет / Shader / ColorFilter
  6. Xfermode

(Я только что видел ваше обновление и да, то, что вы нашли, описывает этапы конвейера по порядку.)

Конвейер становится немного более сложным при использовании слоев (Canvas.saveLayer ()), так как конвейер удваивается. Сначала вы проходите через конвейер, чтобы визуализировать ваши примитивы в закадровом растровом изображении (слое), а затем закадровое растровое изображение применяется к Canvas, проходя через конвейер.

0 голосов
/ 13 июля 2017

SkPathEffect - изменение геометрии (траектории) до того, как она сгенерирует альфа-маску (например, штрихование). SkRasterizer - создание пользовательских слоев маски (например, теней). SkMaskFilter - изменение альфа-маски до того, как она будет раскрашена и нарисована (например, размытие). SkShader- например, градиенты (линейные, радиальные, развертки), шаблоны растровых изображений (зажим, повтор, зеркало). SkColorFilter - изменить исходный цвет (цвета) перед применением xfermode (например, цветовой матрицы) SkXfermode - например, режимы переноса портье, режимы наложения

http://imgur.com/0X5Yqod

...