home *** CD-ROM | disk | FTP | other *** search
/ PC Media 23 / PC MEDIA CD23.iso / share / prog / dclib500 / pcxunit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-12-20  |  10.6 KB  |  627 lines

  1. {$R-}    {Range checking off}
  2. {$B-}    {Boolean complete evaluation off}
  3. {$S-}    {Stack checking off}
  4. {$I+}    {I/O checking on}
  5. {$N-}    {No numeric coprocessor}
  6.  
  7. unit PCXUNIT;
  8.  
  9. INTERFACE
  10.  
  11. uses
  12.   Crt, Dos;
  13.  
  14. const
  15.    MAX_WIDTH = 4000;
  16.    COMPRESION_NUM = $C0;
  17.    MAX_BLOCK = 4096;
  18.  
  19.    RED = 0;
  20.    GREEN = 1;
  21.    BLUE = 2;
  22.  
  23.    CGA4 = $04;
  24.    CGA2 = $06;
  25.    EGA  = $10;
  26.    VGA  = $12;
  27.    MCGA = $13;
  28.  
  29. type
  30.    str80 = string [80];
  31.    file_buffer = array [0..127] of byte;
  32.    block_array = array [0..MAX_BLOCK] of byte;
  33.    pal_array = array [0..255, RED..BLUE] of byte;
  34.    ega_array = array [0..16] of byte;
  35.    line_array = array [0..MAX_WIDTH] of byte;
  36.  
  37.    pcx_cabeza = record
  38.         Manufacturer: byte;
  39.  
  40.         Version: byte;
  41.  
  42.         Encoding: byte;
  43.  
  44.         Bits_per_pixel: byte;
  45.  
  46.         Xmin: integer;
  47.         Ymin: integer;
  48.         Xmax: integer;
  49.         Ymax: integer;
  50.  
  51.         Hdpi: integer;
  52.         Vdpi: integer;
  53.  
  54.         ColorMap: array [0..15, RED..BLUE] of byte;
  55.  
  56.         Reserved: byte;
  57.  
  58.         Nplanes: byte;
  59.  
  60.         Bytes_per_line_per_plane: integer;
  61.  
  62.         PaletteInfo: integer;
  63.  
  64.         HscreenSize: integer;
  65.         VscreenSize: integer;
  66.  
  67.         Filler: array [74..127] of byte;
  68.         end;
  69.  
  70. var
  71.    Name: str80;
  72.    ImageName: str80;
  73.    BlockFile: file;
  74.    BlockData: block_array;
  75.  
  76.    Cabeza: pcx_cabeza;
  77.    Palette256: pal_array;
  78.    PaletteEGA: ega_array;
  79.    PCXline: line_array;
  80.  
  81.    Ymax: integer;
  82.    NextByte: integer;
  83.    Index: integer;
  84.    Data: byte;
  85.  
  86.    PictureMode: integer;
  87.    Reg: Registers;
  88.  
  89.  
  90.    PROCEDURE ERROR (S:STR80);
  91.    PROCEDURE READERROR(MSG:INTEGER);
  92.    PROCEDURE VIDEOMODE(N:INTEGER);
  93.    PROCEDURE EGAPALETTE(N,R,G,B:INTEGER);
  94.    PROCEDURE VGAPALETTE(N,R,G,B:INTEGER);
  95.    PROCEDURE EGA16PALETTE;
  96.    PROCEDURE VGA16PALETTE;
  97.    PROCEDURE ENTIREVGAPALETTE;
  98.    PROCEDURE SETPALETTE;
  99.    PROCEDURE SHOWCGA(Y:INTEGER);
  100.    PROCEDURE SHOWEGA(Y:INTEGER);
  101.    PROCEDURE SHOWMCGA(Y:INTEGER);
  102.    PROCEDURE READ256PALETTE;
  103.    PROCEDURE READHEADER;
  104.    PROCEDURE READBYTE;
  105.    PROCEDURE READ_PCX_LINE;
  106.    PROCEDURE READ_PCX (NAME:STR80);
  107.    PROCEDURE DISPLAY_PCX(NAME:STR80);
  108.    PROCEDURE VERPCX(NAME:STR80);
  109.  
  110. IMPLEMENTATION
  111.  
  112. procedure Error (s: str80 );
  113.  
  114. var c: char;
  115.     i: integer;
  116.  
  117. begin
  118. TextMode (C80);
  119. writeln ('ERROR');
  120. writeln (s);
  121. halt;
  122. end;
  123.  
  124.  
  125. procedure ReadError (msg: integer);
  126.  
  127. begin
  128. if IOresult <> 0 then
  129.    case msg of
  130.    1: Error ('No puedo abrir el fichero - ' + ImageName);
  131.    2: Error ('Error cerrando fichero - ' + ImageName + ' - el disco debe de estar lleno');
  132.    3: Error ('Error leyendo fichero - ' + ImageName);
  133.  
  134.    else
  135.       Error ('Error haciendo I/O en fichero - ' + ImageName);
  136.    end;
  137. end;
  138.  
  139.  
  140. procedure VideoMode (n: integer);
  141.  
  142.  
  143. begin
  144. Reg.ah := $00;
  145. Reg.al := n;
  146. intr ($10, Reg);
  147. end;
  148.  
  149.  
  150.  
  151. procedure EGApalette (n, R, G, B: integer);
  152.  
  153. var i: integer;
  154.  
  155. begin
  156. R := R shr 6;
  157. G := G shr 6;
  158. B := B shr 6;
  159. i := (R shl 4) + (G shl 2) + B;
  160.  
  161. Reg.ah := $10;
  162. Reg.al := 0;
  163. Reg.bh := i;
  164. Reg.bl := n;
  165. intr ($10, Reg);
  166. end;  { EGApalette }
  167.  
  168.  
  169. procedure VGApalette (n, R, G, B: integer);
  170.  
  171. begin
  172. R := R shr 2;
  173. G := G shr 2;
  174. B := B shr 2;
  175.  
  176. Reg.ah := $10;
  177. Reg.al := $0;
  178. Reg.bl := n;
  179. Reg.bh := n;
  180. intr ($10, Reg);
  181.  
  182. Reg.ah := $10;
  183. Reg.al := $10;
  184. Reg.bx := n;
  185. Reg.dh := R;
  186. Reg.ch := G;
  187. Reg.cl := B;
  188. intr ($10, Reg);
  189. end;
  190.  
  191.  
  192. procedure EGA16palette;
  193.  
  194. var
  195.    i, r, g, b: integer;
  196.  
  197. begin
  198. for i := 0 to 15 do
  199.    begin
  200.    r := Cabeza.ColorMap [i, RED]   shr 6;
  201.    g := Cabeza.ColorMap [i, GREEN] shr 6;
  202.    b := Cabeza.ColorMap [i, BLUE]  shr 6;
  203.    PaletteEGA [i] := (r shl 4) + (g shl 2) + b;
  204.    end;
  205. PaletteEGA [16] := 0;
  206.  
  207. Reg.ah := $10;
  208. Reg.al := $02;
  209. Reg.dx := ofs (PaletteEGA);
  210. Reg.es := seg (PaletteEGA);
  211. intr ($10, Reg);
  212.  
  213. end;
  214.  
  215.  
  216. procedure VGA16palette;
  217.  
  218. var
  219.    i: integer;
  220.  
  221. begin
  222. for i := 0 to 15 do
  223.    PaletteEGA [i] := i;
  224. PaletteEGA [16] := 0;
  225.  
  226. Reg.ah := $10;
  227. Reg.al := $02;
  228. Reg.dx := ofs (PaletteEGA);
  229. Reg.es := seg (PaletteEGA);
  230. intr ($10, Reg);
  231.  
  232. for i := 0 to 15 do
  233.    begin
  234.    Palette256 [i, RED]   := Cabeza.ColorMap [i, RED]   shr 2;
  235.    Palette256 [i, GREEN] := Cabeza.ColorMap [i, GREEN] shr 2;
  236.    Palette256 [i, BLUE]  := Cabeza.ColorMap [i, BLUE]  shr 2;
  237.    end;
  238.  
  239. Reg.ah := $10;
  240. Reg.al := $12;
  241. Reg.bx := 0;
  242. Reg.cx := 255;
  243. Reg.dx := ofs (Palette256);
  244. Reg.es := seg (Palette256);
  245. intr ($10, Reg);
  246.  
  247. end;
  248.  
  249.  
  250. procedure EntireVGApalette;
  251.  
  252. var
  253.    i: integer;
  254.  
  255. begin
  256. for i := 0 to 255 do
  257.    begin
  258.    Palette256 [i, RED]   := Palette256 [i, RED]   shr 2;
  259.    Palette256 [i, GREEN] := Palette256 [i, GREEN] shr 2;
  260.    Palette256 [i, BLUE]  := Palette256 [i, BLUE]  shr 2;
  261.    end;
  262.  
  263. Reg.ah := $10;
  264. Reg.al := $12;
  265. Reg.bx := 0;
  266. Reg.cx := 255;
  267. Reg.dx := ofs (Palette256);
  268. Reg.es := seg (Palette256);
  269. intr ($10, Reg);
  270.  
  271. end;
  272.  
  273.  
  274. procedure SetPalette;
  275.  
  276. var i: integer;
  277.  
  278. begin
  279. if PictureMode = MCGA then
  280.    EntireVGApalette
  281. else if PictureMode = VGA then
  282.    VGA16palette
  283. else
  284.    EGA16palette;
  285. end;
  286.  
  287.  
  288. procedure ShowCGA (Y: integer);
  289.  
  290. var
  291.    i, j, l, m, t: integer;
  292.    Yoffset: integer;
  293.    CGAScreen: array [0..32000] of byte absolute $B800:$0000;
  294.  
  295. begin
  296. i := 8 div Cabeza.Bits_per_pixel;
  297.  
  298. if (i = 8) then
  299.    j := 7
  300. else
  301.    j := 3;
  302.  
  303. t := (Cabeza.Xmax - Cabeza.Xmin + 1);
  304. m := t and j;
  305.  
  306. l := (t + j) div i;
  307. if l > 80 then
  308.    begin
  309.    l := 80;
  310.    m := 0;
  311.    end;
  312.  
  313. if (m <> 0) then
  314.    begin
  315.    m := $FF shl (8 - (m * Cabeza.Bits_per_pixel));
  316.    t := l - 1;
  317.    PCXline [t] := PCXline [t] and m;
  318.    end;
  319.  
  320. Yoffset := 8192 * (Y and 1);
  321. Move (PCXline [0], CGAScreen [((Y shr 1) * 80) + Yoffset], l);
  322.  
  323. end;
  324.  
  325.  
  326. procedure ShowEGA (Y: integer);
  327.  
  328.  
  329. var
  330.    i, j, l, m, t: integer;
  331.    EGAplane: integer;
  332.    EGAscreen: array [0..32000] of byte absolute $A000:$0000;
  333.  
  334. begin
  335. EGAplane := $0100;
  336. PortW [$3CE] := $0005;
  337.  
  338.  
  339. t := (Cabeza.Xmax - Cabeza.Xmin + 1);
  340. m := t and 7;
  341.  
  342. l := (t + 7) shr 3;
  343. if (l >= 80) then
  344.    begin
  345.    l := 80;
  346.    m := 0;
  347.    end;
  348.  
  349. if (m <> 0) then
  350.    m := $FF shl (8 - m)
  351. else
  352.    m := $FF;
  353.  
  354. for i := 0 to Cabeza.Nplanes-1 do
  355.    begin
  356.    j := i * Cabeza.Bytes_per_line_per_plane;
  357.    t := j + l - 1;
  358.    PCXline [t] := PCXline [t] and m;
  359.  
  360.    PortW [$3C4] := EGAplane + 2;
  361.    Move (PCXline [j], EGAscreen [Y * 80], l);
  362.    EGAplane := EGAplane shl 1;
  363.    end;
  364.  
  365. PortW [$3C4] := $0F02;
  366. end;
  367.  
  368.  
  369. procedure ShowMCGA (Y: integer);
  370.  
  371.  
  372. var
  373.    l: integer;
  374.    MCGAscreen: array [0..64000] of byte absolute $A000:$0000;
  375.  
  376. begin
  377. l := Cabeza.XMax - Cabeza.Xmin;
  378. if l > 320 then
  379.    l := 320;
  380.  
  381. Move (PCXline [0], MCGAScreen [Y * 320], l);
  382.  
  383. end;
  384.  
  385.  
  386. procedure Read256palette;
  387.  
  388.  
  389. var
  390.    i: integer;
  391.    b: byte;
  392.  
  393. begin
  394. seek (BlockFile, FileSize (BlockFile) - 769);
  395. BlockRead (BlockFile, b, 1);
  396. ReadError (3);
  397.  
  398. if b <> 12 then
  399.    exit;
  400.  
  401. BlockRead (BlockFile, Palette256, 3*256);
  402. ReadError (3);
  403.  
  404. seek (BlockFile, 128);
  405.  
  406. end;
  407.  
  408.  
  409. procedure ReadHeader;
  410.  
  411. label WrongFormat;
  412.  
  413. begin
  414. {$I-}
  415. BlockRead (BlockFile, Cabeza, 128);
  416. ReadError (3);
  417.  
  418.  
  419. if (Cabeza.Manufacturer <> 10) or (Cabeza.Encoding <> 1) then
  420.    begin
  421.    close (BlockFile);
  422.    Error ('Este fichero no es una imagen PCX válida.');
  423.    end;
  424.  
  425. if (Cabeza.Nplanes = 4) and (Cabeza.Bits_per_pixel = 1) then
  426.    begin
  427.    if (Cabeza.Ymax - Cabeza.Ymin) <= 349 then
  428.       begin
  429.       PictureMode := EGA;
  430.       Ymax := 349;
  431.       end
  432.    else
  433.       begin
  434.       PictureMode := VGA;
  435.       Ymax := 479;
  436.       end;
  437.    end
  438. else if (Cabeza.Nplanes = 1) then
  439.    begin
  440.    Ymax := 199;
  441.  
  442.    if (Cabeza.Bits_per_pixel = 1) then
  443.       PictureMode := CGA2
  444.    else if (Cabeza.Bits_per_pixel = 2) then
  445.       PictureMode := CGA4
  446.    else if (Cabeza.Bits_per_pixel = 8) then
  447.       begin
  448.       PictureMode := MCGA;
  449.       if Cabeza.Version = 5 then
  450.          Read256palette;
  451.       end
  452.    else
  453.       goto WrongFormat;
  454.    end
  455. else
  456.    begin
  457. WrongFormat:
  458.    close (BlockFile);
  459.    Error ('Fichero PCX esta en un formato incorrecto - Requiere CGA, EGA, VGA, o MCGA');
  460.    end;
  461.  
  462. Index := 0;
  463. NextByte := MAX_BLOCK;
  464.  
  465. end;
  466.  
  467.  
  468.  
  469. procedure ReadByte;
  470.  
  471.  
  472. var
  473.    NumBlocksRead: integer;
  474.  
  475. begin
  476. if NextByte = MAX_BLOCK then
  477.    begin
  478.    BlockRead (BlockFile, BlockData, MAX_BLOCK, NumBlocksRead);
  479.    NextByte := 0;
  480.    end;
  481.  
  482. data := BlockData [NextByte];
  483. inc (NextByte);
  484. end;  { ReadByte }
  485.  
  486.  
  487.  
  488. procedure Read_PCX_Line;
  489.  
  490. var
  491.    count: integer;
  492.    bytes_per_line: integer;
  493.  
  494. begin
  495. {$I-}
  496.  
  497. bytes_per_line := Cabeza.Bytes_per_line_per_plane * Cabeza.Nplanes;
  498.  
  499. if Index <> 0 then
  500.    FillChar (PCXline [0], Index, data);
  501.  
  502. while (Index < bytes_per_line) do
  503.    begin
  504.    ReadByte;
  505.  
  506.    if (data and $C0) = COMPRESION_NUM then
  507.       begin
  508.       count := data and $3F;
  509.       ReadByte;
  510.       FillChar (PCXline [Index], count, data);
  511.       inc (Index, count);
  512.       end
  513.    else
  514.       begin
  515.       PCXline [Index] := data;
  516.       inc (Index);
  517.       end;
  518.    end;
  519.  
  520. ReadError (3);
  521.  
  522. Index := Index - bytes_per_line;
  523.  
  524. {$I+}
  525. end;
  526.  
  527.  
  528. procedure Read_PCX (name: str80);
  529.  
  530. var
  531.    k, kmax: integer;
  532.  
  533. begin
  534. {$I-}
  535. ImageName := name;
  536.  
  537. assign (BlockFile, name);
  538. reset (BlockFile, 1);
  539. ReadError (1);
  540.  
  541. ReadHeader;
  542.  
  543.  
  544. VideoMode (PictureMode);
  545. if Cabeza.Version = 5 then
  546.    SetPalette;
  547.  
  548.  
  549. kmax := Cabeza.Ymin + Ymax;
  550. if Cabeza.Ymax < kmax then
  551.    kmax := Cabeza.ymax;
  552.  
  553. if (PictureMode = EGA) or (PictureMode = VGA) then
  554.    begin
  555.    for k := Cabeza.Ymin to kmax do
  556.       begin
  557.       Read_PCX_Line;
  558.       ShowEGA (k);
  559.       end;
  560.    end
  561. else if (PictureMode = MCGA) then
  562.    begin
  563.    for k := Cabeza.Ymin to kmax do
  564.       begin
  565.       Read_PCX_Line;
  566.       ShowMCGA (k);
  567.       end;
  568.    end
  569. else
  570.    begin
  571.    for k := Cabeza.Ymin to kmax do
  572.       begin
  573.       Read_PCX_Line;
  574.       ShowCGA (k);
  575.       end;
  576.     end;
  577.  
  578. close (BlockFile);
  579. ReadError (2);
  580. {$I+}
  581. end;
  582.  
  583.  
  584. procedure display_pcx (name: str80);
  585.  
  586. var
  587.    c: char;
  588.  
  589. begin
  590. Read_PCX (name);
  591.  
  592. while (not KeyPressed) do
  593.    { nothing };
  594.  
  595. c := ReadKey;
  596. if c = #0 then
  597.    c := ReadKey;
  598.  
  599. end;
  600.  
  601.  
  602. PROCEDURE VERPCX(NAME:STR80);
  603. BEGIN
  604. {ClrScr;
  605. writeln ('   PCXUNIT - Adaptación de SHOW_PCX al formato Unit por David Carrero F-B.');
  606. writeln ('         SHOW_PCX - leer y visualizar gráficos PC Paintbrush (R) ');
  607. writeln;
  608. writeln ('                            PERMISSION TO COPY:');
  609. writeln ('            SHOW_PCX -- (C) Copyright 1989 ZSoft, Corporation.');
  610. writeln;
  611. writeln;
  612. writeln (' Resevados todos los derechos por ZSoft Corporation de SHOW_PCX. ');
  613. writeln (' ZSoft Corporation,  450 Franklin Road, Suite 100,  Marietta, GA 30067');
  614. writeln (' (404) 428-0008');
  615. writeln;}
  616.  
  617.  
  618. if (Pos ('.', Name) = 0) then
  619.    Name := Concat (Name, '.pcx');
  620.  
  621. display_pcx (Name);
  622.  
  623. TextMode (co80);
  624.  
  625. end;
  626. END.
  627.