unit uHues;

interface

uses Classes, SysUtils, GR32, Dialogs, Graphics, uUtilities;

type    THueColorTable = array[0..31] of Word;
        THueName = array[0..19] of Char;

        THueEntry = packed record
                ColorTable : THueColorTable;
                TableStart, TableEnd : Word;
                Name : THueName;
        end;

        THueGroup = packed record
                Header : Integer;
                Entries : Array[0..7] of THueEntry;
        end;

        THue = packed record
                ColorTable : THueColorTable;
                TableStart, TableEnd : Word;
                Name : THueName;
                Index : Integer;
        end;

        THues = class
        private
                FarbListe : TList;
        public
                loaded : Boolean;
                constructor Create;
                destructor Free;
                procedure Load( FilePath : String );
                procedure Save( FilePath : String );
                function GetColor( Id, Index : Integer ) : Integer;
                function GetName( Id : Integer ) : THueName;
                function GetHueCount : Integer;
                procedure SetColor( Id, Index, Color : Integer );
                procedure SetName( Id : Integer; Name : String );
                procedure Spread( StartIndex, EndIndex, Id : Integer );                
        end;

var     Hues : THues;
        Hues2 : THues;

implementation

constructor THues.Create;
begin
        FarbListe := TList.Create;
        loaded := false;
end;

destructor THues.Free;
begin
        FarbListe.Free;
end;

procedure THues.Load( FilePath : String );
var     fStream : TFileStream;
        GroupCount : integer;
        I : integer;
        Group : THueGroup;
        Hue : ^THue;
begin
        fStream := TFileStream.Create( FilePath, fmOpenRead );
        fStream.Seek( 0, soFromBeginning );

        groupcount := 0;
        while fStream.Position < fStream.Size do begin
                fStream.Read( Group, sizeof( THueGroup ) );
                for i := 0 to 7 do begin
                        new( Hue );
                        Hue.ColorTable := Group.Entries[ i ].ColorTable;
                        Hue.Name := Group.Entries[ i ].Name;
                        Hue.TableStart := Group.Entries[ i ].TableStart;
                        Hue.TableEnd := Group.Entries[ i ].TableEnd;
                        Hue.Index := groupcount * 8 + i;
                        Farbliste.Add( Hue );
                end;
                inc( groupcount );
        end;
        fStream.Free;
        Loaded := true;
end;

procedure THues.Save( FilePath : String );
var     fStream : TFileStream;
        I, GroupCount : integer;
        Group : THueGroup;
        Hue : ^THue;
begin
        fStream := TFileStream.Create( FilePath, fmCreate );
        fStream.Seek( 0, soFromBeginning );

        for GroupCount := 0 to ( Farbliste.Count div 8 )-1 do begin
                for i:=0 to 7 do begin
                        Hue := FarbListe.Items[ GroupCount*8+i ];
                        Group.Entries[ i ].ColorTable := Hue.ColorTable;
                        Group.Entries[ i ].Name := Hue.Name;
                        Group.Entries[ i ].TableStart := Hue.TableStart;
                        Group.Entries[ i ].TableEnd := Hue.TableEnd;
                end;
                fStream.Write( Group, sizeof( THueGroup ) );
        end;
        fStream.Free;
end;

function THues.GetColor( Id, Index : Integer ) : Integer;
var     Hue : ^THue;
begin
        Hue := FarbListe.Items[ Id ];
        if Hue.Index <> Id then begin
                showmessage( 'Bug beim Indizieren der Hues.' );
                Result := -1;
                exit;
        end;

        Result := Hue.ColorTable[ Index ];
end;

function THues.GetName( Id : Integer ) : THueName;
var     Hue : ^THue;
begin
        Hue := FarbListe.Items[ Id ];
        if Hue.Index <> Id then begin
                showmessage( 'Bug beim Indizieren der Hues.' );
                Result := '';
                exit;
        end;

        Result := Hue.Name;
end;

function THues.GetHueCount : Integer;
begin
        Result := FarbListe.Count;
end;

procedure THues.SetColor( Id, Index, Color : Integer );
var     Color15 : Word;
begin
        Color15 := ((Color and $F80000) shr 19) or ((Color and $F800) shr 6) or ((Color and $F8) shl 7);
        THue( FarbListe.Items[ Id ]^ ).ColorTable[ Index ] := Color15;
end;

procedure THues.SetName( Id : Integer; Name : String );
var     NameNew : THueName;
begin
        StrPCopy( NameNew, pChar( Name ) );
        THue( FarbListe.Items[ Id ]^ ).Name := NameNew;
end;

procedure THues.Spread( StartIndex, EndIndex, Id : Integer );
var     RedA, RedE, GreenA, GreenE, BlueA, BlueE : Integer;
        Red, Green, Blue : Integer;
        ColorA, ColorE, Dif, ColorNew : Integer;
        i : Integer;
        RedOffset, GreenOffset, BlueOffset : real;
begin
        ColorA := Color15to32( GetColor( Id, StartIndex ) );
        ColorE := Color15to32( GetColor( Id, EndIndex ) );

        RedA := RedComponent( ColorA );
        GreenA := GreenComponent( ColorA );
        BlueA := BlueComponent( ColorA );
        RedE := RedComponent( ColorE );
        GreenE := GreenComponent( ColorE );
        BlueE := BlueComponent( ColorE );
        Dif := EndIndex - StartIndex;
        RedOffset := 0.5 * ( RedA + RedE - ( RedE - RedA )*( StartIndex + EndIndex )/ Dif );
        GreenOffset := 0.5 * ( GreenA + GreenE - ( GreenE - GreenA )*( StartIndex + EndIndex )/ Dif );
        BlueOffset := 0.5 * ( BlueA + BlueE - ( BlueE - BlueA )*( StartIndex + EndIndex )/ Dif );

        for i := StartIndex to EndIndex do begin
                Red := round( ( RedE - RedA ) *i / Dif + RedOffset );
                Green := round( ( GreenE - GreenA ) *i / Dif + GreenOffset );
                Blue := round( ( BlueE - BlueA ) *i / Dif + BlueOffset );
                ColorNew := Color32( Blue, Green, Red );
                SetColor( Id, i, ColorNew );
        end;
end;

end.
