[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]

    {
    ============================================================

    PROGRAM : CLOSECOL.PAS

    AUTHOR  : SCOTT TUNSTALL B.Sc

    PURPOSE : Get the colour which has specified RGB values from
              the VGA palette.
              If no colour with specified values exists, return
              the nearest colour.

    NOTES   :

    I seem to recall AGES ago that someone wanted a routine
    that would find the colour CLOSEST to a specified RGB
    value.

    This might help, although I've not tested it extensively.
    Tests seem to show it works OK tho'.

    Oh yeah. It needs KOJAKVGA (preferably V3) to work as is,
    but it won't be too difficult for smart cookies to work out
    whats going on, if they want to convert the code to their
    units.

    DISCLAIMER:

    The standard stuff follows:

    Unless you're a proud CGA/EGA card user ;), this unit
    shouldn't break your PC.

    However, the rule is: use this code AT YOUR OWN RISK.

    If you use this code in any programs, please mention my name
    in the credits. An ad for KOJAKVGA 3.3 would be nice too ;)

    Have fun folks!
    ------------------------------------------------------------
    }

    program CloseCol;

    uses kojakvga, crt;

    {
    As the function name implies, this gets the palette entry which
    contains RGB values closest to those specified.
    (C) 1997 Crap explanations ;)

    Expects: R,G,B component values to look for;
             Red component must be in range 0-63
             Same applies for Green and Blue.

             Values above 63 are reset to (Value MOD 64) !
             This is due to the limitations of the VGA DAC I'm afraid.

    Returns: index (0-255) of closest or matching colour.
    }

    function GetClosestVGAColour(SearchRed,SearchGreen,SearchBlue:byte) : byte;
    var bestindex, currRed, currGreen, currBlue, colourcount: byte;
        distred, distgreen, distblue,
        bestdistred, bestdistgreen, bestdistblue: integer;
        RGBTotal, BestRGBTotal: word;

    begin
         bestindex:=0;
         distred:=255;              { Distance of red from SearchRed value }
         distgreen:=255;
         distblue:=255;

         bestdistred:=255;
         bestdistgreen:=255;
         bestdistblue:=255;
         BestRGBTotal:=255+255+255; { R,G,B summed }

         { Iterate (love that word!) through all palette entries }

         for colourcount:=0 to 255 do
             begin
             { Read colour from VGA adaptor directly. }

             GetRGB(colourcount,currRed,currGreen,currBlue);

             { Compute Red/Green and Blue distances }

             distred:=abs(CurrRed-SearchRed);
             distgreen:=abs(CurrGreen-SearchGreen);
             distblue:=abs(CurrBlue-SearchBlue);

             { The lower the sum of RGB distances, the closer
               the colour is to what was required }

             RGBTotal:=distred+distgreen+distblue;
             If RGBTotal <= BestRGBTotal Then
             Begin
                BestIndex:=ColourCount;

                { If we've got a perfect match, i.e. the
                  total colour distance is 0, then
                  break the loop }

                If RGBTotal = 0 Then
                   break
                else
                    BestRGBTotal:=RGBTotal;

             End;
         end;

         { And return the closest colour's palette index }

         getClosestVGAColour:=BestIndex;
    end;

    { Support function to display red, green, blue values at X,Y in
      colour printcolour }

    procedure PrintRGB(x:word; y, printcolour, r,g,b: byte);
    var NumStr: string[3];
        Builtstr:string[30];
    begin
        str(r, BuiltStr);
        str(g, NumStr);
        BuiltStr:=BuiltStr+','+NumStr;
        str(b, NumStr);
        BuiltStr:=BuiltStr+','+NumStr;
        UseColour(printcolour);
        PrintAt(x,y,BuiltStr);
    end;

    { Test. You input your required RGB values and the system shows
      two blocks which should be nearly - or even better,
      ** exactly ** - the same colour shade.
    }

    var MyRed, MyGreen, MyBlue,             { RGB of colour to look for }
        FoundRed, FoundGreen, FoundBlue,    { RGB of closest colour }
        OurColour, FillColour: byte;        { Indexes for drawing }

    begin
         Writeln('What [VGA] R,G,B values are you looking for ? ');
         Write('Red   (0-63) '); Readln(MyRed);
         Write('Green (0-63) '); Readln(MyGreen);
         Write('Blue  (0-63) '); Readln(MyBlue);

         InitVGAMode;
         OurColour:=GetClosestVGAColour(MyRed, MyGreen, MyBlue);

         If OurColour = 0 Then
            FillColour:= 1
         Else
             FillColour:= OurColour -1;

         SetRGB(FillColour,MyRed,MyGreen,MyBlue);

         { Display colour looked for }

         PrintRGB(0,0,FillColour, MyRed, MyGreen, MyBlue);
         FillArea(0,16,158,199, FillColour);

         { Display closest colour }

         GetRGB(OurColour, FoundRed, FoundGreen, FoundBlue);
         PrintRGB(160,0, OurColour, FoundRed, FoundGreen, FoundBlue);
         FillArea(161,16,319,199,OurColour);

         { And do I have to explain what this does? }

         repeat until keypressed;
    End.

[Back to GRAPHICS SWAG index] [Back to Main SWAG index] [Original]