Работа с графическими образами на диске




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

Мы уже рассматривали, каким образом можно получить копию изображения с экрана на принтере (см. разд. 19.6.1). Теперь {520} попробуем записать изображение с экрана на диск. Казалось бы просто — достаточно немного изменить процедуру CopyToPrint. Однако при таком подходе место на диске будет расходоваться неэкономно: в каждом байте старшие четыре (как минимум) бита не используются. Исключение составляют все режимы с количеством цветов 256 и более (VGA, MCGA, IBM8514). Чтобы не заботиться об этом, можно воспользоваться функцией ImageSize (см. разд. 19.6.1) — она возвращает размер картинки в байтах, уже учтя все нюансы ее расположения в ОЗУВ. Воспользовавшись затем процедурой GetImage, можно сохранить изображение на диске (рис. 22.11).

USES Graph; {$I initgraf.pas} {процедура инициализации (см. гл. 19) } { Процедура записи на диск картинки с экрана. } { Максимальный размер 640x200 при 16 цветах. } PROCEDURE SaveScreen(X1, Y1 { координаты картинки } X2, Y2: Word; FileName: String); { имя файла картинки } VAR PicFile: File; { бестиповый файл } size:Word; { размер файла } dataptr: Pointer; { указатель на буфер } BEGIN Size:= ImageSize(X1,Y1, X2, Y2); { размер картинки } GetMem(dataptr, size); { выделение памяти } GetImage(X1,Y1,X2,Y2,dataptr^); { картинку – в буфер } Assign(PicFile, FileName); { Открытие файла для } Rewrite(PicFile, size); { записи картинки. } BlockWrite(PicFile,dataptr^,1); { запись картинки } Close(PicFile); { закрытие файла } FreeMem(dataptr, size) { освобождение кучи } END; BEGIN { Пример вызова процедуры } GrInit; SetFillStyle(1,15); Bar(0, 0, GetMaxX, GetMaxY); SetFillStyle(2, 2); Bar(40, 40, GetMaxX-40, GetMaxY-40); SetFillStyle(3, 3); Bar(120, 120, GetMaxX-120, GetMaxY-120); SetFillStyle(4, 4);Bar(240, 180, GetMaxX-240, GetMaxY-180); ReadLn; SaveScreen(70,70, GetMaxX-70, GetMaxY-70, 'graph.scr'); CloseGraph END.

Рис. 22.11 {521}

А с помощью процедуры PutImage можно восстановить это изображение (рис. 22.12).

USES Graph; {$I initgraf.pas} {процедура инициализации (см. гл. 19) } {Процедура вывода на экран картинки, записанной на диск. } {Максимальный размер - экран в режиме 640x200, 16 цветов. } PROCEDURE LoadScreen(X,Y:Word; { координаты левого верх- } { него угла картинки } FileName: String; { имя файла картинки } Put: Word); { режим вывода на экран } VAR PicFile:File; { бестиповый файл } size: Word; { размер файла в байтах } dataptr: Pointer; { указатель на начало } BEGIN Assign(PicFile, FileName); { Открытие файла для } Reset(PicFile, 1); { чтения по одному байту. } size:= FileSize(PicFile); { размер файла в байтах } Reset(PicFile, size); { смена буфера файла } GetMem(dataptr, size); { выделение памяти } BlockRead(PicFile,dataptr^,1); { чтение картинки } PutImage(X,Y,dataptr^,put); { вывод картинки на экран } Close(PicFile); { закрытие файла } FreeMem(dataptr, size) { освобождение памяти } END; BEGIN { Пример вызовов процедуры } GrInit; LoadScreen(0, 0, 'graph.scr', XORPut); LoadScreen(20, 20, 'graph.scr', XORPut); LoadScreen(40, 40, 'graph.scr', XORPut); LoadScreen(60, 60, 'graph.scr', XORPut }; LoadScreen(80, 80, 'graph.scr', XORPut); ReadLn; CloseGraph END.

Рис. 22.12

При таком способе сохранения изображений существует ограничение на их размер. Это связано с тем, что функция ImageSize возвращает результат типа Word. Таким образом, картинка не должна занимать в памяти больше 65520 байт. Для адаптера EGA, {522} например, полностью весь экран можно записать на диск максимум в режиме 640x200, 16 цветов — это займет 64004 байта. Кроме того, если размеры картинки таковы, что она полностью не сможет поместиться на экран, то выводиться на него при чтении с диска она не будет.

У такого способа записи изображений есть одно удобное свойство: в каком бы графическом режиме картинка не была записана, она всегда сможет быть прочитана и показана в любом другом графическом режиме.

Другой способ сохранения и чтения картинок основан на знании устройства и работы графических адаптеров: каждая цветовая плоскость сохраняется в отдельном файле. При таком способе работы ограничений на размер картинки практически нет (рис. 22.13).

USES Graph; {$I initgraf.pas} {процедура инициализации (см. гл. 19) } TYPE g_plan=Array [1..38400] of Byte; { массив-плоскость } {Процедура сохранения изображения всего экрана на диске. Для каждой битовой плоскости создается отдельный файл. Параметр file_name - имя файла без расширения. } PROCEDURE SaveBitPlanes(file name: String); VAR scr_buf:Pointer; { указатель на буфер данных } scr_arr:g_plan absolute $A000:$0; { память адаптера } plen,mx,my:LongInt; { размер плоскости } { Вложенная процедура записи плоскости на диск } PROCEDURE WriteBlk(name: String); VAR image_file: File; BEGIN Assign(image_file, name); Rewrite(image_fite, plen); BlockWrite(image_file, scr_buf^, 1); Close(image file) END; BEGIN mx:= GetMaxX+1; my:= GetMaxY+1; { размеры плоскости }

Рис. 22.13 {523}

plen:= mx*my div 8; { получение длины буфера } GetMem(scr_buf, plen); { память для буфера } Port[$3CE]:=4; Port[$3CF]:=0; { чтение плоскости Blue } Move(scr_arr,scr_buf^,plen); { копирование ее в буфер } WriteBlk(file_name+'.blu'); { запись буфера на диск } Port[$3CE]:=4; Port[$3CF]:=1; { чтение плоскости Green } Move(scr_arr,scr_buf^,plen); { копирование ее в буфер } WriteBlk(file_name+'.grn'}; { запись буфера на диск } Port[$3CE]:=4; Port[$3CF]:=2; { чтение плоскости Red } Move(scr_arr,scr_buf^,plen); { копирование ее в буфер } WriteBlk(file name+'. red'); { запись буфера на диск } Port[$3CE]:=4; Port[$3CF]:=3; { плоскость яркости } Move(scr_arr,scr_buf^,plen); { копирование ее в буфер } WriteBlk(file_name+'.int'); { запись буфера на диск } FreeMem(scr_buf, plen); { освобождение памяти } Port[$3CE]:=4; Port[$3CF]:=0; { восстановление портов } END; {Процедура чтения файлов изображения и вывода их на экран. Параметр file_name - hmz файла без расширения. } PROCEDURE LoadBitPlanes(file_name: String); VAR scr_buf:Pointer; { указатель на буфер данных } scr_arr:g_plan absolute $A000:$0; { память адаптера } plen,mx,my:LongInt; { размер плоскости } { Вложенная процедура чтения плоскости с диска } PROCEDURE ReadBlk(name: String); VAR image file: File; BEGIN Assign(image.file, name); Reset(image_file, plen); BlockRead(image_file, scr_buf^, 1); Close(image_file) END; BEGIN mx:=GetMaxX+1; my:=GetMaxY+1; {размеры плоскости } plen:= mx*my div 8; {получение длины буфера } GetMem(scr_buf, plen); {память для буфера } ReadBlk(file_name+'.blu'); {чтение с диска в буфер } Port[$3C4]:=2; Port[$3C5]:=1; {Буфер копируется } Move(scr_buf^,scr_arr,plen); {в плоскость Blue. } ReadBlk(file_name+'.grn'); {чтение с диска в буфер }

Рис. 22.13 (продолжение) {524}

Port[$3C4]:=2; Port[$3C5]:=2; { Буфер копируется } Move(scr_buf^,scr_arr,plen); { в плоскость Green. } ReadBlk(file_name+'.red'); { чтение с диска в буфер } Port[$3C4]:=2; Port[$3C5]:=4; { Буфер копируется } Move(scr_buf^,scr_arr,plen); { в плоскость Red. } ReadBlk(file_name+'.int'); { чтение с диска в буфер } Port[$3C4]:=2; Port[$3C5]:=8; { Буфер копируется } Move(scr_buf^,scr_arr,plen); { в плоскость яркости. } FreeMem(scr_buf, plen); { освобождение памяти } Port[$3C4]:=2;Port[$3C5]:=15; { восстановление портов } END; BEGIN { Пример вызовов процедур } GrInit; SetFillStyle(1,15); Bar(0, 0, GetMaxX, GetMaxY); SetFillStyle(2, 2); Bar(40, 40,GetMaxX-40, GetMaxY-40); SetFillStyle(3,3); Bar(120,120, GetMaxX-120, GetMaxY-120); SetFillStyle(4,4); Bar(240,180, GetMaxX-240, GetMaxY-180); ReadLn; SaveBitPlanes('plane'); ClearDevice; ReadLn; LoadBitPlanes('plane'); ReadLn; CloseGraph END.

Рис. 22.13 (окончание)

Эти процедуры работают для всех режимов, кроме CGA (так как в нем другой способ хранения данных). Поэтому для него приведем отдельные процедуры (рис. 22.14).

USES Graph; TYPE g_plan=Array [1..16384] of Byte; { массив двух блоков } {Процедура сохранения изображения всего экрана на диске } { для адаптеров, работающих в режиме CGA. } PROCEDURE SaveCGAScr(file_name:String); {полное имя файла } VAR image_file: File; scr_buf: Pointer; { ссылка на буфер } scr_addr:g_plan absolute $B800:0; { память адаптера } plen, mx, my: LongInt; { размер плоскости }

Рис. 22.14 {525}

BEGIN mx:= GetMaxX+1; my:= GetMaxY+1; { размеры плоскости } if GetGraphMode = CGAHi { размер буфера: } then plen:= mx*my div 8 + 384 { один бит на точку } else { или } plen:= mx*my div 4 + 384; { два бита на точку } GetMem(scr_buf, plen); { выделение памяти } Assign(image_file, file_name); { связь файлов } Rewrite(image_file, plen); { открытие файла } Move(scr_addr, scr_buf^, plen); { экран – в буфер } BlockWrite(image_file,scr_buf^,1); { запись его в файл } Close(image_file); { закрытие файла } FreeMem(scr_buf, plen) { удаление буфера } END; { Процедура чтения изображения с диска и вывода его на } { экран для адаптеров, работающих в режиме CGA } PROCEDURE LoadCGAScr(file_name:String); {полное имя файла } VAR image_file: File; scr_buf: Pointer; { ссылка на буфер } scr_addr:g_plan absolute $8800:0; { память адаптера } plen,mx,my: LongInt; { размер плоскости } BEGIN mx:= GetMaxX+1; my:= GetMaxY+1; { размеры плоскости } if GetGraphMode = CGAHi { размер буфера: } then plen:= mx*my div 8 + 384 { один бит на точку } else { или } plen:= mx*my div 4 + 384; { два бита на точку } GetMem(scr_buf, plen); { отводится память } Assign(image_file, file_name); { связь файлов } Reset(image_file, plen); { открытие файла } BlockRead(image_file,scr_buf^,1); { чтение картинки } Close(image.file); { закрытие файла } Move(scr_buf^,scr_addr, plen); { буфер – на экран } FreeMem(scr buf, plen) { удаление буфера } END;

Рис. 22.14 (окончание)

Подобный способ хранения изображений используется в некоторых графических пакетах программ (PBrush, DrHALO). Однако формат записи, используемый в них, другой. Поэтому они не совместимы ни между собой, ни с другими графическими пакетами. {526}

ПРИЛОЖЕНИЕ 1



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-01 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: