🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.pascal.ansi-iso
Article #37

Re: Making Pascal Display Picture Files

#37
From: Alexander V. Gaiduk
Date: Fri, 04 Jul 1997 00:00
334 lines
9472 bytes
> I'm sorta new to pascal programming, could someone show me how or put me
> on the right track to figuring out how to make pascal display picture
> files, jpg, gif, bmp, pcx, tif, etc...
> I would be eternally grateful if anyone could help.
> Mike Bailey a.k.a. Phantom CyberSpace
> Owner/K&K SoftWare, Consulting & Webpage Design
> 

unit TBMP;

{ Unit for show Windows Bitmap files.        }
{ Now support only :                         }
{   BMP 256 colors (Not RLE)                 }
{   BMP 16  colors (Not RLE)                 }
{ image show in CURRENT screen graphics mode }

interface

const
  BmpOk           =  0;
  BmpUnknownError = -1;
  BmpFileNotFound = -2;
  BmpNotSuppRes   = -3;
  BmpNotSuppFmt   = -4;

  function ShowBitMapImage(Name : String; X, Y : Word) : Integer;

implementation

uses Crt, Dos, Graph;

type
  TPaletteEntry = record
    B: Byte;
    G: Byte;
    R: Byte;
    Flags: Byte;
  end;
  TBitmapFileHeader = record
    bfType: Word;
    bfSize: Longint;
    bfReserved1: Word;
    bfReserved2: Word;
    bfOffBits: Longint;
    biSize: Longint;
    biWidth: Longint;
    biHeight: Longint;
    biPlanes: Word;
    biBitCount: Word;
    biCompression: Longint;
    biSizeImage: Longint;
    biXPelsPerMeter: Longint;
    biYPelsPerMeter: Longint;
    biClrUsed: Longint;
    biClrImportant: Longint;
  end;

var
  BitmapName : String;
  F : File;
  bfh : TBitmapFileHeader;
  Pal256 : array[0..255] of TPaletteEntry;
  Pal16 : array[0..15] of TPaletteEntry;
  FileOpen : Boolean;
  Width_R, Width, Height : Word;
  BitCount : Word;
  Xstart, Ystart, xt, yt : Word;
  W2 : Word;

  function SwapNibble(B : Byte) : Byte;
    {-Swap the high and low nibbles of B: SwapNibble($F0) returns $0F.}
    inline(
      $58/                     {pop ax     ;AL = B}
      $88/$C4/                 {mov ah,al  ;AH = B}
      $B9/$04/$00/             {mov cx,4   ;4 bits/nibble}
                               {Start:}
      $D0/$CC/                 {ror ah,1   ;rotate rightmost bit of AH}
      $D0/$D8/                 {rcr al,1   ;into leftmost bit of AL}
      $E2/$FA);                {loop Start ;do it four times}

  function OpenFile : Boolean;
  begin
    FileOpen := False;
    OpenFile := False;
    Assign(F, BitmapName);
    Reset(F, 1);
    if IoResult <> 0 then Exit;
    FileOpen := True;
    OpenFile := True;
  end;

  function CloseFile : Boolean;
  begin
    FileOpen := False;
    CloseFile := False;
    Close(F);
    if IoResult <> 0 then Exit;
    CloseFile := True;
  end;

  function ReadBMPFileHead : Boolean;
  begin
    ReadBMPFileHead := False;
    BlockRead(F, bfh, SizeOf(bfh));
    if (IoResult <> 0) or
       (bfh.bfType <> $4D42) then Exit;
    Width := bfh.biWidth;
    Height := bfh.biHeight;
    BitCount := bfh.biBitCount;
    Width_R := Width;
    ReadBMPFileHead := True;
  end;

  function ReadPalette16 : Boolean;
  var C : Byte;
  begin
    ReadPalette16 := False;
    BlockRead(F, Pal16, SizeOf(Pal16));
    if IoResult <> 0 then Exit;
    for C := 0 to 15 do
      begin
        Pal16[C].R := Pal16[C].R shr 2;
        Pal16[C].G := Pal16[C].G shr 2;
        Pal16[C].B := Pal16[C].B shr 2;
      end;
    ReadPalette16 := True;
  end;

  function ReadPalette256 : Boolean;
  var C : Byte;
  begin
    ReadPalette256 := False;
    BlockRead(F, Pal256, SizeOf(Pal256));
    if IoResult <> 0 then Exit;
    for C := 0 to 255 do
      begin
        Pal256[C].R := Pal256[C].R shr 2;
        Pal256[C].G := Pal256[C].G shr 2;
        Pal256[C].B := Pal256[C].B shr 2;
      end;
    ReadPalette256 := True;
  end;

  procedure SetPalette256;
  const
    RED = 0;
    GREEN = 1;
    BLUE = 2;
  type
    Pal_array = array[0..255, RED..BLUE] of Byte;
  var
    Palette256 : Pal_array;
    Reg : Registers;
    i : Byte;
  begin
    for i := 0 to 255 do
      begin
        Palette256[i, RED]   := Pal256[i].R;
        Palette256[i, GREEN] := Pal256[i].G;
        Palette256[i, BLUE]  := Pal256[i].B;
      end;
    Reg.ah := $10;                { Set DAC Call }
    Reg.al := $12;                { set a block of DAC registers }
    Reg.bx := 0;                  { first DAC register number }
    Reg.cx := 255;                { number of registers to update }
    Reg.dx := Ofs(Palette256);    { offset of block }
    Reg.es := Seg(Palette256);    { segment of block }
    Intr($10, Reg);               { call interrupt }
  end;

  function SetPalette16 : Boolean;
  const
    RED = 0;
    GREEN = 1;
    BLUE = 2;
  type
    Pal_array = array[0..15, RED..BLUE] of Byte;
  var
    Palette16 : Pal_array;
    Reg : Registers;
    i : Byte;
  begin
    for i := 0 to 15 do
      begin
        Palette16[i, RED]   := Pal16[i].R;
        Palette16[i, GREEN] := Pal16[i].G;
        Palette16[i, BLUE]  := Pal16[i].B;
      end;
    Reg.ah := $10;                { Set DAC Call }
    Reg.al := $12;                { set a block of DAC registers }
    Reg.bx := 0;                  { first DAC register number }
    Reg.cx := 16;                 { number of registers to update }
    Reg.dx := Ofs(Palette16);     { offset of block }
    Reg.es := Seg(Palette16);     { segment of block }
    Intr($10, Reg);               { call interrupt }
  end;

  function ShowImage4 : Boolean;
  var
    Px, C0, C1 : Byte;
    Lin4 : array[0..1023] of Byte;
  begin
    ShowImage4 := False;
    Seek(F, bfh.bfOffBits);
    if (Width mod 8) <> 0 then
      while (Width mod 8) <> 0 do Inc(Width);
    W2 := (Width_R-1) div 2;
    for yt := Height-1 downto 0 do
      begin
        BlockRead(F, Lin4, Width div 2);
        for xt := 0 to W2 do
          begin
            Px := Lin4[xt];
            C0 := Px shr 4;
            Px := SwapNibble(Px);
            C1 := Px shr 4;
            PutPixel(Xstart+xt*2, Ystart+yt, C0);
            PutPixel(Xstart+xt*2+1, Ystart+yt, C1);
          end;
      end;
    ShowImage4 := True;
  end;

  function ShowImage8 : Boolean;
  type
    TLin = record
      X, Y : Word;
      Data : array[0..1023] of Byte;
    end;
  var
    SizeP : Word;
    Lin8 : ^TLin;
  begin
    ShowImage8 := False;
    if (Width mod 4) <> 0 then
      while (Width mod 4) <> 0 do Inc(Width);
    Seek(F, bfh.bfOffBits);
    SizeP := ImageSize(0, 0, 1028, 0);
    GetMem(Lin8, SizeP);
    Lin8^.X := Width_R-1;
    Lin8^.Y := 0;
    for yt := Height-1 downto 0 do
      begin
        BlockRead(F, Lin8^.Data, Width);
        PutImage(Xstart, Ystart+yt, Lin8^, NormalPut);
      end;
    FreeMem(Lin8, SizeP);
    ShowImage8 := True;
  end;

  procedure ShowPalette16;
  var x : Byte;
  begin
    for x := 0 to 15 do
      begin
        SetFillStyle(SolidFill, x);
        Bar(x*20, 0, (x+1)*20, 20);
      end;
  end;

  procedure ShowPalette256;
  var x, y, c : Byte;
  begin
    c := 0;
    for y := 0 to 15 do
      for x := 0 to 15 do
        begin
          SetFillStyle(SolidFill, c);
          Bar(x*20, y*20, (x+1)*20, (y+1)*20);
          Inc(c);
        end;
  end;

  procedure FadeOut16;
  var i, k : Byte;
  begin
    ReadKey;
    for k := 0 to 63 do
      begin
        for i := 0 to 15 do
          begin
            if Pal16[i].R > 0 then Dec(Pal16[i].R);
            if Pal16[i].G > 0 then Dec(Pal16[i].G);
            if Pal16[i].B > 0 then Dec(Pal16[i].B);
          end;
        SetPalette16;
        Delay(20);
      end;
  end;

  procedure FadeOut256;
  var i, k : Byte;
  begin
    ReadKey;
    for k := 0 to 63 do
      begin
        for i := 0 to 255 do
          begin
            if Pal256[i].R > 0 then Dec(Pal256[i].R);
            if Pal256[i].G > 0 then Dec(Pal256[i].G);
            if Pal256[i].B > 0 then Dec(Pal256[i].B);
          end;
        SetPalette256;
        Delay(20);
      end;
  end;

  function ShowBitMapImage(Name : String; X, Y : Word) : Integer;
  begin
    ShowBitMapImage := BmpUnknownError;
    BitmapName := Name;
    ShowBitMapImage := BmpFileNotFound;
    Xstart := X;
    Ystart := Y;
    if not OpenFile then Exit;
    if not ReadBMPFileHead then Exit;
    case BitCount of
      4 : begin
            ReadPalette16;
            SetPalette16;
            ShowImage4;
          end;
      8 : begin
            ReadPalette256;
            SetPalette256;
            ShowImage8;
          end;
    end;
    if not CloseFile then Exit;
    ShowBitMapImage := BmpOk;
  end;

end. 
Technical Details
Message-ID: <01bc884e$e56724e0$0db8bac2@gav.lesobank.ru>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <33B7DFDD.91D383C8@oneworld.owt.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 10261c,7fdb5cd19d186f8a
X-Google-Attributes: gid10261c,public
X-Google-Thread: 111659,7fdb5cd19d186f8a
X-Google-Attributes: gid111659,public
X-Google-Thread: 10c950,7fdb5cd19d186f8a
X-Google-Attributes: gid10c950,public
X-Google-Thread: 10cc59,7fdb5cd19d186f8a
X-Google-Attributes: gid10cc59,public
X-Google-Thread: 108d84,7fdb5cd19d186f8a
X-Google-Attributes: gid108d84,public
From: "Alexander V. Gaiduk" <gav@lesobank.ru>
Subject: Re: Making Pascal Display Picture Files
Date: 1997/07/04
Message-ID: <01bc884e$e56724e0$0db8bac2@gav.lesobank.ru>
X-Deja-AN: 254473391
References: <33B7DFDD.91D383C8@oneworld.owt.com>
Organization: LesoBANK
Newsgroups: comp.lang.pascal.ansi-iso,comp.lang.pascal.borland,comp.lang.pascal.misc,fidonet.pascal,comp.lang.pascal