Главная » Delphi » Растровые изображения в Windows

0

Microsoft всегда заимствовала чужие идеи, но никогда не воспроизводила их один к одному. Иногда у нее получалось лучше, чвще — хуже, но всегда оригинально. Оригинальным стал и родной для Windows формат растровых изображений BMP (что очевидно расшифровывается, как просто BitMaP, т. е. "карта битов"). Этот формат является основным при хранении изображений в памяти (в том числе и при переносе их через буфер обмена), и, естественно, существует в виде формата дискового файла. Другое наименование формата — DIB (Device-Independent Bitmap "аппаратно-независимый битмэп"; собственно, аббревиатуру BMP правильно относить только к дисковым файлам).

Напомним, что вообще-то любая печатная картинка, начиная с появления цинкографического способа воспроизведения изображений, состоит из отдельных точек, т. е. представляет собой растр. Качество печатных изображений напрямую зависит от подробности растра; считается, что разрешение в 300 точек на дюйм (dpi) достаточно для самой высококачественной полиграфической печати. Отсюда легко подсчитать, что картинка, соответствующая любительскому фото 10×15, должна иметь размеры примерно в 1200×1600 точек (или 2 мегапиксела в терминах цифровой фотографии). На самом де.чс это требование критично только для действительно качественной печати (типа "глянцевых" журналов или художественных апьбомоа), обычная цветная печать обходится разрешениями 100—150 dpi (уточнение этих понятий см. далее во врезке). В домашних условиях, или даже для изданий типа цветных еженедельников, 2-мегапиксельную картинку вполне можно растянуть на формат А4, правда, при условии, если исходный формат файла — не чересчур сжатый JPEG. В различия между форматами сжатия мы здесь вдаваться не будем — об этом написано достаточно много, наш предмет — собственно растровые изображения, т. е. чистая "карта битов". Для полноты картины добавим, что все упомянутые ранее рассуждения о разрешениях справедливы лишь именно для печати, а для воспроизведения на экране действуют сове|> шенно другие законы — прежде всего потому, что максимальное разрешение современных мониторов застыло на достигнутом еще лет 10 назад уровне максимум в 100 ppi (пикселов на дюйм) и больше этого предела в демонстрируемых картинках повышать его нет никакого смысла (картинка "во весь экран" в масштабе 1:1 на обычном мониторе — это примерно 1,2 мегапиксела). Поэтому для размещения в Интернете (если вы не выкладываете картинки специально для скачивания с целью последующей печати, или если это не штриховые чертежи) максимально необходимыми для качественного воспроизведения будут размеры около 640×480 — при большем размере вы будете только получать массу проклятий на свою голову за слишком долгое время загрузки.

Отображение растра при печати

Читатель вправе задать вопрос — а зачем нужны принтеры с разрешением, которое может на сегодняшний день составлять до 2400 точек (физических!) на дюйм и даже более, если даже в качественной полиграфии ограничиваются значением 300? Между понятием физического разрешения устройства печати (измеряемом в dpi) и результирующим разрешением картинки (линеатурой растра в линиях на дюйм, Ipi) есть большая разница, которую мы рассмотрим на примере монохромной печати оттенками серого. При типографской печати мы располагаем только одной краской, прозрачность которой никак регулировать нельзя. Как в таком случае обеспечить полутона? Единственным очевидным способом будет там, где изображение светлее, часть точек (лучше всего в случайном порядке) просто не закрашп- вать. Те, кто видел советские газеты 40—50-летней давности и старше, отлично понимает, о чем я — там растр был столь груб, что описанную мной технику воспроизведения полутонов можно было разглядеть невооруженным взглядом. С повышением разрешения печатающих устройств качество стало более приемлемым, но принцип сохранился (и в цвете он точно такой же, только там не один, а четыре разноцветных растра, наложенные друг на друга под разными углами, по числу красок в модели CMYK, на которой мы здесь останавливаться не будем). Этот метод передачи полутонов называется частотной модуляцией.

В результате разрешение печатающего устройства (dpi) и заданное разрешение полученного изображения (Ipi) оказываются связаны между собой нелинейной зависимостью. Линеатура есть величина обратная минимальному размеру элементарной ячейки изображения, в которой может быть воспроизведено заданное количество полутонов. Во многих профессиональных принтерах, между прочим, линеатуру можно устанавливать специально. Если взять за элементарную ячейку фрагмент изображения, равный разрешающей способности принтера (или типографского станка), то он может иметь только два цвета— черный или белый. Чем больший фрагмент изображения мы будем рассматривать как элементарную ячейку, тем больше оттенков можно различить. При максимальном качестве оттенков серого должно быть 256 (позже мы узнаем, почему принята именно эта величина). Какой величины ячейка обеспечит столько оттенков при заданном разрешении принтера? Оказывается, есть простая формула, которая позволяет это подсчитать точно: число полутонов равно единице плюс корень квадратный из частного от деления разрешения на линеатуру. Легко подсчитать, что при разрешении принтера 600 dpi и 256 оттенках, линеатура будет всего-навсего 40 Ipi, т. е. фактическое разрешение полутоновой картинки будет всего 40 линий на дюйм, или 15 линий на сантиметр! Очень грубая картинка, и это знает каждый, кто пытался печатать полутоновые фото на старых лазерных принтерах. (Кстати, для цвета расчет будет тем же самым, т. к. печать выполняется отдельно для каждого из составляющих цветов.)

Как же выйти из положения? Во-первых, для увеличения качества повышают физическое разрешение при печати — отсюда те самые умопомрачительные цифры. Для современных фотонаборных автоматов при подготовке картинок для качественной печати характерно физическое разрешение в 2540 dpi (100 точек на мм), что при всех воспроизводимых 256 градациях серого при расчете по формуле, приведенной ранее, соответствует линеату- ре в 160 Ipi или размеру полутоновой точки растра в 0,16 мм — вполне приличная величина, но фактически линеатура может быть установлена и значительно большей, потому что на бумаге с ее динамическим диапазоном максимум в 2D (т. е. отличием между черным и белым максимум в 100 раз) 256 градаций серого никому не нужны, они просто неразличимы. И тем не менее, нельзя же физическое разрешение увеличивать беспредельно?!

Поэтому в струйных принтерах научились регулировать величину точки растра. При этом методе— называемом еще амплитудной модуляцией — приемлемая передача полутонов возможна даже при относительно грубом растре, упомянутая ранее формула уже не работает и величина линеатуры вообще не применима, растрирование при печати не производится, элементарная ячейка соответствует физическому разрешению. И для качества принтера большее значение имеет не разрешение — конечно, сверх некоего предела, который уже достигнут во всех современных моделях— а минимальный размер капли красителя, который он может выдать. Приличной неличиной сейчас считается объем капли в 2 пиколитра, что соответствует ее диаметру в 8 микрон. На самом деле капля еще должна растечься, поэтому, чтобы соответствовать декларированному разрешению в 2400 dpi (примерно 12 микрон), поверх этого основного способа в струйных принтерах придумывают еще всякие ухищрения, вроде того, что капля специально делится на множество мелких, что позволяет более тонко регулировать полутона. И все же до качества настоящих фотоизображений, созданным традиционным серебряным способом, не могут дотянуть ни типографские, ни струйные устройства.

На практике ориентировочные цифры такие: при увеличении разрешения выше примерно 1200—1440 dpi цветная полутоновая картинка на струйном принтере зрительно лучше не становится, только чернила больше расходуются, а для нормального качества в быту вполне достаточно и 720 dpi. Заметим еще, что ведь все преимущества высокого разрешения принтера появляются в полной мере, если разрешение исходного изображения достаточно велико (отсюда и требование в 300 dpi)— нет никакого смысла повышвть разрешение при печати, если соседние точки все равно будут иметь одинаковый цвет. Но, конечно, оно необязательно должно достигать приведенных огромных величин, принтер при высоком разрешении просто лучше прорабатывает переходы между точками, и по этой причине картинки небольшого размера для печати следует готовить, растягивая их заранее, а не полагаясь на принтер. При грамотных алгоритмах растяжки исходная точка не делится на идентичные маленькие точки, фактически просто увеличиваясь н размерах, а цвета получающихся точек подбираются по специальным алгоритмам.

Имейте также в виду, что картинки при загрузке их в канву компонентов Delphi и в ресурсы приложения сами по себе не ужимаются в размерах — если вы загрузите изображение 2000×3000 точек, то оно уменьшится только при отображении, а в файле будут храниться все положенные мегабайты (то же самое относится и к картинкам, размещаемым в документах Word, закачиваемым с HTML-страницы, или хранимым в файлах PDF). Поэтому при пол- готовке проекта картинки следует заранее подгонять примерно под тог размер, который они будут иметь при отображении на экране.

Поняв теперь, что именно и когда нам требуется в смысле размеров и разрешения, обратимся на уровень ниже— а что такое пиксел при воспроизведении на экране? Смысл этого понятия кроется в устройстве любого экрана, на котором элементарная точка состоит из трех: красной, зеленой и синей составляющей. Балансируя яркостями этих точек, можно получить все оттенки цветов — от черного (все три составляющих погашены) до белого (одинаково максимальная яркость всех трех составляющих). К этой модели цвета, называемой еще "RGB" по именам трех основных цветов (Red-Green-Blue), при отображении на экране приводятся все остальные многочисленные модели цвета, на которых мы задерживаться здесь не будем’.

Компьютерные системы на основе DOS, о которых я с такой ностальгией вспоминал в начале главы, начиная с 90-х годов стандартно поддерживали так называемый режим VGA (Video Graphic Array, стандарт появился с внедрением компьютеров IBM PS2 в конце 80-х годов), который сейчас поддерживают все компьютеры на уровне BIOS (в этом режиме идет, например, установка Windows). VGA предполагает разрешение экрана 640×480 и 16 воспроизводимых цветов. Нас интересует последняя величина — как это достигается? В этом режиме каждый RGB-пиксел кодируется одним полубайтом (что равносильно одному шестнадцатеричному разряду), который, как известно, принимает как раз 16 значений. Раскладывается этот полубайт так: младшие три бита есть состояние RGB-составляющих (именно в таким порядке, т. е. самый младший бит представляет синий цвет), а старший управляет общей яркостью (фактически упрощенный вариант управления палитрой, которых в данном случае может быть две— более подробно об этом см. далее). Например, чтобы воспроизвести черный цвет, нужно все биты установить в 0, белый — в 1, а серых получится целых два: когда младшие три бита в 1, а старший — в 0 (светлый серый), или наоборот, когда младшие все в 0, а старший — в 1 (темный серый). Соответственно, будут два красных, два синих и тому подобных цвета — теперь вы легко можете понять, откуда взялось понятие "основных" (или "стандартных") 16 цветов и почему их порядок именно таков (см., например, выпадающий список в компоненте CoiorBox в проекте SlideShow из предыдущей главы). Сами эти цвета перечислены в таблице ниже вместе с их 24-битным представлением. Картинки, в которых представлено всего 16 отгенков, физически занимают на диске (без дополнительного сжатия, разумеется) ровно в два раза меньше байт, чем арифметическое произведение их высоты и ширины в пикселах (т. е. один байт представляет сразу два пиксела).

На самом деле адаптер VGA имеет возможность отображать много больше оттенков, чем 16 стандартных, поскольку внутреннее представление цвета в нем 18-битное (по 6 бит или 64 градации на каждую из RGB-составляющих). Это достигается с помощью задания так называемой палитры — т. е. установки непосредственного значения в соответствующих регистрах преобразования цвета в выходном цифроаналоговом преобразователе (Digital-Analog Converter, DAC) адаптера. Одновременно может воспроизводиться все равно только 16 оттенков, но они выбираются из 262 144 возможных. Текущая палитра может задаваться в файле с изображением (см. далее устройство формата BMP), или просто устанавливаться программно (процедура SetRGBcoi в модуле Graph из TurboPascal и TurboC). Подменой палитры можно, не меняя самого изображения, раскрасить его в другие цвета. Заданием палитры широко пользуются при редукции цветов (т. е. при сведении их к меньшему количеству оттенков) — так, широко известный формат GIF имеет однобайтное представление цвета (256 одновременно воспроизводимых оттенков), но при преобразовании из полноцветного (TrueColor) файла он в палитре сохраняет именно те оттенки, которые наиболее близки к оригиналу.

Набор сочетаний разрешения экрана и количества отображаемых при этом цветов устанавливает поддерживаемый всеми видеокартами стандарт VESA (Video Electronics Standards Association— ассоциация производителей компьютеров, организованная в 1989 году 29 компаниями с целью стандартизации в области компьютерной графики). Редакция 1.2 этого стандарта устанавливает набор графических режимов от 640×400 (256 цветов) до 1280×1024 (16 млн цветов), который поддерживается на уровне BIOS видеоадаптера. Режимы ниже первой величины (в том числе и "любимый" DOS 640×480, 16 цветов) поддерживаются на уровне BIOS материнской платы. Разрешения экрана могут быть и выше указанной в стандарте версии 1.2 величины (есть и версия VESA 2.0.), но они нас сейчас не волнуют, мы займемся количеством отображаемых цветов. Перескочив через редко используемый в наше время режим SVGA в 256 цветов (один целый байт на пиксел), а также через режим HighColor (16 бит на пиксел или 65 536 цветов) и другие, в том числе никогда не использовавшиеся на практике режимы типа 15 бит на пиксел, обратимся к наиболее распространенному в наше время режиму TrueColor, в котором на каждый пиксел приходится по три байта (или 24 бита). Естественно, никакой специальной "палитры" в таком режиме уже нет, разрядность DAC строго совпадает с представлением цвета в памяти. Каждый из отдельных байтов дает 256 вариантов для каждой из RGB-составляющих, итого пресловутые 16 миллионов, а точнее 16 7 7 7 2 1 6 (234) цветов. На самом деле и это количество отнюдь не исчерпывает всех оттенков, возможных в природе— именно поэтому практически все современные сканеры поддерживают "на всякий случай" 48-битный цвет. Такой запас нужен не для отображения, а для более точного представления цвета при преобразованиях — чтобы избежать ошибок округления, например, при сильной растяжке изображения. В конечных изображениях глубина цвета все равно обычно не превышает 24 бита, на практике для отображения на экране и тем более для печати на бумаге (где диапазон яркостей еще на пару порядков меньше) трех байтов более чем достаточно. Если подумать, то легко сообразить, что в таком представлении оттенков серого будет всего 256 (все три байта должны иметь одинаковую величину— и на практике этого также более чем достаточно), поэтому их можно хранить и в одном байте. Так как получается, что серый в цветном изображении и серый в формате именно оттенков серого (Grayscale)— для компьютера несколько разные вещи, то мы можем наблюдать печальные последствия такого разделения при печати на некоторых не самых продвинутых фотопринтерах — при воспроизведении оттенков серого в окружении других цветов они упорно пытаются имитировать серый смешением цветных красок, и результаты бывают довольно плачевными.

Кстати, преобразовать цветной BitMap в оттенки серого можно без специального преобразования палитры, если придать всем трем байтам для каждого пиксела одинаковую величину. Но вот по какому алгоритму? Это сложный и неоднозначный вопрос, но для автоматического преобразования обычно принято использовать формулу, которую применяют в телевидении: Gray = = 0.30R + 0.59G + 0.11В. Формула выведена эмпирически, и хорошо иллюстрирует тот факт, что яркость человек в основном воспринимает в зеленой части спектра. Нужно совершить это преобразование для каждого пиксела и затем приравнять все три его компонента полученной величине*. Для цвета, заданного типом TCoior в вашей программе (именно этот тип имеет массив Canvas.Pixels), это можно делать через функции GetXValue (Color:Tcolor) (где х равен R, G или в), которые возвращают интенсивность той или иной составляющей, и функцию rgb (r,g,B), которая производит обратное преобразование. В примере с оттенками серого вместо r, g и в в последней функции нужно подставить одну и ту же полученную расчетом величину Gray. Хотя далее мы будем делать похожую операцию непосредственным манипулированием битами, использование этих функций может быть проще для понимания.

Из принципов представления цвета в формате RGB понятно, что означают используемые в программировании (а также, например, в HTML) числа типа SFF0080, с помощью которых задается цвет. Старший байт этого числа есть интенсивность синей, средний — зеленой, и младший — красной составляющих (т. е. в обратном порядке, чем это было в 16-цветном режиме). Белый цвет будет SFFFFFF, черный — $000000, базовый красный — $000080, базовый яркий красный — $0000FF и т. д. А наш пример $FF0080 представляет яркий синий + темный красный — красивый оттенок ярко-лилового. Любой из оттенков серого будет характеризоваться одинаковым набором байтов.

В табл. 10.1 приводится соответствие 16 базовых цветов и их 24-битных представлений. В скобках приведено название и значение соответствующей DOS-константы так, как она определена в модуле Graph из Turbo Pascal и Turbo С. Значение ее совпадает со значением полубайта, определяющего цвет в 16-цветном пикселе. Нельзя не отметить, что названия констант в Windows более отвечают бытовому представлению о цветах, хотя и менее логичны с физической точки зрения.

Таблица 10.1.16 базовых (стандартных) цветов

Цвет

Представление

cIBlack (Black=0)

$000000

cINavy <Blue=1)

$000080

cIGreen (Green=2)

$008000

cITeal (Cyan=3)

$008080

dMaroon (Red=4)

$800000

cIPurple (Margenta=5)

$800080

clOlive (Brown=6)

$808000

clSilver (LightCray=7)

$C0C0C0

cIGray (DarkGray=8)

$808080

dBlue (LightBlue=9)

$0000FF

clLime (LightGreen=10)

$00FF00

clAqua (LightCyan=11)

$00FFFF

cIRed (LightRed=12)

$FF0000

clFuchsia (LightMargenta=13)

SFF00FF

clYellOW (Yellow=14)

SFFFF00

clWhite (White=15)

$FFFFFF

BMP

Теперь перейдем к тому, как хранятся эти самые пикселы и формате BMP (остальные форматы устроены аналогично, отличаются они лишь способами хранения собственно изображения, а также количеством и расположением информации в заголовках). В начале файла идут две структуры, bitmat’fileheader и bitmapinfoheader. Самый первый элемент первой структуры представляет собой два ASCII-символа "ВМ" (сигнатуру), с которых и начинается любой BMP-файл (рассмотрите его в каком-нибудь ПЕХ-редакторе или даже просто откройте в Блокноте). Это представляет удобный и быстрый, хотя и не стопроцентно надежный, способ опознавания формата (кстати, для иконок такого способа уже нет). Для надежности можно использовать дополнительно следующие четыре байта, которые представляют собой число типа DWord (записанное, естественно, начиная с младшего байта), равное размеру самого BMP-файла (а не картинки!).

Описание заголовочных структур легко при надобности найти на том же сайте MSDN и, т. к. нам BitMap вручную создавать, слава богу, не придется3, то здесь заметим лишь, что в заголовках приводится исчерпывающая информация о собственно формате изображения (цветное или оттенки серого, количество цветов в битах на пиксел, ширина и высота картинки, разрешение в точках на метр, наличие и тип сжатия, где в файле расположено начало массива пикселов и другая полезная и не очень информация). Если число оттенков представляется числом бит на пиксел, отличающимся от TrueColor (т. е. меньше, чем 24), то после заголовков может идти палитра — массив acolors, представляющий структуры из четырех байтов, содержащих нужные интенсивности красного, зеленого и синего, четвертый байт декларируется как резервный. А собственно массив точек изображения тогда состоит из индексов к этому массиву, т. е. из номеров цветов. Некоторые подробности об устройстве файлов BMP-формата вы можете узнать из главы 19, где они будут использованы для иллюстрации приемов стеганографии — скрытой пересылки тайных сообщений.

Если вы попытаетесь сохранить TrueColor-каргинку в формате BMP с 16 или 256 цветами, то результат будет таким же, как и в случае GIF — в палитре будут записаны наиболее близкие оттенки (а не базовые цвета!). Для TrueColor массива значений палитры вообще нет, после заголовков сразу начинается массив пикселов изображения (aBitmapBits), сами значения байтов в этом массиве дают исчерпывающую информацию о цвете. Так как каждый пиксел в этом случае кодируется тремя байтами, то место, занимаемое на диске BMP-файлом, практически равно утроенному произведению ширины на высоту картинки в пикселах (чуть больше его, если учитывать заголовок), и кстати, эта величина указывается в заголовке для проверки целостности файла (варианты со сжатием мы не учитываем, т. к. на практике в BMP оно используется редко). Собственно расположение байтов в массиве aBitmapBi-s почему-то начинается с нижней строки изображения (т. е. первые три бита кодируют самый левый пиксел самой нижней строки). Какая в этом сермяжная правда — мне узнать не удалось, возможно при составлении формата хотели заставить всех разработчиков экранную координату Y отсчитывать в привычном для нас виде, т. е. по возрастанию снизу вверх. Но эта координата всегда отсчитывается от верхнего обреза экрана (потому что именно отсюда начинается построчная развертка электронного луча, а массивы битов, модулирующих его, располагать в памяти удобно именно по ходу его работы), и такой способ представления информации ведет лишь к дополнительным сложностям.

Все остальные многочисленные форматы для картинок, как уже говорилось, при работе с ними в Windows все равно переводят в BMP (точнее, в DIB) — так, в компонент image мы в главе 2 загружали картинку JPEG (что можно сделать при наличии соответствующего драйвера из модуля JPEG), но в исполняемом файле она все равно хранится в BMP.

Иконки

Остановимся теперь еще на одном важнейшем для Windows формате— для хранения иконок. Понять, как они устроены изнутри, даже важнее, чем в случае BMP, иначе будут непонятны многие действия, которые мы предпримем далее.

Не все знают, что у типовых пиктограмм Windows есть конкретный автор — это дизайнер Сьюзен Кэр. Еще интереснее то, что она разрабатывали иконки, логотипы и элементы интерфейса не только для Windows. Еще раньше она сделал то же самое для MacOS, а позднее — для OS/2, и это объясняет тог факт, что, например, "песочные часы" и "корзина" в этих операционных системах очень похожи. Но и участием в этих крупных проектах она не ограничилась. В разное время Сьюзен сотрудничала с Intel. Logitech, Motorola. Netscape, Palm. Xerox и другими компаниями, так что не будет преувеличением утверждать, что интерфейсом почти любого компьютерного "девайса" в мире мы в конечном итоге обязаны именно ей.

Идея, которая лежит в основе воспроизведения иконок в Windows, представлена на рис. Ю.2. Собственно иконка содержит не одно изображение, а два:

AND-маску и XOR-маску. Первая всегда представляет собой двухбитное изображение, т. е. только черный или белый цвет для каждого пиксела (на рисунке черный цвет означает биты с нулевым значением). Сначала к фону "прикладывается" именно она. Эта маска потому и носит название AND- маски, что над пикселами совершается побитовая операция AND (каждый бит в AND-маске в любом случае соответствует целому пикселу, т. е. если фон имеет глубину цвета TrueColor, то не одному, а всем 24 битам фона). Согласно определению операции AND (равно 1 только тогда, когда обе исходные величины равны 1), там, где в маске были нулевые биты, в фоне образуется "дыра" (на самом деле пикселы просто окрашиваются в черный цвет). Затем к тому же месту прикладывается XOR-маска, которая в принципе может содержать изображение с глубиной цвета от 2 до 16 оттенков (а теоретически— и 256, и даже TrueColor), но на практике чаще используется именно 16, т. е. цвет хранится в ней в формате полубайта (на рисунке для наглядности XOR-маска показана также с двухбитным цветом). Delphi умеет работать только с 16-цветными иконками, из-за чего у нас возникнут в дальнейшем сложности. С XOR-маской над пикселами фона (с уже имеющейся "дырой") производится операция "Исключающее ИЛИ" (равно 0 тогда, когда оба входа одинаковы, см. также главу 19). Там, где в XOR-маске были поля с нулевым значением битов (т. е. черного цвета), фон остается неизменным (если одна исходная величина равна нулю, то операция XOR будет повторять вторую исходную величину), в противном случае на фон с дырой накладывается то изображение, которое записано в XOR.

Рис. 10.2. Отображение иконок в Windows (черным показаны пикселы с нулевым знамением)

Заметки на полях____________________________________________

Что будет, если мы "поиздеваемся" над изображением с помощью различных логических операций? Если применить к массиву пикселов операцию NOT, то мы получим изобрвжение в инвертированных цветах — именно так проще всего производить выделение (так и делается, скажем, в Word, когда белый нужно заменить на черный и наоборот). Но могут быть и другие варианты — так. в элементах управления, в браузерах выделение традиционно производится синим. а не черным фоном, но делается это по-разному. На диске в папке Glava10\Ctrl-A лежит файл ctrl-A.htm, который содержит потрясающие по выразительности графические произведения неких умельцев, очень хорошо иллюстрирующие возможности операций над пикселами. Попробуйте загрузить этот файл в Internet Explorer и нажать комбинацию клавиш <Ctrl>+<A>. Не пытайтесь открыть картинки отдельно в обычном редакторе, загружать страничку a Opera, FireFox или. к примеру, в Word — того же эффекта вы не получите, там выделение производится иной логической операцией. Кстати, преобразование BMP в JPEG твкже сильно портит эффект.

И операции копирования канвы, которые мы рассмотрим далее, и перо Реп допускают различные режимы взеимодействия с фоном. Если скопировать изображение фона в отдельный BitMap, а затем скомбинировать его с тем же самым фоном операцией XOR, то оно уничтожится — будет черная дыра. Если применить операцию NOTXOR, то дыра станет белой. Если скомбинировать фон через XOR с белым каадратом — он инвертируется, если с черным — не изменится, а применение XOR с отдельными чистыми цветами будет инверти- роввть соответствующую составляющую. Так, если исходный квадрат синий, то белый цвет станет желтым, желтый — белым, черный — синим и т. п. Инвертированию подвергнутся только чистые цвета, а "грязные" будут изменяться непредсказуемо. Определения логических операций нелишне выучить наизусть, но даже в этом случае для точного предсказания результата чаще асего необходимы эксперименты.

А для иконок, естественно, подгадывают так, чтобы изображение на XOR- маске совпадало с дырой (т. е. с тем местом, где в AND-маске были нули), иначе полученные цвета не будут соответствовать заданным. Так получается эффект прозрачности иконки — естественно, что для иконки без прозрачных областей AND-маска должна содержать все 0 (белое допускается там, где и на XOR-маске белый цвет), а XOR-маска полное изображение.

Описанный механизм получения "прозрачного" цвета есть не что иное, как физическая реализация альфа-канала — понятия, широко распространенного в компьютерной графике. Он может быть реализован для любого изображения, не только иконки — так, Windows 2000/ХР поддерживают подобный механизм для формы в целом, но в Windows 98 у вас ничего этого работать не будет (см. также главу 12). Любой BitMap можно отобразить с "прозрачным" цветом, но только отобразить— сохранить альфа-канал в стандартном файле BMP не удастся. Позже мы вернемся к вопросу, что на практике означает термин Transparency для класса TBitMap, а сейчас только заметим, что файлы в формате BMP потому и не используются в профессиональной графике, что не поддерживают, в частности, альфа-канал. Даже устаревший, но по-прежнему популярный GIF поддерживает однобитный (как в иконках) "прозрачный" цвет, а такие форматы, как PNG или профессиональный формат TIFF, поддерживают восьмибитную градацию прозрачности (256 уровней). Также в них нет никаких ограничений на глубину цвета— она может составлять от 2 до 48 бит (больше, чем 281 474 976 710 656 оттенков, видимо, на практике уже » не потребуется).

Из этих соображений легко подсчитать размер файла стандартной иконки 32×32 пиксела с 16 цветами. AND-маска должна содержать 1024 бита или 128 байт, а XOR-маска с 4-битным цветом 512 байт, итого собственно изображение займет в файле 640 байт, плюс оно сопровождается таким же заголовком bitmapinfoheader. как н в BMP. размером ровно 40 байт. Кроме этого, в файле имеется 22-байтный заголовок iconheader и еще 64 байта занимает палитра в четырехбайтном представлении каждого из 16 возможных цветов. Итого 766 байт (проверьте!). В принципе один файл иконки может содержать и несколько разных иконок, но на практике этим никто не пользуется (достаточно того, что в ресурсах можно задать несколько иконок). Что же касается размеров, то они могут быть 16×16, 32×32 и даже 64×64. Интересно, что традиции представления иконок существуют уже. наверное, лет двадцать без каких-то изменений — как и в Windows первых версий, в последней версии ХР наиболее популярны иконки 32×32 с 16 цветами.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

  • Комментарии