Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ИГС / Lab_02 / labor_02pm.doc
Скачиваний:
10
Добавлен:
17.04.2018
Размер:
699.9 Кб
Скачать

Графические вставки из bmp-файлов в dos программах в режиме работы с видеостраницами.

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

Чтобы картину, полученную из bmp-файла выводить то на одну то на другую видеостраницу, необходимо эту картину где-то хранить. Для хранения будем использовать оперативную память.

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

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

Поместим этот код в класс ScreenMemory, и пусть этот класс находится в файлеclassmem.cpp. Ниже приводится определение этого класса.

//класс для чтения изображения с экрана в оперативную память

//и затем вывода этого изображения на экран

class ScreenMemory

{

public:

int xBlk, yBlk;

//конструктор

ScreenMemory(int hx0, int hy0, int x1, int y1, int x2, int y2);

void ViewScreen(); //выводим изображение на экран

~ScreenMemory(); //деструктор

private:

int *xp, *yp;

void ***saucer;

int *hx, *hy;

double **size;

};

//конструктор, копирует часть изображения с экрана в

//оперативную память по блочно

//hx0, hy0 - размеры блоков для записи изображения в память

//x1,y1,x2,y2 - размеры копируемой части изображения на экране

ScreenMemory::ScreenMemory(int hx0, int hy0,

int x1, int y1, int x2, int y2)

{

xBlk = (x2 - x1)/hx0;

yBlk = (y2 - y1)/hy0;

//если выбранные блоки не полностью покрывают изображение на экране

//то вводятся дополнительные блоки с размерами dxBlk, dyBlk

int dxBlk = (x2 - x1) - xBlk*hx0;

int dyBlk = (y2 - y1) - yBlk*hy0;

int xflag = 0, yflag = 0;

//находим число блоков полностью закрывающих экран

if(dxBlk>0)

{

xBlk++; xflag = 1;

}

if(dyBlk>0)

{

yBlk++; yflag = 1;

}

//выделяем память под массив шагов между блоками по горизонтали

hx = new int[xBlk];

if(hx == NULL)

{

closegraph();

printf("Error of allocation of memory - hx");

exit(1);

}

//выделяем память под массив шагов между блоками по вертикали

hy = new int[yBlk];

if(hy == NULL)

{

closegraph();

printf("Error of allocation of memory - hy");

exit(1);

}

//вычисляем массив шагов между блоками по горизонтали

for(int i=0; i<xBlk; i++)

{

if((xflag == 1) && (i == xBlk-1))

hx[i] = dxBlk;

else

hx[i] = hx0;

}

//вычисляем массив шагов между блоками по вертикали

for(int j=0; j<yBlk; j++)

{

if((yflag == 1) && (j == yBlk-1))

hy[j] = dyBlk;

else

hy[j] = hy0;

}

//выделяем память под массив узловых точек между блоками по горизонтали

xp = new int[xBlk+1];

if(xp == NULL)

{

closegraph();

printf("Error of allocation of memory - xp");

exit(1);

}

//выделяем память под массив узловых точек между блоками по вертикали

yp = new int[yBlk+1];

if(yp == NULL)

{

closegraph();

printf("Error of allocation of memory - yp");

exit(1);

}

//вычисляем массив узловых точек между блоками по горизонтали

xp[0] = x1;

for( i=1; i<=xBlk; i++)

xp[i] = xp[i-1] + hx[i-1];

//вычисляем массив узловых точек между блоками по вертикали

yp[0] = y1;

for( j=1; j<=yBlk; j++)

yp[j] = yp[j-1] + hy[j-1];

//выделяем память под двойной массив размеров блоков

size = new double* [xBlk];

if(size == NULL)

{

closegraph();

printf("Error of allocation of memory -size");

exit(1);

}

for(i=0; i<xBlk; i++)

{

size[i] = new double[yBlk];

if(size[i] == NULL)

{

closegraph();

printf("Error of allocation of memory -size");

exit(1);

}

}

//выделяем память под двойной массив указателей адресов блоков

saucer = new void** [xBlk];

if(saucer == NULL)

{

closegraph();

printf("Error of allocation of memory -*sauser");

exit(1);

}

for(i=0; i<xBlk; i++)

{

saucer[i] = new void* [yBlk];

if(saucer[i] == NULL)

{

closegraph();

printf("Error of allocation of memory -*sauser");

exit(1);

}

}

for( j=0; j<yBlk; j++)

for(int i=0; i<xBlk; i++)

{

//вычисляем размер блока [i][j]

size[i][j] = imagesize(xp[i], yp[j], xp[i+1],yp[j+1]);

//выделяем память под блок [i][j]

saucer[i][j] = new [size[i][j]];

if(saucer[i][j] == NULL)

{

closegraph();

printf("Error of allocation of memory - saucer[i][j]");

exit(1);

}

//копируем блок изображения в блок памяти

getimage(xp[i], yp[j], xp[i+1],yp[j+1], saucer[i][j]);

}

}

//функция выводит изображение из памяти на экран по блочно

void ScreenMemory::ViewScreen()

{

for(int j=0; j<yBlk; j++)

for( int i=0; i<xBlk; i++)

{

putimage(xp[i], yp[j], saucer[i][j], COPY_PUT);

}

}

//деструктор, освобождает выделенную память

ScreenMemory::~ScreenMemory()

{

//освобождаем память, занятую блоками [i][j]

for(int j=0; j<yBlk; j++)

for( int i=0; i<xBlk; i++)

delete saucer[i][j];

//освобождаем память, занятую массивами hx[] hy[]

delete [] hx;

delete [] hy;

//освобождаем память, занятую массивами xp[] yp[]

delete [] xp;

delete [] yp;

//освобождаем память, занятую массивом size[][]

for(int i=0; i<xBlk; i++)

delete [] size[i];

delete [] size;

//освобождаем память, занятую массивом saucer[][]

for(i=0; i<xBlk; i++)

delete [] saucer[i];

delete [] saucer;

}

Возьмем, за основу, программу mov05DOS.cpp, В этой программе моделируется движение самолета и вращающейся стрелки. Уберем стрелку, уберем фон в виде зеленого эллипса. В качестве фона будем использовать картину зеленого поля и голубого неба изbmp-файлаfield_16.bmp. Новую программу назовемmov08DOS.cpp.

В заголовке файла добавим две строчки.

#include "view.cpp"

#include "classmem.cpp"

В главной функции main() добавим следующую строчку вызова функцииViewBMP().

ViewBMP("field_16.bmp");

Уберем строчки вызова стрелки, траектории стрелки, фона.

Далее создадим объект класса ScreenMemory.

//копируем часть изображения в оперативную память по блокам 300x200

ScreenMemory ScMem(300,200,0,0,630,326);

Вызываем функцию ViewScreen()для объекта ScMem.

//копируем изображение из памяти на экран

ScMem.ViewScreen();

Компилируем, запускаем программу mov08DOS.exe, и результат работы этой программы показан на Рис.36.

Рис. 36.

Результат работы программы mov08DOS.cpp.

Соседние файлы в папке Lab_02