[fpc-pascal] Syntax to select constant or variable with function call

Michael Van Canneyt michael at freepascal.org
Sun Sep 24 07:55:03 CEST 2017



On Sat, 23 Sep 2017, James Richters wrote:

> I have several Similar arrays as follows for translating various color schemes into RGB565, I currently have 5 arrays but may add more.
>
>
>  ACI256: Array[0..255] of VGARGBRec = (
>      (R:$00; G:$00; B:$00; RGB:$0000),  //[  0]
>      (R:$FF; G:$00; B:$00; RGB:$F800),  //[  1]
>      (R:$FF; G:$FF; B:$00; RGB:$FFE0),  //[  2]
>      (R:$00; G:$FF; B:$00; RGB:$07E0),  //[  3]
>      (R:$00; G:$FF; B:$FF; RGB:$07FF),  //[  4]
> ..
>      (R:$FF; G:$FF; B:$FF; RGB:$FFFF)); //[255]
>
>   VGA256: Array[0..255] of VGARGBRec = (
>      (R:$00; G:$00; B:$00; RGB:$0000),  //[000]
>      (R:$00; G:$00; B:$AA; RGB:$0015),  //[001]
>      (R:$00; G:$AA; B:$00; RGB:$0540),  //[002]
>      (R:$00; G:$AA; B:$AA; RGB:$0555),  //[003]
>      (R:$AA; G:$00; B:$00; RGB:$A800),  //[004]
> ..
>      (R:$00; G:$00; B:$00; RGB:$0000)); //[255]
>
>
> I have some simple functions that use these arrays for example this one to find the closest value to specified Red, Green, and Blue values:
>
> Function Find_VGA(r ,g ,b : Word) : Byte;
> Var
>  Dist,closest:Double;
>  i,bestchoice:Byte;
> Begin
>   Closest:=200000;
>   For i:= 0 to 255 do
>      Begin
>         Dist :=  ((R-VGA256[i].R))*((R-VGA256[i].R)) + ((G-VGA256[i].G)*(G-VGA256[i].G)) + ((B-VGA256[i].B)*(B-VGA256[i].B));
>         If Dist<Closest Then
>            Begin
>               Closest:=Dist;
>               BestChoice:=i;
>            End;
>      End;
>   Find_VGA:=BestChoice;
> End;
>
>
> Instead of having a bunch of separate functions,
> I would like to know if there is a way I can specify which constant to use directly so the one function could use any of the arrays.
>
> Something like 
> function Find_Color(Array_to_use:var ;r ,g ,b : Word) : Byte;
>
> then use Array_to_use[i] instead of VGA256[i] in my formula...
>
> so calling Find_Color(VGA256,$00,$FF,$FC) would use the VGA256 array and 
> calling Find_Color(ACI256,$00,$FF,$FC) would use the ACI256 array.. etc.. 
>
> Is this kind of thing even possible? Or do I just need separate functions?

This is certainly possible.

First, define
Type
   TVGA256Array = Array[0..255] of VGARGBRec;
   PVGA256Array = ^TVGA256Array;

And redeclare your arrays as:
   ACI256: TVGA256Array = (
   // etc
    VGA256: TVGA256Array  = (
   // etc

Then define
function Find_Color(anArray :PVGA256Array; r ,g ,b : Word) : Byte;
  Var
   Dist,closest:Double;
   i,bestchoice:Byte;

begin
    Closest:=200000;
    For i:= 0 to 255 do
       Begin
          Dist :=  ((R-AnArray^[i].R))*((R-AnArray^[i].R))
                     + ((G-AnArray^[i].G)*(G-Anarray^[i].G))
                     + ((B-AnArray^[i].B)*(B-AnArray^[i].B));
          If Dist<Closest Then
             Begin
                Closest:=Dist;
                BestChoice:=i;
             End;
       End;
    Find_VGA:=BestChoice;
end;

Call as
Find_Color(@VGA256,$00,$FF,$FC)
etc.

Alternatively, you can avoid the pointer if you declare the function as

function Find_Color(constref anArray :TVGA256Array; r ,g ,b : Word) : Byte;
you can then get rid of the dereferencing:
          Dist :=  ((R-AnArray[i].R))*((R-AnArray[i].R))
                     + ((G-AnArray[i].G)*(G-Anarray[i].G))
                     + ((B-AnArray[i].B)*(B-AnArray[i].B));

The loop can still be optimized, but that is another topic.

Michael.



More information about the fpc-pascal mailing list