Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
32.Инвертированные файлы
Инвертированный файл представляет собой структуру, которая состоит из двух частей:
словарь, содержащий все термы, встретившиеся в коллекции и ссылку на массив данных «пост-листа» для каждого из них. Помимо того возможно наличие специальных структур, ускоряющих поиск слова в словаре.
пост-листы, представляющие собой массив информации обо всех вхождениях данного слова в документы коллекции.
При реализации инвертированного файла можно организовать его как отдельную структуру или на основе В+ дерева, используя наработанные механизмы работы с ними.
При организации эффективного хранения индекса и оптимизации работы с ним требуется использовать алгоритмы сжатия информации. Наибольший объем имеют пост-листы, представляющие, в простейшем случае, массив идентификаторов содержащих их документов. Также, в различных реализациях, в них может храниться вес этого документа относительно данного слова, указания на коллекцию, к которой относится документ и другие данные.
В случае, если в пост-листе хранятся идентификаторы в возрастающем порядке, компактнее будет хранить их разность, чем идентификаторы целиком. Сами же числа сохраняют с применением техник кодирования чисел:
кодов переменной длины. Например, первые семь байтов каждого бита передают значимую часть числа, последний байт обозначает оканчивается ли на этом число или нет.
гамма и дельта кодирование Элиса и параметрические коды Голомба.
В случаях, когда требуется эффективное сжатие коротких пост-листов, имеет смысл объединять списки для нескольких слов. В этом случае получается список идентификаторов, который может быть эффективно кодирован одним из способов компактного хранения чисел. У каждого идентификатора указывается слово или список слов из объединенного списка, которые в нем встречаются. Можно указывать их номера, сжатые методом Хаффмана.
В случае реализации индекса на основе В+ деревьев на размер пост-листа накладывается ограничение реализации. Для того, чтобы разместить длинные пост-листы в индексе применяются два метода:
1. разбиение пост-листа. Один пост-лист размещается в нескольких записях. В этом случае ключем дерева является не только слово, но и первое значение в пост-листе.
2. вынесение длинных пост-листов во внешнюю, по отношению к дереву, структуру.
Потери связанные с повторением в ключе записи слов можно компенсировать префиксным сжатием всей страницы индекса. При получении пост-листа, разбитого на части, можно декодировать только нужную его часть, что позволяет более эффективно расходовать память.
При совершении поиска по поисковому запросу, работа с индексной информацией состоит из этапов поиска каждого слова запроса в словаре, получении для каждого пост-листа (пост-листов), раскодировании их, полном или дополнительном взвешивании документа по данному списку слов запроса, формировании результатов для пользователя.
Изменения индексной информации делятся на массовые, при которых изменяется большое число документов и имеет смысл полное перестроение индекс, и одиночные, при которых полного перестроения не происходит. Полное перестроение используется при начальной инициализации индекса. При этом в выделенной области оперативной памяти собирается индекс по части документов, при заполнении сохраняется во временных файлах, а потом многопоточным слиянием объединяется в единую индексную структуру.
В случае реализации индекса через В+ деревья эффективно происходит добавление и удаление информации, разбиение длинных пост-листов позволяет эффективно обновлять только нужные их части, не считывая остальные.
33. Ассоциативные структуры данных на основе B+-дерева для работы с ВЗУ.
Схема организации классических B-деревьев проста и элегантна, но не очень хороша для практического использования. Прежде всего это связано с тем, что в большинстве практических применений необходимо хранить во внешней памяти не только ключи, но и записи. Поскольку в B-дереве элементы располагаются и во внутренних, и в листовых страницах, а размер записи может быть достаточно большим, внутренние страницы не могут содержать слишком много элементов, по причине дерево может быть довольно глубоким. Поэтому для доступа к ключам и записям, находящимся на нижних уровнях дерева, может потребоваться много обменов с внешней памятью. Во-вторых, на практике часто встречается потребность хранения и поиска ключей и записей переменного размера. Поэтому тот критерий, что в каждой странице B-дерева содержится не меньше n и не больше 2*n ключей, становится неприменимым.
Широкое практическое применение получила модификация механизма B-деревьев, которую принято называть B+-деревьями. Эти деревья похожи на обычные B-деревья. Они тоже сильно ветвистые, и длина пути от корня к любой листовой странице одна и та же. Но структура внутренних и листовых страниц различна. Внутренние страницы устроены так же, как у B-дерева, но в них хранятся только ключи (без записей) и ссылки на страницы-потомки. В листовых страницах хранятся все ключи, содержащиеся в дереве, вместе с записями, причем этот список упорядочен по возрастанию значения ключа (рисунок 5.6).
Поиск ключа всегда доходит до листовой страницы. Аналогично операции включения и исключения тоже начинаются с листовой страницы. Для применения переливания, расщепления и слияния используются критерии, основанные на уровне заполненности соответствующей страницы. Для более экономного и сбалансированного использования внешней памяти при реализации B+-деревьев иногда используют технику слияния трех соседних страниц в две и расщепления двух соседних страниц в три. Хотя B+-деревья хранят избыточную информацию (один ключ может храниться в двух страницах), они, очевидно, обладают меньшей глубиной, чем классические B-деревья, а для поиска любого ключа требуется одно и то же число обменов с внешней памятью.
(a) Структура внутренней страницы B+-дерева
(b) Структура листовой страницы B+-дерева
Рис. 5.6. Структуры страниц B+-дерева
Дополнительной полезной оптимизацией B+-деревьев является связывание листовых страниц в одно- или двунаправленный список. Это позволяет просматривать списки записей для заданного диапазона значений ключей с лишь одним прохождением дерева от корня к листу.
Разновидности B+-деревьев для организации индексов в базах данных
B+-деревья наиболее интенсивно используются для организации индексов в базах данных. В основном это определяется двумя свойствами этих деревьев: предсказуемостью числа обменов с внешней памятью для поиска любого ключа и тем, что это число обменов по причине сильной ветвистости деревьев не слишком велико при индексировании даже очень больших таблиц.
При использовании B+-деревьев для организации индексов каждая запись содержит упорядоченный список идентификаторов строк таблицы, включающих соответствующее значение ключа. Дополнительную сложность вызывает возможность организации индексов по нескольким столбцам таблицы (так называемых "составных" индексов). В этом случае в B+-дереве может появиться очень много избыточной информации по причине наличия в разных составных ключах общих подключей. Имеется ряд технических приемов сжатия индексов с составными ключами, улучшающих использование внешней памяти, но, естественно, замедляющих выполнение операций включения и исключения.
34. Обобщение B+-дерева для случая работы с геометрическими данными (R-дерево).
Коротко рассмотрим еще одно расширение механизма B-деревьев, используемое главным образом для организации индексов в пространственных базах данных, - R-деревья. Подобно B+-деревьям, R-дерево представляет собой ветвистую сбалансированную древовидную структуру с разной организацией внутренних и листовых страниц.
Но информация, хранящаяся в R-дереве несколько отличается от той, которая содержится в B-деревьях. В дополнение к находящимся в листовых страницах идентификаторам пространственных объектов, в R-деревьях хранится информация о границах индексируемого объекта. В случае двумерного пространства сохраняются горизонтальные и вертикальные координаты нижнего левого и верхнего правого углов наименьшего прямоугольника, содержащего индексируемый объект. Пример простого R-дерева, содержащего информацию о шести пространственных объектах, приведен на рисунке 5.7.

Рис. 5.7. Простое R-дерево для представления шести пространственных объектов
35. Анализ методов обеспечения транзакционности, сбоеустойчивости и параллельности обработки данных при работе с ВЗУ.
36. Двухверсионное B+-дерево
37. Устройства вывода информации. Видеокарты. Общие принципы формирования изображений. Ускорители.
Видеока́рта (известна также как графи́ческая пла́та, графи́ческая ка́рта, видеоада́птер) (англ. videocard) — устройство, преобразующее изображение, находящееся в памяти компьютера, в видеосигнал для монитора.
Обычно видеокарта является платой расширения и вставляется в разъём расширения, универсальный (PCI-Express, PCI, ISA, VLB, EISA, MCA) или специализированный (AGP), но бывает и встроенной (интегрированной) в системную плату (как в виде отдельного чипа, так и в качестве составляющей части северного моста чипсета или ЦПУ).
Современные видеокарты не ограничиваются простым выводом изображения, они имеют встроенный графический микропроцессор, который может производить дополнительную обработку, разгружая от этих задач центральный процессор компьютера. Например, все современные видеокарты Nvidia и AMD (ATi) поддерживают приложения OpenGL на аппаратном уровне. В последнее время также имеет место тенденция использовать вычислительные способности графического процессора для решения неграфических задач (см. OpenCL).
Изображение передают сигналы, имеющие аналоговую, непрерывную форму. Поэтому они преобразуются в дискретную форму путем дискретизации, т. е. разбиения непрерывного графического изображения на отдельные элементы.
В процессе дискретизации производится кодирование, т. е. присвоение каждому элементу конкретного значения в форме двоичного кода.
Создавать и хранить графические объекты в компьютере можно двумя способами - как растровое и векторное изображение. Для каждого типа изображения используется свой способ кодирования.
Растровое изображение состоит из отдельных точек (пикселей - от англ. pixel - элемент изображения). На изображение накладывается прямоугольная сетка - растр, которая позволяет разбить рисунок на конечное количество элементов - пикселей.
Каждая такая точка изображения имеет свой цвет, который кодируется двоичным кодом.
Векторное изображение представляет собой графический объект, состоящий из элементарных отрезков и дуг. Положение этих элементарных объектов определяется координатами точек и длиной радиуса. Для каждой линии указывается ее тип (сплошная, пунктирная, штрих - пунктирная), толщина и цвет.
Информация о векторном изображении кодируется также двоичным кодом и обрабатывается специальными программами.
В видеопамяти любое изображение представляется в растровом виде. Экран монитора разбит на фиксированное число пикселей.
Разрешающая способность экрана монитора - размер растра, задаваемого в виде произведения MxN, где М - количество точек по горизонтали, N - количество точек по вертикали (число строк).
Количество цветов, воспроизводимых на экране монитора (K), и число бит, отводимых в видеопамяти под каждый пиксель (b) (битовая глубина), связаны формулой:
К=2b .
Объем видеопамяти, необходимой для хранения одной страницы изображения:
V=b•M•N.
Начнём традиционно с истории. Первые видеокарты не были даже не 3D-ускорителями, а не были ускорителями вообще. Они служили лишь как ЦАП (цифро-аналоговый преобразователь) – преобразовывали данные, рассчитанные центральным процессором (представляющий собой цифровой код) в аналоговый сигнал, доступный для отображения на мониторе. Но сложность изображений росла, и дальше так продолжаться не могло. Тенденция усложнения изображений привела к появлению 2D- ускорителя – видеокарты, имеющий свой собственный, пусть и простейший процессор, бравший на себя часть функций, разгружая центральный процессор. Но когда появилась необходимость строить 3D изображения – ситуация осложнилась.
Чтобы построить, скажем, простой фрагмент стены, процессору нужно было выполнить следующие операции: сначала необходимо выделить грани этого объекта, затем наложить текстуры, добавить освещение... а когда таких объектов сотни, их форма сложна, они движутся и перекрываются, отбрасывают тени и т. д. задача становится невероятно сложной. Для помощи процессору в решении этой задачи и были созданы ускорители трёхмерной графики, о работе которых и пойдёт речь в этой статье.
Для начала выясним – а что нам, собственно, нужно, чтобы построить трёхмерное изображение. Необходимо сказать, что видеоакселератор НЕ занимается расчётом того, какую сцену он должен сейчас строить. Определением 3D сцены – объектов, точки наблюдения и т. п. занимается центральный процессор. Как только все необходимые данные собраны – они передаются видеокарте, которая начинает построение сцены.
Построение сцены происходит следующим образом:
Загрузка в чип ускорителя вершин из памяти акселератора, со своими атрибутами.
Далее, каждая из вершин попадает в вершинный процессор. Подробнее мы вернемся к нему чуть позже.
Далее происходит установка треугольников - трансформированные и освещенные (т. е. уже обработанные вершинным шейдером или фиксированным T&L блоком) вершины объединяются по три, и происходит подготовка данных для закраски треугольника. Здесь же происходит отсечение невидимых – перекрытых (overdraw) поверхностей.
Далее, треугольник разбивается на фрагменты, часть которых признаются невидимыми и отбрасывается в ходе Z-теста на уровне фрагментов (то, что мы называем Hidden Surface Removal, HSR). Как правило, конечным результатом этого процесса являются видимые (или частично видимые) фрагменты 2х2 пикселя – так называемые «квады», подлежащие закраске. Именно такие фрагменты наиболее удобны для быстрой закраски пикселей.
Далее квады отправляются на установку фрагментов. Здесь для каждого из них вычисляется (интерполируется) множество необходимых параметров, таких как текстурные координаты, MIP уровень, векторы, установочные параметры анизотропии и т. д.
После установки и интерполяции параметров происходит закраска фрагментов. Существенной частью этого процесса является выборка и фильтрация текстур.
После того как значения цвета были рассчитаны, в пиксельном процессоре происходит смешение (блендинг) - если включен соответствующий режим - или просто запись результирующих значений цвета и глубины в буфер кадра. На этом этапе может происходить несколько дополнительных операций.
Ну а из буфера кадра происходит вывод изображения на экран, иногда после дополнительных проходов для АА.
Отметим, что всё это непрерывная очередь.
Всем желающим подробнее узнать про алгоритм построения сцены современными ускорителями я рекомендую изучить великолепный материал под названием DirectX Current, подготовленный нашими коллегами с iXBT.
Итак, каждая стадия построения изображения очень ресурсоемка, требует множества расчётов. Вполне логичным выглядит шаг вынесения их из CPU и переправка на специализированный процессор видеокарты. Особенно если учитывать, что графические данные имеют потоковый характер, и вычислительную потребность значительно большую, чем логическую.
Каждый новый виток развития ускорителей представляет собой некое поколение, поэтому для начала введём стандартизацию поколений (понимать поколения можно по-разному – я приведу лишь один вариант):
Первое поколение, которое было более-менее распространено – это акселераторы, использующие API Direct3D 5 и Glide. Представителем первых была NVIDIA Riva128, а вторых – 3Dfx Voodoo. Карты этого поколения брали на себя только последнюю часть построения сцены – текстурирование и закраску. Все предыдущие этапы выполнял CPU.
Второе поколение использовало API Direct3D 6, также в это время началось стремительное возрождение API, разработанного SGI – OpenGL. Представителями карт того времени были NVIDIA RivaTNT и ATI Rage. Это было практически эволюционное развитие карт предыдущего поколения.
Третье поколение – Direct3D 7. Именно тогда появились карты, снабженные TCL-блоком, снимавшим с CPU значительную часть нагрузки. Этот блок отвечал за трансформацию, освещение и отсечение. (TCL - Transformaton-Clipping-Lighting) Теперь видеокарта строила сцену самостоятельно – от начала до конца. Представителями этого поколения стали NVIDIA GeForce256 и ATI Radeon.
Четвёртое поколении – очередная революция. Кроме прочих новых возможностей API Direct3D 8 (и 8.1) эти карты принесли с собой самую главную возможность – аппаратные шейдеры. Причину их появления мы опишем чуть позже. Представляют это поколение NVIDIA GeForce 3,4 и ATI Radeon 8500, 9000, 9100, 9200.
Пятое поколение – это, в основном, развитие шейдерных технологий (версия 2.0), и попытка ввести АА и АФ в ряд обязательных к использованию функций. Это поколение, поддерживает API Direct3D версии до 9.0b включительно, представляют ATI RADEON 9500, 9600, 9700, 9800, Х800, а также NVIDIA GeForce FX 5200, 5500, 5600, 5700, 5800, 5900, 5950.
Шестое поколение – это поколение DirectX9.0c. Оно пока включает в себя только одну серию NVIDIA GeForce 6 и платы GeForce 6800Ultra/6800GT/6800 на базе чипа NV40. Эти карты поддерживают шейдеры версии 3.0, и предлагают некоторые другие возможности.
Теперь, определившись с общим устройством конвейера и поколениями видеокарт, мы более подробно рассмотрим вершинный и фрагментный процессоры, а также определимся в отличиях версий соответствующих шейдеров.
Причиной появления шейдеров стало отсутствие какой-либо гибкости у фиксированного TCL блока. Быстро стало понятно, что ждать момента, когда производители внесут очередную порцию функций в TCL блок видеокарт – не лучший выход. Такой подход не устраивал никого. Разработчикам не нравилась мысль, что для того, чтобы внести в, например, игру новый эффект им надо годик подождать выхода нового ускорителя. Производителям тоже не светило ничего хорошего – им бы пришлось постоянно увеличивать как сами чипы, так и драйверы к ним. Это и стало причиной появления шейдеров – программ, способных настраивать ускоритель так, как того требует следующая сцена.
Шейдер – это программа, которая загружается в ускоритель, и конфигурирует его узлы для обработки соответствующих элементов. Теперь нет ограничения заранее заданным набором способов обработки эффектов. Теперь стало возможно составлять из стандартных инструкций любые программы (ограниченные спецификациями используемой версией шейдера), задающие необходимые эффекты.
Шейдеры делятся по своим функциям на вершинные и фрагментные (пиксельные): первые работают с вершинами и треугольниками, заменяя собой функциональность TCL блока (сейчас он практически исчез – в случае необходимости он эмулируется специальным вершинным шейдером). Фрагментные же шейдеры служат для создания программ обработки фрагментов размеров 2х2 пикселя – квадов. Они необходимы для реализации некоторых текстурных эффектов.
Шейдеры также характеризуются номером версии - каждая последующая добавляет к предыдущим всё новые и новые возможности. Наиболее свежей спецификацией фрагментных и вершинных шейдеров на сегодняшний день является версия 3.0, поддерживаемая через API DirectX 9с, - на нее и будут ориентироваться как производители акселераторов, так и разработчики новых игр. На их поддержку аппаратурой стоит обращать внимание и пользователям, желающим приобрести современную игровую видеокарту.
Обратим внимание на главное отличие шейдеров 3.0 от предыдущих версий (кроме 2.0а) – это DFC – Dynamic Flow Control – динамическое управление потоком. С одной стороны – это великолепная возможность, позволяющая заметно повысить скорость построения сцены, с другой – лишние транзисторы, и как вытекающие побочные эффекты, лишнее тепло и ниже максимальные частоты. Давайте более подробно опишем эту возможность.
Представим себе ситуацию, когда для какой-либо вершины (или фрагмента) шейдер нужно выполнить не весь, а только 12% от него. В случае применения DFC мы выполним лишь те необходимые 12%, основываясь на параметрах объекта. Без DFC мы вынуждены выполнить шейдер целиком. Легко заметить, что с DFC мы получим выигрыш без малого в 10 раз, при этом, заплатив пониженной производительностью на вершинах, для которых нужно выполнить все 100% шейдера. Именно по этому в сети до сих пор не утихают споры – хорошо это или нет. Я не буду проводить сравнения – тут каждый сам делает выбор, а лишь отмечу, что я лично сторонник третьей шейдерной модели.
Первые шейдеры состояли всего из нескольких команд, и их нетрудно было написать на низкоуровневом языке ассемблера. Хотя сложность отладки ассемблерного кода поначалу отпугнула от шейдеров многих разработчиков… Но с ростом сложности шейдерных эффектов, насчитывающих иногда десятки и сотни команд, возникла необходимость в более удобном, высокоуровневом языке написания шейдеров. Их появилось сразу два: NVIDIA Cg (C for graphics) и Microsoft HLSL (High Level Shading Language) - последний является частью стандарта DirectX 9. Достоинства и недостатки этих языков, и прочие нюансы будут интересны только программистам, так что подробнее на них мы останавливаться не станем. Отметим только, что Cg не получил широкого распространения, ввиду появления нового, более продвинутого GLSL – аналога HLSL для API OpenGL.
Не будем проводить сравнения этих языков, а лишь отметим, что, как и в любой другой области, применение языков высокого уровня значительно сокращает объём необходимых работ по написанию и отладке кода.
Теперь давайте посмотрим, что необходимо для того, чтобы получить все те возможности, которые дает столь полезная технология, как шейдеры последнего поколения. А нужно следующее:
Самая свежая версия DirectX, на данный момент это DirectX 9.0с;
Видеокарта с поддержкой DirectX 9с;
Самые свежие драйверы видеокарты (в более старых некоторые функции могут отсутствовать);
Игра, использующая все эти возможности.
Особенно хочется отметить последнее обстоятельство – обычно на внедрение новых технологий уходит 2 - 3 года, но благодаря высокоуровневым языкам создания шейдеров это время заметно сократилось.
38. Принципы формирования динамических спрайтовых изображений.
Спрайт (sprite) — небольшое изображение, свободно перемещающееся по монитору. В первоначальном смысле слова этот термин применялся только для аппаратно выводимых изображений. Собственно, лишь один настоящий спрайт можно встретить на IBM PC — аппаратный курсор мыши. При архитектуре х86 под спрайтом принято понимать программно выводимое изображение, которое может иметь сложную форму и передвигаться поверх фона, не затирая его.
Перед тем как выводить спрайт, надо сохранить находящееся под ним изображение, чтобы фон не испортился, когда спрайт «уйдет». Поэтому считаем информацию с того места экрана, куда будет помещен спрайт. Непосредственно перед выводом спрайта восстановим изображение, а затем снова сохраним фон из нового места, куда будет помещен спрайт.
Реальные спрайты редко имеют прямоугольную форму, поэтому выводить следует только отдельные точки считанного изображения, включив для этого понятие «прозрачный цвет». В данном случае мы выбираем белый цвет с кодом 255 ($FF). При выводе спрайта рисуются лишь те точки, код которых не равен 255 (для «прозрачного цвета» можно взять любое значение: 0, 5, 31 — как вам будет удобно).
Чтобы скорость работы программы не зависела от производительности компьютера, применим синхронизацию с обратным ходом кадровой развертки. Она также избавит и от мерцания. В более сложных программах эти две функции реализуются с помощью различных механизмов независимо друг от друга.
Текст созданной нами программы см. в листинге
. Чтобы описать спрайт, определяем запись SpriteType. Для прямого доступа к видеопамяти используем массив Mem, а для вызова функции VideoBIOS — процедуру intr. Итак, что же получилось?
Цвета вышли не такие, какие нам хотелось бы. Что делать? По умолчанию в среде DOS и в Windows установлены различные палитры. Чтобы цвета были такими, какими нужно, следует прочитать заголовок BMP-файла, взять из него данные по цветам и записать их в регистры палитры.
Изображение спрайта получилось перевернутым. Так уж устроено, что на экране ось Y идет сверху вниз, а в BMP-файле — снизу вверх. Думаю, исправить это не составит большого труда.
Если сделать спрайт большего размера, то возникает мелькание в верхней части экрана. Чтение данных из видеопамяти происходит долго, поэтому этого лучше просто избегать. (Подробнее обо всем см. в следующих номерах журнала.)
Кстати, попробуйте отключить (закомментировать) ожидание обратного хода и посмотрите, что из этого получится.
На приведенном здесь примере показано, как перемещать спрайт по экрану. Кроме того, чередуя несколько фаз (кадров) изображения, можно заставить спрайт «махать руками», «топать ногами» и т. п., даже находясь в одном месте экрана. Для этого нужно либо сопоставить файл каждому кадру, либо поместить все кадры в один файл (последнее предпочтительнее, но требует большей работы), а затем по очереди выводить изображение спрайта из того или иного кадра на экран (в буфер).
39. Альфа-канал. Полупрозрачное наложение спрайтовых изображений.
В компьютерной графике альфа-композиция обозначает процесс комбинирования изображения с фоном с целью создания эффекта частичной прозрачности. Этот метод часто применяется для многопроходной обработки изображения по частям с последующей комбинацией этих частей в единое двумерное результирующее изображение.
Альфа-канал, также известный как маска-канал, это просто способ объединить переходную прозрачность с изображением. Формат GIF поддерживает простую бинарную прозрачность (когда любой пиксель может быть либо полностью прозрачным, либо абсолютно непрозрачным), PNG позволяет 254 уровня частичной прозрачности между нормальным изображением (или 65534 уровня прозрачности для специальных «очень безумных»).
Все три типа PNG изображений («TrueColor», «GrayScale» и индексированная палитра) могут содержать альфа-информацию, хотя обычно она применяется лишь с «TrueColor» изображениями. Вместо того, чтобы сохранять три байта для каждого пикселя (красный, зелёный и синий, RGB), сохраняются четыре: красный, зелёный, синий и альфа, таким образом получается RGBA.
Вся эта переходная прозрачность позволяет создавать замечательные «спецэффекты», хорошо выглядящие на любом фоне. Например, эффекта фотовиньетки, для портрета, можно добиться путём установки полностью непрозрачной центральной области (то есть для лица и плеч), прозрачной остальной обстановки и с созданием плавного перехода между двумя этими различными областями. В браузере типа Arena, портрет будет плавно осветляться на белом фоне, и затемняться на чёрном. Ещё один идеальный спецэффект с альфа-прозрачностью — это отбрасывание тени. Так, на изображениях ниже показан тукан, в первом случае отбрасывающий тень на красочный фон, во втором — на свою копию.
Эта особенность с прозрачность наиболее важна для маленьких изображений, обычно используемых на web-страницах, вроде цветных (круглых) маркеров или причудливого текста. Альфа-смешивание позволяет использовать другой эффект, а именно сглаживание (anti-aliasing), создавая иллюзию гладких кривых на сетке прямоугольных пикселей плавно изменяя их цвета, что позволяет добиться округлых и кривых изображений, хорошо отображаемых как на белом (к примеру), так и на любом другом фоне. Таким образом одно и то же изображение может быть многократно использовано в нескольких местах без «призрачного» эффекта, свойственного GIF-изображениям. [2]
40. Алгоритмы отрисовки графических примитивов. Отрисовка отрезков
class CLine
{
public:
CLine();
virtual ~CLine();
public:
int XFirst, YFirst; //Начальные и конечные
int XLast, YLast; //Координаты отрезка прямой
int LineWidth; //Толщина линии
COLORREF LineColor; //Цвет прямой
//Инкапсуляция функции в класс
DrawLine(CDC *pDC, int X, int Y); // Отрисовка отрезка начиная
// с координат X, Y.
};
CLine :: DrawLine(CDC *pDC, int X, int Y)
{
CPen Pen(PS_SOLID, LineWidth, LineColor); // Создание пера
CPen *OldPen; // Указатель на предыдущее перо
OldPen=pDC->SelectObject(&Pen); // Выбор пера
pDC->MoveTo(XFirst + X, YFirst + Y); // Перемещение пера
pDC->LineTo(XLast + X, YLast + Y); // Рисование отрезка
pDC->SelectObject(OldPen); // Выбираем предыдущее перо
}
Line1.XFirst=0; //Определяем начальные координаты отрезка
Line1.YFirst=0;
Line1.XLast =100;
Line1.YLast =100;
Line1.LineWidth=5; //Устанавливаем толщину отрезка
Line1.LineColor=RGB(255,0,0); //Красный цвет
CDC *pDC=GetDC(); //Получаем контекст окна
int StartPosX=10;
for (int i=0;i < 100;i++)
{
pDC->FillSolidRect(0,0,2000,2000,RGB(255,255,255)); //Очистка экрана
Line1.DrawLine(pDC, StartPosX,100); //Рисуем отрезок
StartPosX+=5;
Sleep(20); //Пауза 20 мс
}
ReleaseDC(pDC); //Освобождаем контекст окна


