program PCXShow; uses crt, dos; type ImgInfoHeader = record { вот это и есть запись. описывающая заголовок} Manufacturer : Byte; Version : Byte; Encoding : Byte; BitsPerPixel : Byte; Xmin, Ymin, Xmax, YMax : Integer; HDPI : Integer; VDPI : Integer; Colormap : array [0..15, 1..3] of Byte; Reserved : Byte; NPlanes : Byte; BytesPerLine : Integer; PaletteInfo : Integer; Filler : array [1..58] of Byte; end; ColType = record R, G, B : Byte; end; PalType = array [0..255] of ColType; {для удобства, палитру будем хранить в массиве} procedure Set13h; {Устанавливаем режим экрана 320x200x256цветов} var Rp : Registers; begin Rp.Ax := $0013; Intr($10, Rp); end; procedure SetText; {Возвращаем текстовый режим} var Rp : Registers; begin Rp.Ax := $0003; Intr($10, Rp); end; procedure PutPixel(x, y : Integer; Color : Byte); {Записываем пиксель в видеопамять} begin Mem[$A000:X+(Y*320)] := Color; end; procedure SetPal(ColorNo : Byte; R, G, B : Byte); {Задаёт цвету за номером ColorNo соответствующие значения RGB} begin Port[$3c8] := ColorNo; Port[$3c9] := R; Port[$3c9] := G; Port[$3c9] := B; end; procedure ShowPCX(x, y : integer; FileName : string); {Собственно сама процедура для вывода PCX} var Img : file; ImgHeader : ImgInfoHeader; x_cur, y_cur : Integer; i, b1, b2 : Byte; Pal : PalType; begin Assign(Img, FileName); {Инициализируем файловую переменную} Reset(Img, 1); {Открываем файл как нетипизированный} BlockRead(Img, ImgHeader, 128); {Считываем заголовок (128 байт!)} Seek(Img, FileSize(Img) - 768); {Находим конец файла и отступаем 768(размер палитры!) байт назад} BlockRead(Img, Pal, 768); {Считываем палитру} for i := 0 to 255 do {Для каждого из 256 цветов выполняем:} with Pal[i] do begin R := R shr 2; {shr 2 - это сдвиг всех битов в переменной на 2 позиции вправо} G := G shr 2; {это аналогично целочисленному делению на 4} B := B shr 2; {В файле значения R,G,B лежат в диапазоне 0..255. Зачем делить? Смотри ниже.} SetPal(i, R, G, B); {Устанавливаем цвет. Вот здесь значения RGB должны быть 0..63. Затем и делили} end; Seek(Img, 128); {Устанавливаем указатель сразу после заголовка} x_cur := 0; y_cur := 0; {Это координаты текущей точки рисунка} while y_cur < ImgHeader.VDPI do {Выполняем, пока координата y_cur меньше высоты рисунка} begin BlockRead(Img, b1, 1); {Читаем байт} if ((b1 and $c0) = $c0) then {Это мы так мудрёно проверяем, установлены ли 2 старших бита} begin {Если установлены, значит младшие 6 младших битов содержат значение, } {указывающее, сколко раз следующий байт должен быть выведен на экран} BlockRead(Img, b2, 1); {Считываем этот самый следующиий байт} for i := 1 to (b1 and $3f) do {b1 and $3f - 'это мы получаем значение из младших 6 битов} begin PutPixel(x + x_cur, y + y_cur, b2); {Выводим пиксель} Inc(x_cur); {Увеличиваем x_cur} if x_cur > ImgHeader.HDPI - 1 then {Если x_cur больше ширины рисунка, значит} begin x_cur := 0; {x_cur в ноль} Inc(y_cur); {y_cur увеличиваем} end; end; end else begin {Если не установлены, значит просто выводим пиксель на экран} PutPixel(x + x_cur, y + y_cur, b1); Inc(x_cur); if x_cur > ImgHeader.HDPI - 1 then begin x_cur := 0; Inc(y_cur); end; end; end; Close(Img); {закрыли файл..............Уффф...Всё! :)} end; begin Set13h; ShowPCX(1, 1, '001.pcx');{} ReadKey; SetText; end.