Следующим шагом происходит считывание растровые данные из файла. Как только строка со значениями пикселов прочитана из файла, она в функции put_pixel передается в видео-буфеp для получения изображения на экране.
2.3. Используемые переменные и функции.
typedefunsignedcharbyte
Объявление типа.
char far *video = (char far *) 0xA0000000L
Указатель на видеопамять.
intMaxX, MaxY
Максимальное разрешение экрана.
VidMode=0x13
Гафический режим 13h.
1.3.2. Основные функции и процедуры
structpcxHeaderType
Структура заголовка файла PCX.
struct bmpHeaderType
Структура заголовка файла BMP.
voidset_mode (void)
Установка графического режима 13h.
voidset_text (void)
Установкатекстовогорежимa.
void set_palette (int color, byte r, byte g, byte b)
Установление цвета в палитре.
voidput_pixel (intx, inty, bytecolor)
Вывод пиксела установленного цвета в позицию 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[])
Читает имя файла из командной строки, проверяет по расширению к какому типу файлов он относится и вызывает соответствующую функция просмотра.
Программа является консольным приложением и функционирует под управлением операционной системы MSDOS или её эмуляции («Сеанс MSDOS» в Windows’е).
Запуск программы производится из окна файлового менеджера, либо из командной строки, и имеет следующий синтаксис:
PCX_BMP.EXE <имя графического файла>[PCX]/[BMP]
Примеры:
PCX_BMP.EXETEST.PCX
PCX_BMP.EXETEST.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.
Листинг программы “Просмотрщик графических файлов”.
#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
{
charmanufacturer; // всегда 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
structbmpHeaderType
{
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, ®s, ®s);
}
// Установка текстового режимa
void set_text (void)
{
union REGS regs; // объявленов dos.h - регистры
regs.h.ah = 0;
regs.h.al = 0x03; // номер текстового режима
int86 (0x10, ®s, ®s);
}
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; // координаты пиксела
unsignedintwidth; // ширина картинки
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; // вывод на экран подсказки
}