Просмотрщик графических файлов. Форматы PCX и BMP

АСТРАХАНСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ

УНИВЕРСИТЕТ

РОСКОМРЫБОЛОВСТВА

Институт информационных технологий и коммуникаций







	Кафедра 

Информационных 

систем







КУРСОВАЯ РАБОТА





по дисциплине «Основы алгоритмического языка C++»

на тему «Просмотрщик графических файлов. Форматы PCX и BMP»











		Выполнил:

		студент группы ЗИУ–31

		Андросов О.В.

		98 ИУ-022

	

		Проверил:

		доцент Миронов Б.Н.

		Рецензент:

		доцент Лаптев В.В.

























Астрахань, 2001 год

Содержание

	Введение.	3

	1. Форматы графических файлов.	4

	1.1. Общие принципы строения графических файлов.	4

	1.2. Описание и структура файла формата PCX.	4

	1.3. Описание и структура файла формата BMP.	6

	2. Описание программы.	9

	2.1. Реализация алгоритма просмотра файла PCX.	9

	2.2. Реализация алгоритма просмотра файла BMP.	9

	2.3. Используемые переменные и функции.	9

	2.3.1. Глобальные переменные.	9

	1.3.2. Основные функции и процедуры	10

	2.4. Запуск программы	11

	2.5. Содержание дистрибутивной дискеты	11

	СПИСОК ЛИТЕРАТУРЫ	12

	ПРИЛОЖЕНИЕ	13

	Листинг программы “Просмотрщик графических файлов”.	13




Введение.

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

Расширение в имени файла говорит о том, в каком формате хранится информация. Например, расширение BMP обозначает BMP-файл, поддерживаемый в системах Windows и OS/2 (BMP - сокращение от bitmap, т.е. битовый, растровый). Формат файла BMP - это "родной" формат растровой графики для Windows, поскольку он наиболее близко соответствует внутреннему формату Windows, в котором эта система хранит свои растровые массивы. 

Формат PCX стал первым стандартным форматом графических файлов для хранения файлов растровой графики в компьютерах IBM PC. Формат PCX изначально был придуман для хранения черно-белых графических файлов, создаваемых ранней версией программы раскраски PC Paintbrush. На этот формат в начале 80-х гг. фирмой Microsoft была приобретена лицензия, и затем он распространялся вместе с изделиями Microsoft. В дальнейшем формат был преобразован в Windows Paintbrush и начал распространяться с Windows. Хотя область применения этого популярного формата сокращается, файлы формата PCX, которые легко узнать по расширению PCX, все еще широко распространены сегодня.




1. Форматы графических файлов.

1.1. Общие принципы строения графических файлов.

Что содержит растровый графический файл? Такой файл обычно содержит информацию двух видов: графическую и неграфическую. В графических данных указываются цвета пикселов, неграфические данные содержат другую информацию, необходимую для восстановления изображения, например его высоту и ширину. (Если изображение содержит 1 миллион пикселов, то как графической программе узнать размеры: рисовать ли ей изображение 500 на 2000 или 1000 на 1000 пикселов?) Неграфическая часть файла может также включать другую информацию, такую как номер версии или сведения об авторских правах. Все зависит от формата и от того кто (или какой программный пакет) создал этот файл. 

В растровых файлах используется обычно один из двух методов хранения данных о пикселах. В полноцветных изображениях пиксел может принимать любое из более, чем 16 миллионов значений, поэтому и цвет пиксела хранится обычно как 24-разрядное значение - по 8 битов на красную, зеленую и синюю компоненты цвета. Если изображение содержит 1 миллион пикселов, то размер файла будет равен 3 миллионам байтов плюс длина неграфических данных. Если же изображение ограничено 256 или менее цветами, то цветовая информация обычно кодируется с использованием палитры. Вместо того, чтобы хранить значение цвета пиксела, информация о пикселе указывает на строку в палитре, а она, в свою очередь, содержит цвет. С уменьшением количества битов, требуемых для представления цвета пиксела, уменьшается размер файла (а это во все времена ценное приобретение, поскольку пространство памяти не бывает бесплатным). 

В качестве примера возьмем изображение из миллиона пикселов, содержащее 256 различных цветов. Кодирование цвета каждого пиксела 24-битным значением пpиводит к расточительной избыточности, потому что некоторые (а возможно и все) из 256-ти цветов повторяются неоднократно. Для хранения используемых цветов лучше выделить в файле 768 байтов под цветовую палитру: 256 полей по 24 бита, каждое поле содержит один из цветов, встречающихся в изображении. Тогда под значение цвета пиксела можно отвести 8 битов, то есть целое число в диапазоне от 0 до 255, указывающее номер цвета в палитре. теперь для графической части файла достаточно 1.000.768 байтов, против прежних 3.000.000 байтов, которые требуются для хранения этого изображения без использования палитры. И даже с учетом дополнительных байтов из неграфической части файла, мы все-таки получаем уменьшение размера файла почти на две трети. 

В большинстве форматов графических файлов пикселы располагаются построчно. Если размеры изображения 1000 на 1000 пикселов, и каждый пиксел представляется 8-ю битами, то первые 1000 байтов графической части файла содержат цвета пикселов из верхней строки изображения (слева направо), следующие 1000 байтов содержат цвета пикселов второй строки и так далее. Однако, в некоторых форматах используется иной порядок строк. Например, BMP-файлы начинаются с нижней строки и заканчиваются верхней строкой изображения. В каждом формате графические и неграфические данные структурируются по своему. 



1.2. Описание и структура файла формата PCX.

Файлы PCX разделены на следующие три части: заголовок PCX, данные растрового массива и факультативная таблица цветов. 128-байт заголовок PCX содержит несколько полей, в том числе поля размера изображения и числа бит для кодирования информации о цвете каждого пиксела. Информация растрового массива сжимается с использованием простого метода сжатия RLE; факультативная таблица цветов в конце файла содержит 256 значений цветов RGB, определяющих цвета изображения. Формат PCX первоначально был разработан для адаптеров CGA- и EGA-дисплеев и в дальнейшем был модифицирован для использования в адаптерах VGA и адаптерах истинных цветов. Кодирование цвета каждого пиксела в современных изображениях PCX может производиться с глубиной 1, 4, 8 или 24 бит. 



Заголовок файла PCX (128 байт) 

Сигнатура файла PCX (1 байт) - Постоянный флаг 10 - ZSoft .PCX 

Версия. (1 байт) - (0 - Версия 2.5, 2 - Версия 2.8 с информацией о палитре, 3 - Версия 2.8 без информации о палитре, 5 - Версия 3.0).

Кодирование. (1 байт) - (1 - кодирование длинными сериями).

Бит/пиксел (1 байт) - Число бит на пиксел в слое.

Xmin (2 байт) – угловые координаты изображения.

Ymin (2 байт) - угловые координаты изображения.

Xmax (2 байт) - угловые координаты изображения.

Ymax (2 байт) - угловые координаты изображения.

Горизонтальное разрешение создающего устройства (2 байт).

Вертикальное разрешение создающего устройства (2 байт).

Набор цветовой палитры (48 байт).

Не используется (1 байт). Зарезервировано.

Число цветовых слоев (1 байт).

Число байт на строку в цветовом слое (2 байт).

Информация о палитре (2 байт) – (1 = цветная/черно-белая, 2 = градации серого).

Не используется (58 байт). Заполняется нулями до конца заголовка.



Набор цветовой палитры.

Информация палитры хранится в одном из четырех форматов. Для режимов CGA, используется только первый и четвертый байт палитры заголовка. Первый байт обозначает цвет заднего фона - разделив его на 16 получим величину от 0 до 15. Четвертый байт обозначает цвет переднего фона. Число палитр CGA равно 8, поэтому разделим на 32 чтобы получить величину в пределах от 0 до 7.

Для режимов EGA, данные хранятся в 16 "тройках". Тройка - это 3-байтовый набор величин красного, зеленого и голубого цветов. Так как каждая величина может находиться в диапазоне от 0 до 255, Вы должны отобразить эти величины в одном из четырех возможных уровней для каждого цвета. Следовательно, 256 разделить на 4 будет 64, поэтому с 0 до 63 = уровень 0, с 64 до 127 = уровень 1, и так далее. Система BIOS адаптера EGA ожидает один байт формата 00RGBrgb для кажого регистра палитры. Четыремя возможными величинами для Bb являются 00, 01, 10 и 11. Когда Вы определили уровень для каждого цвета, скомбинируйте их в байте, совместимом с BIOS (Базовой системой ввода-вывода).

Для 16-цветных режимов VGA, палитра снова хранится в "тройках". Для преобразования в совместимый формат BIOS, сдвиньте каждый байт вправо на два бита. Это преобразование автоматически выполняется функцией pcxGetFilePalette или функцией pcxDecodePalette.

И последний формат поддерживает 256-цветный режим VGA. Так как каждый цвет требует тройку RGB (R (red)- Красный, G (green) - зеленый, B (blue) - голубой), для хранения всей палитры VGA будет необходимо 768 байт. Формат PCX, однако, может поддерживать только 16 цветов как максимум, поэтому палитра не может храниться в заголовке изображения по своему обычному адресу.

Формат 256-цветной палитры претерпел мало изменений с тех пор, когда были впервые созданы 256-цветные режимы. Заголовок PCX был изначально создан для хранения 16 цветов как максимум, и длина его составляет всего 128 байт. Для 256-цветной палитры требуется 768 байт (3 умножить на 256) - очевидно, что надо внести изменение. 256-цветная палитра форматируется и интерпретируется точно также, как 16-цветная, естественно, за исключением того, что она длиннее. Палитра (число цветов x 3 байта длины) добавляется в конец PCX файла и ей предшествует байт с десятичным значением 12. Для определения палитры VGA BIOS вам достаточно разделить прочитанные значения цветов на 4. 

Для доступа к 256-цветной палитре следует: Прочитать в заголовке поле Version. Если оно равно 5, палитра должна быть. Или прочитать в заголовке поле число бит на пиксел. Если оно равно 8, 256-цветная палитра должна быть.Прочитать конец файла и отсчитать назад 769 байт. Найденное вами значение должно равняться 12, что указывает на присутствие 256-цветной палитры.

Оставшаяся часть файла с изображением состоит из закодированных графических данных. При кодировании используется простой алгоритм, основанный на методе длинных серий. Если в файле запоминается несколько цветовых слоев, каждая строка изображения запоминается по цветовым слоям (в общем случае красному-R, зеленому-G, синему-B и слою интенсивности-I) 

Метод кодирования состоит в следующем: 

ДЛЯ каждого байта X, прочитанного из файла

    ЕСЛИ оба старших бита X равны 1, то

        <повторитель> = 6 младшим битам X

        <данные> = следующему байту за X

    ИНАЧЕ

        <повторитель> = 1

        <данные> = X

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



1.3. Описание и структура файла формата BMP.

Формат графических файлов - BMP широко использующийся в системах Windows и OS/2. В частности мы рассмотрим BMP-файл, описывающий 256-цветное изображение размером 1000 на 1000 пикселов. (Формат BMP-файла немного различается в зависимости от того сколько цветов содержит изображение - 2, 16, 256 или 16,7 млн. Форматы BMP в Windows и OS/2 также немного отличаются. Описание этого файла будет соответствовать варианту BMP для Windows.) В файлах BMP информация о цвете каждого пиксела кодируется 1, 4, 8, 16 или 24 бит (бит/пиксел). Числом бит/пиксел, называемым также глубиной представления цвета, определяется максимальное число цветов в изображении. Изображение при глубине 1 бит/пиксел может иметь всего два цвета, а при глубине 24 бит/пиксел - более 16 млн. различных цветов.

Файл состоит из четырех основных частей: 14-байтного заголовка файла, 40-байтного информационного заголовка, 1024-байтной цветовой таблицы и миллиона байтов для значений пикселов. (Под цветовую таблицу отводится 1024 байта, а не 768, поскольку в каждое 24-битовое поле таблицы добавлен еще один, неиспользуемый байт.)



Структура графического файла формата BMP.

Заголовок файла растровой графики (14 байт) 

Сигнатура файла BMP (2 байт) 

Размер файла (4 байт) 

Не используется (2 байт) 

Не используется (2 байт) 

Местонахождение данных растрового массива (4 байт)

Информационный заголовок растрового массива (40 байт) 

Длина этого заголовка (4 байт) 

Ширина изображения (4 байт) 

Высота изображения (4 байт) 

Число цветовых плоскостей (2 байт) 

Бит/пиксел (2 байт) 

Метод сжатия (4 байт) 

Длина растрового массива (4 байт) 

Горизонтальное разрешение (4 байт) 

Вертикальное разрешение (4 байт) 

Число цветов изображения (4 байт) 

Число основных цветов (4 байт)

Таблица цветов (длина изменяется от 8 до 1024 байт)

Собственно данные растрового массива (длина переменная)



1. Первые 14 байтов BMP-файла составляют его заголовок. Заголовок файла содержит три значения: буквы BM, которые говорят о том, что графический файл имеет BMP формат, число, означающее размер файла и число, указывающее на то, где находятся растровые данные. Последнее число равно количеству байтов от начала файла. Еще два поля в заголовке файла зарезервированы для будущих нужд и обычно содержат нули. 

2. Необходимые неграфические данные упрятаны в информационном заголовке. Поля в информационном заголовке в числе прочих содержат его размер (40 байтов в BMP-файлах для Windows), высоту и ширину изображения в пикселах, и количество битов на пиксел. В зависимости от способа кодирования поле бит на пиксел, может принимать значения:

1 - битовый образ монохромный, и таблица цветов должна содержать два элемента. Каждый бит в массиве данных кодирует один пиксел. Если значение бита - 0, то пиксел становится первым цветом таблицы; если - 1, пиксел становится вторым цветом таблицы.

4 - битовый образ имеет максимум 16 цветов, и таблица цветов имеет до 16 элементов. Цвет каждого пиксела определяется по таблице цветов при помощи четырехбитного индекса. Например, если первый байт данных имеет значение 3Ah, то при отображении битового образа цвет первого пиксела определяет четвертый элемент таблицы цветов, а цвет второго - одиннадцатый.

8 - битовый образ имеет максимум 256 цветов, и таблица цветов имеет до 256 элементов. Каждый байт массива данных определяет цвет одного пиксела.

24 - битовый образ имеет максимум 2 в 24-й степени цветов. Таблица цветов пуста, а цвет пикселов определяется пакетами из трех байтов, описывающими цветовые интенсивности красного, зеленого и голубого цветов.

3. Цветовая таблица содержит 256 полей по 4 байта. первый байт в каждом поле отвечает за синюю компоненту цвета, второй за зеленую и третий - за красную. Четвертый байт не используется и обычно устанавливается в 0. Если первые три значения в цветовой таблице 0, 192 и 192, это значит, что нулевой номер соответствует желтому цвету средней интенсивности (смесь зеленого и красного). В цветовой таблице определены все цвета, использующиеся в изображении.

4. Остальная часть файла содержит значения пикселов. Последовательность байтов соответствует порядку пикселов в изображении: слева направо, начиная с нижней строки изображения. Значение каждого байта есть номер цвета в цветовой таблице. Формат собственно данных растрового массива в файле BMP зависит от числа бит, используемых для кодирования данных о цвете каждого пиксела. При 256-цветном изображении каждый пиксел в той части файла, где содержатся собственно данные растрового массива, описывается одним байтом (8 бит). Это описание пиксела не представляет значений цветов RGB, а служит указателем для входа в таблицу цветов файла. Таким образом, если в качестве первого значения цвета RGB в таблице цветов файла BMP хранится R/G/B=255/0/0, то значению пиксела 0 в растровом массиве будет поставлен в соответствие ярко-красный цвет. Значения пикселов хранятся в порядке их расположения слева направо, начиная (как правило) с нижней строки изображения. Таким образом, в 256-цветном BMP-файле первый байт данных растрового массива представляет собой индекс для цвета пиксела, находящегося в нижнем левом углу изображения; второй байт представляет индекс для цвета соседнего справа пиксела и т. д. Если число байт в каждой строке нечетно, то к каждой строке добавляется дополнительный байт, чтобы выровнять данные растрового массива по 16-бит границам. 

Не все файлы BMP имеют структуру, подобную показанной на схеме. Например, файлы BMP с глубиной 16 и 24 бит/пиксел не имеют таблиц цветов; в этих файлах значения пикселов растрового массива непосредственно характеризуют значения цветов RGB. Также могут различаться внутренние форматы хранения отдельных разделов файла. Например, информация растрового массива в некоторых 16 и 256-цветных BMP-файлах может сжиматься посредством алгоритма RLE, который заменяет последовательности идентичных пикселов изображения на лексемы, определяющие число пикселов в последовательности и их цвет. В Windows допускается работа с BMP-файлами стиля OS/2, в которых используются различные форматы информационного заголовка растрового массива и таблицы цветов. 




2. Описание программы.

После запуска программы PCX_BMP.EXE <имя графического файла> стандартная функция Fnsplit разбивает полное имя файла на 4 части. Что дает возможность передать файлы с расширениями PCX и BMP на обработку функциям вывода графических файлов на экран (show_pcx и show_bmp).



2.1. Реализация алгоритма просмотра файла PCX.

Вывод на экран картинки, хранящейся в PCX-файле, начинается с чтения заголовка файла. С помощью этого определяется является ли этой файл форматом PCX (manufacturer должен быть равен 10), размеры изображения, информации о палитре, число цветовых слоев. После чего происходит переход на 768 байт с конца файла для чтения набора цветовой палитры и с помощью функции Set_palette заполнение цветовой палитры значениями.

Теперь начинается декодирование первой строки развертки - прочитывается первый байт данных из файла. Если два старших бита этого байта равны 1, оставшиеся шесть битов показывают сколько раз следует повторить следующий байт из файла. Если это не так, то этот байт сам является данными с повторителем равным 1. Продолжайте декодирование до конца строки, ведя подсчет количества байтов, переданных в буфер вывода. В конце каждой строки развертки имеет место остановка алгоритма кодирования, но ее не существует при переходе от одного слоя к другому. Как только строка со значениями пикселов прочитана из файла, она в функции put_pixel передается в видео-буфеp для получения изображения на экране. 



2.2. Реализация алгоритма просмотра файла BMP.

Вывод на экран картинки, хранящейся в BMP-файле, начинается с чтения заголовка файла и информационного заголовка. Программа таким образом проверяет является ли этот файл графически форматом BMP (сигнатура должна быть ‘BM’) а так же узнает размеры изображения и количество цветов. 

Затем программа читает цветовую таблицу. После чего программа с помощью функции Set_palette заполняет цветовую палитру значениями из цветовой таблицы. Таким образом, обеспечивается правильная передача цветов картинки. Если компьютер способен отобразить тысячи или миллионы цветов одновременно, то цветовую палитру заполнять не нужно. 

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



2.3. Используемые переменные и функции.

2.3.1. Глобальные переменные.

typedef unsigned char byte

Объявление типа.



char far *video = (char far *) 0xA0000000L

Указатель на видеопамять.



int MaxX, MaxY

Максимальное разрешение экрана.



VidMode=0x13

Гафический режим 13h.



1.3.2. Основные функции и процедуры

struct pcxHeaderType 

Структура заголовка файла PCX.



struct bmpHeaderType

Структура заголовка файла BMP.



void set_mode (void)

Установка графического режима 13h.



void set_text (void)

Установка текстового режимa.



void set_palette (int color, byte r, byte g, byte b)

Установление цвета в палитре.



void put_pixel (int x, int y, byte color)

Вывод пиксела установленного цвета в позицию x y.



void read_pcx_header (FILE *dataFile, pcxHeaderType &pcxHeader)

Чтение заголовка pcx файла.



int show_pcx (char *name)

Вывод pcx файла на экран.



void read_bmp_header (FILE *dataFile, bmpHeaderType &bmpHeader)

Чтение заголовка bmp файла.



void read_bmp_header (FILE *dataFile, bmpHeaderType &bmpHeader)

Чтение заголовка bmp файла.



int show_bmp (char *name)

Вывод bmp файла на экран.



void main(int argc, char *argv[])

Читает имя файла из командной строки, проверяет по расширению к какому типу файлов он относится и вызывает соответствующую функция просмотра.



2.4. Запуск программы

Программа является консольным приложением и функционирует под управлением операционной системы MS DOS или её эмуляции («Сеанс MS DOS» в Windows’е).

Запуск программы производится из окна файлового менеджера, либо из командной строки, и имеет следующий синтаксис:



PCX_BMP.EXE <имя графического файла>[PCX]/[BMP]



Примеры:

		PCX_BMP.EXE TEST.PCX

		PCX_BMP.EXE TEST.BMP



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



2.5. Содержание дистрибутивной дискеты



Дискета с дистрибутивом содержит следующие файлы:



В каталоге DEMO находится файл основной запускающей программы PCX_BMP.EXE.



В каталоге SOURCE находятся файл PCX_BMP.cpp - исходный текст программы, написанный на языке С++.



В каталоге DOC находится файл Viewer.doc - описание алгоритма и работы программы просмотра графических файлов.



В каталоге TEST находятся тестовые графические файлы.



					TEST.BMP 	– 	графический файл формата BMP (320x200)

					TEST.PCX 	– 	графический файл формата PCX (320x200)

					TEST2.BMP 	– 	графический файл формата BMP (224x160)

					TEST2.PCX 	– 	графический файл формата PCX (256x160)

					TEST3.BMP 	– 	графический файл формата BMP (320x22)

					TEST3.PCX 	– 	графический файл формата PCX (200x125)



В корневом каталоге дискеты находится файл Read.me.




СПИСОК ЛИТЕРАТУРЫ



Д.С. Ватолин "Алгоритмы сжатия изображений". Методические материалы к спецкурсу ВМиК МГУ "Машинная графика-2" под руководством Ю.М. Баяковского.

Справочное руководство по IBM PC. Часть 1. Москва ТПП “Сфера” 1991 стр. 55-62

http://home.novgorod.ru/lab/index.php3?path=formtfil/n-q

http://fileformat.virtualave.net/ind_form.htm

http://www.codenet.ru/progr/formt/intro.php

http://vnews.uka.ru/html/school.htm

http://www.halyava.ru/document/ext_b.htm

http://members.nbci.com/treestation/

http://graphics.cs.msu.su/

http://www.programmersheaven.com/zone10/index.htm

http://www.dcs.ed.ac.uk/home/mxr/gfx/utils-hi.html

http://rtfm.vn.ua/

http://www2.crosswinds.net/~hellerzone/manuals.html

http://www.math.rsu.ru/dictionary/fileform.htm








ПРИЛОЖЕНИЕ

Листинг программы “Просмотрщик графических файлов”.

#include <dos.h>

#include <iostream.h>

#include <conio.h>

#include <stdio.h>

#include <string.h>

#include <dir.h>



// Глобальные переменные

typedef unsigned char byte;                               // объявление типа

char far *video = (char far *) 0xA0000000L;   // указатель на видеопамять

int MaxX=320, MaxY=200, VidMode=0x13;  // Максимальное разрешение экрана



// Структура заголовка файла PCX

struct pcxHeaderType

   {

   char manufacturer;      // всегда 10 для Paintbrush

   char version;           // информация о версии (версия 5)

   char encoding;          // групповое кодирование (=1)

   char bitsPerPixel;      // число бит на пиксел

   int  x, y;              // координаты левого верхнего угла

   int  width, height;     // размеры изображения

   int  hResolution, vResolution;  // горизонтальное и вертикальное разрешение экрана

   char egaPalette[48];    // палитра 256 цветов

   char reserved;          // зарезервировано всегда 0

   char nColorPlanes;      // число цветовых слоев

   int  bytesPerLine;      // число байт на строку в цветном слое

   int  paletteType;       // определение палитры (1-цветная/черно-белая, 2-градация серого)

   char padding[58];       // заполняется 0 до конца заголовка

   };



// Структура заголовка файла BMP

struct bmpHeaderType

   {

   char magic1, magic2;		// тип файла ('BM')

   long fileSize;		// размер файла в байтах

   long reserved;		// зарезервировано всегда 0

   long pixelOffset;		// смещениме данных от заголовка

   long bmiSize;		// размер заголовка

   long cols, rows;		// ширина и высота картинки

   int  nPlanes;		// число цветовых слоев (1)

   int  bitsPerPixel;	// число битов на пиксел (1 - 2 цвета, 4 - 16 цветов, 8 - 256 цветов)

   long compression, cmpSize;	// сжатие картинки?


   long xScale, yScale;         // горизонтальное и вертикальное разрешение

   long colors, impColors;      // число используемых цветов

   };



// Установка графического режима 13h

void set_mode (void)

   {

   union REGS regs;        // объявлено в dos.h - регистры

   regs.h.ah = 0;

   regs.h.al = VidMode;

   int86 (0x10, &regs, &regs);

   }



// Установка текстового режимa

void set_text (void)

   {

   union REGS regs;        // объявлено в dos.h - регистры

   regs.h.ah = 0;

   regs.h.al = 0x03;       // номер текстового режима

   int86 (0x10, &regs, &regs);

   }



void set_palette (int color, byte r, byte g, byte b) // устанавление цвета в палитре

   {

   outportb (0x3C8, color);

   outportb (0x3C9, r);

   outportb (0x3C9, g);

   outportb (0x3C9, b);   }



// вывод пиксела установленного цвета в позицию x y

void put_pixel (int x, int y, byte color)

   {

   if (y>=0 && y<MaxY)                     // можно вывести эту точку

      if (x>=0 && x<MaxX)

	 video[y*MaxX+x] = color;    // использование прямого доступа к памяти

   }



// Чтение заголовка pcx файла

void read_pcx_header (FILE *dataFile, pcxHeaderType &pcxHeader)

   {

   fread (&pcxHeader, sizeof (pcxHeaderType), 1, dataFile);

   }



// Вывод pcx файла на экран

int show_pcx (char *name)

   {

   pcxHeaderType pcxHeader;   // структура заголовка

   FILE *dataFile;            // указатель на pcx файл

   byte color, r, g, b,       // установка палитры

   counter, length;           // for RLE (счетчик, длина)

   unsigned int x, y;         // координаты пиксела



   dataFile = fopen (name, "rb");         // открытие картинки

   if (dataFile == NULL) return 4;        // ошибка открытия



   read_pcx_header (dataFile, pcxHeader); // тестирование на ошибки

   if (pcxHeader.bitsPerPixel != 8)       // не поддерживается (8 бит -256 цветов)

      { fclose (dataFile); return 1; }

    else

      cout << "Этот формат PCX не поддерживается" << endl;

   if (pcxHeader.nColorPlanes != 1)// не поддерживается (число цветовых слоев - 1)

      { fclose (dataFile); return 2; }

    else

      cout << "Этот формат PCX не поддерживается" << endl;

   if (pcxHeader.manufacturer != 10)      // ошибка pcx (10 для Paintbrush)

      { fclose (dataFile); return 3; }

    else

      cout << "Ошибка в PCX" << endl;



   fseek (dataFile, -768, SEEK_END);      // начало чтения картинки



   set_mode();                            // установка графического режима



   for (x=0; x<256; x++)                  // чтение палитры

     {

     r = fgetc (dataFile); r = r>>2;

     g = fgetc (dataFile); g = g>>2;

     b = fgetc (dataFile); b = b>>2;

     set_palette (x, r, g, b);

     }



   // начало вывода

   x=0; y=0;                         // верхная левая координата

   fseek (dataFile, 128, SEEK_SET);  // перемещение указателя

   while (y <= pcxHeader.height)    // выводить пока не дойдет до последней строки

      {

      color = fgetc (dataFile);      // чтение байта

      if (color < 192)               // не сжатый?

	 {

	 if (x > pcxHeader.width)    // проверка на переполнение

	    {

	    x = 0;

	    y++;

	    }

	 put_pixel (x++, y, color);  // вывод точки на экран

	 }

      else                           // сжатый

	 {

	 length = color-192;         // определение количества выводимых пикселов

	 color = fgetc (dataFile);   // чтение следующего байта

	 for (counter=0; counter<length; counter++)

	    {

	    if (x > pcxHeader.width) // проверка на переполнение

	       {
		       x = 0;

	       y++;

	       }

	    put_pixel (x++, y, color); // вывод точки на экран

	    }

	 }

      }

   fclose (dataFile);             // закрыть файл

   getch();                       // ждать нажатие любой клавиши

   set_text();                    // установка текстового режима

   return 0;                      // вернуть код ошибки 0 (без ошибки)

   }



// Чтение заголовка bmp файла

void read_bmp_header (FILE *dataFile, bmpHeaderType &bmpHeader)

   {

   fread (&bmpHeader, sizeof (bmpHeaderType), 1, dataFile);

   }



// Вывод bmp файла на экран

int show_bmp (char *name)

   {

   bmpHeaderType bmpHeader;		// структура заголовка

   FILE *dataFile; 			// указатель на файл

   byte r, g, b;                        // красный, зеленый и синий в палитре

   int x, y;				// координаты пиксела

   unsigned int width;			// ширина картинки



   dataFile = fopen (name, "rb");	// открыть файл

   if (dataFile == NULL) return 5;	// если не может открыть



   read_bmp_header (dataFile, bmpHeader);	// тестирование на ошибки

   if (bmpHeader.nPlanes != 1)			// не поддерживается (число цветовых слоев - 1)

      { fclose (dataFile); return 1; }

   else

      cout << "Этот формат BMP не поддерживается" << endl;

   if (bmpHeader.bitsPerPixel != 8) 		// не поддерживается (8 бит -256 цветов)

      { fclose (dataFile); return 2; }

   else

      cout << "Этот формат BMP не поддерживается" << endl;

   if (bmpHeader.compression != 0)    		// не поддерживается

      { fclose (dataFile); return 3; }

   else

      cout << "Этот формат BMP не поддерживается" << endl;

   if (bmpHeader.magic1 != 'B' || bmpHeader.magic2 != 'M')

      {fclose (dataFile); return 4;}		// ошибка bmp

   else

      cout << "Это не формат BMP" << endl;



   fseek (dataFile, 54, SEEK_SET);	// начало чтения картинки



   set_mode();                            // установка графического режима



   for (x=0; x<256; x++)		// чтение палитры

     {

     b = fgetc (dataFile); b = b>>2;	

     g = fgetc (dataFile); g = g>>2;

     r = fgetc (dataFile); r = r>>2;

     set_palette (x, r, g, b);		// установка палитры

     fgetc (dataFile);			// следующий байт

     }



   width = bmpHeader.cols;		// чтение ширины из заголовка

   while (width % 4 != 0) width++;	// пока не кратно 4

   for (y=bmpHeader.rows; y>0; y--)	// до высоты картинки

      for (x=0; x<width; x++)		// до ширины картинки

	 put_pixel (x, y, fgetc(dataFile));	// чтение и вывод



   fclose (dataFile);			// закрытие файла

   getch();				// ждать нажатия клавиши

   set_text();				// возврат в текстовый режим

   return 0;				// вернуть код ошибки 0 (без ошибки)

   }

//Читает имя файла из командной строки, проверяет по расширению к какому типу

//относится и вызывает соответствующую функция просмотра

void main(int argc, char *argv[]) //количество параметров и массив параметров

   {

   char fodrive[MAXDRIVE], fodir[MAXDIR], foname[MAXFILE], foext[MAXEXT];



   if (argc > 1)         //если количество параметров больше 1

      {

      fnsplit(argv[1],fodrive,fodir,foname,foext);

      if (strcmp(strupr(foext),strupr(".pcx")) == 0) //сравнение по расширению

	 show_pcx(argv[1]);                          //берем 2 параметр и выводим

      if (strcmp(strupr(foext),strupr(".bmp")) == 0)

	 show_bmp(argv[1]);                          //берем 2 параметр и выводим

      }

    else

      cout << "Запуск: PCX_BMP.EXE <Имя файла>" << endl; // вывод на экран подсказки

   }





9