//
unit ads_ColorConv;
{Copyright(c)2016 Advanced Delphi Systems
Richard Maley
Advanced Delphi Systems
12613 Maidens Bower Drive
Potomac, MD 20854 USA
phone 301-840-1554
dickmaley@advdelphisys.com
The code herein can be used or modified by anyone. Please retain references
to Richard Maley at Advanced Delphi Systems. If you make improvements to the
code please send your improvements to dickmaley@advdelphisys.com so that the
entire Delphi community can benefit. All comments are welcome.
}
(*UnitIndex Master Index Implementation Section Download UnitsDescription: ads_ColorConv.pas This unit contains the following routines.
BitmapSimilarity_1 BitmapSimilarity_2 BitmapSimilarity2 BitmapsSimilar ColorToHSV ColorToHue ColorToInternet ColorToRGB ColorToSaturation ColorToValue HSVToColor HSVtoRGB JpegFileRenameToSimilarity JpegFileToBitmap JpegSimilarity JpegsSimilar RGBToColor RGBtoHSV
*) interface Uses Windows,SysUtils,Graphics,Classes,Math,Dialogs,ads_File,Jpeg; Function JpegFileToBitmap(JpegFile: String;Bitmap: TBitmap): Boolean; Function JpegSimilarity(JpegFile1,JpegFile2: String): Double;OverLoad; Function JpegsSimilar(JpegFile1,JpegFile2: String;PercentDif:Double): Boolean; Function JpegFileRenameToSimilarity(JpegFileBaseLine,JpegFileCompare,TimeStamp: String;var FileName: String;DeletionLevel: Integer): Boolean; function BitmapSimilarity2(Bitmap1, Bitmap2: TBitmap): Double; Function BitmapSimilarity(Bitmap1,Bitmap2: TBitmap): Double; OverLoad; Function BitmapSimilarity(BitmapFile1,BitmapFile2: String): Double; OverLoad; Function BitmapsSimilar(BitmapFile1,BitmapFile2: String;PercentDif:Double): Boolean; Function ColorToValue(c:TColor): Double; Function ColorToSaturation(c:TColor): Double; Function ColorToHue(c:TColor): Double; Function ColorToInternet(c:TColor): String; procedure ColorToRGB(c:TColor;out r,g,b: Double;maxr,maxg,maxb: Double); procedure ColorToHSV(c:TColor;out h,s,v: Double;maxs,maxv: Double); Function RGBToColor(R,G,B:Double): TColor; Function HSVToColor(H,S,V:Double): TColor; procedure RGBtoHSV(r,g,b: Double;out h,s,v: Double;maxr,maxg,maxb,maxs,maxv: Double); procedure HSVtoRGB(out r,g,b:Double;h,s,v: Double;maxr,maxg,maxb,maxs,maxv: Double); implementation // r,g,b values are from 0 to 1 // h = [0,360], s = [0,1], v = [0,1] // if s == 0, then h = -1 (undefined) //Unit Description UnitIndex Master Index
procedure RGBtoHSV(r,g,b: Double;out h,s,v: Double;maxr,maxg,maxb,maxs,maxv: Double);
Var
Vmin : Double;
Vmax : Double;
delta : Double;
Begin
If maxr<>1.0 Then r:=(r/maxr);
If maxg<>1.0 Then g:=(g/maxg);
If maxb<>1.0 Then b:=(b/maxb);
Vmin := Min(r,Min(g,b));
Vmax := Max(r,Max(g,b));
v := Vmax;
delta:=Vmax-Vmin;
If Vmax<> 0 Then
Begin
s:=delta/Vmax;
End
Else
Begin
s:=0;
h:=0;
Exit;
End;
If r=Vmax Then
Begin
If delta=0 Then
h:=0
Else
h:=(g-b)/delta;
End
Else
Begin
If g=Vmax Then
Begin
h:=2+((b-r)/delta);//between cyan & yellow
End
Else
Begin
h:=4+((r-g)/delta);//between magenta & cyan
End;
End;
h:=h*60;//degrees
If h<0 Then h:=h+360;
If maxs<>1.0 Then s:=(s*maxs);
If maxv<>1.0 Then v:=(v*maxv);
End;
//Unit Description UnitIndex Master Index
procedure HSVtoRGB(out r,g,b:Double;h,s,v: Double;maxr,maxg,maxb,maxs,maxv: Double);
Var
i : Integer;
f,p,q,t: Double;
Begin
If maxs<> 1.0 Then s:=(s/maxs);
If maxv<> 1.0 Then v:=(v/maxv);
If s=0 Then
Begin
//achromatic (grey)
r:=v;
g:=v;
b:=v;
If maxr<>1.0 Then r:=(r*maxr);
If maxg<>1.0 Then g:=(g*maxg);
If maxb<>1.0 Then b:=(b*maxb);
Exit;
End;
h:=h/60;
i:=floor(h);
f:=h-i; // factorial part of h
p:=v*(1-s);
q:=v*(1-(s*f));
t:=v*(1-(s*(1-f)));
case i Of
0:
Begin
r:=v;
g:=t;
b:=p;
End;
1:
Begin
r:=q;
g:=v;
b:=p;
End;
2:
Begin
r:=p;
g:=v;
b:=t;
End;
3:
Begin
r:=p;
g:=q;
b:=v;
End;
4:
Begin
r:=t;
g:=p;
b:=v;
End;
Else
Begin
r:=v;
g:=p;
b:=q;
End;
End;
If maxr<>1.0 Then r:=(r*maxr);
If maxg<>1.0 Then g:=(g*maxg);
If maxb<>1.0 Then b:=(b*maxb);
End;
//Unit Description UnitIndex Master Index
procedure ColorToRGB(c:TColor;out r,g,b: Double;maxr,maxg,maxb: Double);
Begin
with TRGBQuad(Graphics.ColorToRGB(c)) Do
Begin
r:=rgbRed;
g:=rgbGreen;
b:=rgbBlue;
If maxr<>255 Then r:=(r*maxr)/255;
If maxg<>255 Then g:=(g*maxg)/255;
If maxb<>255 Then b:=(b*maxb)/255;
End;
End;
//Unit Description UnitIndex Master IndexFunction RGBToColor(R,G,B:Double): TColor; Begin Result:=TColor((Floor(R)*65536)+(Floor(G)*256)+Floor(B)); End; //Unit Description UnitIndex Master Index
procedure ColorToHSV(c:TColor;out h,s,v: Double;maxs,maxv: Double); Var r,g,b: Double; Begin ColorToRGB(c,r,g,b,255,255,255); RGBtoHSV(r,g,b,h,s,v,255,255,255,maxs,maxv); End; //Unit Description UnitIndex Master Index
Function HSVToColor(H,S,V:Double): TColor; Var r,g,b: Double; Begin HSVtoRGB(r,g,b,h,s,v,255,255,255,255,255); Result:=RGBToColor(r,g,b); End; //Unit Description UnitIndex Master Index
Function ColorToInternet(c:TColor): String; Var r,g,b: Double; Begin ColorToRGB(c,r,g,b,255,255,255); Result:=IntToHex(Floor(b),2)+IntToHex(Floor(g),2)+IntToHex(Floor(r),2); End; //Unit Description UnitIndex Master Index
Function ColorToHue(c:TColor): Double; Var h,s,v: Double; Begin ColorToHSV(c,h,s,v,255,255); Result:=h; End; //Unit Description UnitIndex Master Index
Function ColorToSaturation(c:TColor): Double; Var h,s,v: Double; Begin ColorToHSV(c,h,s,v,255,255); Result:=s; End; //Unit Description UnitIndex Master Index
Function ColorToValue(c:TColor): Double; Var h,s,v: Double; Begin ColorToHSV(c,h,s,v,255,255); Result:=v; End; //Unit Description UnitIndex Master Index
function BitmapSimilarity(Bitmap1, Bitmap2: TBitmap): Double;
Var
P1 : PByteArray;
P2 : PByteArray;
t : Integer;
x : Integer;
y : Integer;
begin
Result:=0.0;
t:=0;
If (BitMap1.Height<>BitMap2.Height) Or (BitMap1.Width<>BitMap2.Width) Then Exit;
for y := 0 to BitMap1.Height -1 do
begin
P1 := BitMap1.ScanLine[y];
P2 := BitMap2.ScanLine[y];
for x := 0 to BitMap1.Width -1 do
Begin
If (ColorToValue(P1[x])-ColorToValue(P2[x]))>25 Then t:=t+1;
End;
end;
Result:=(1-(t/(Bitmap1.Width*Bitmap1.Height)))*100;
end;
//Unit Description UnitIndex Master Index
function BitmapSimilarity2(Bitmap1, Bitmap2: TBitmap): Double;
Var
FBitmap1 : TBitmap;
FBitmap2 : TBitmap;
P1 : PByteArray;
P2 : PByteArray;
t : Integer;
x : Integer;
y : Integer;
inMaxX : Integer;
inMaxY : Integer;
begin
Result:=0.0;
t:=0;
If (BitMap1.Height<>BitMap2.Height) Or (BitMap1.Width<>BitMap2.Width) Then Exit;
FBitmap1 := TBitmap.Create();
FBitmap2 := TBitmap.Create();
Try
FBitmap1.Assign(Bitmap1);
FBitmap2.Assign(Bitmap2);
If FBitmap1.PixelFormat<>pf16bit Then FBitmap1.PixelFormat:=pf16bit;
If FBitmap2.PixelFormat<>pf16bit Then FBitmap2.PixelFormat:=pf16bit;
inMaxX := FBitMap1.Width -1;
inMaxY := FBitMap1.Height -1;
for y := 0 to inMaxY do
begin
P1 := FBitMap1.ScanLine[y];
P2 := FBitMap2.ScanLine[y];
If P1=P2 Then Continue;
for x := 0 to inMaxX do
Begin
Try
If P1[x] <> P2[x] Then t:=t+1;
Except
End;
End;
end;
Result:=(1-(t/((inMaxX+1)*(inMaxY+1))))*100;
Finally
FBitmap1.Free;
FBitmap2.Free;
End;
end;
//Unit Description UnitIndex Master Index
Function BitmapSimilarity(BitmapFile1,BitmapFile2: String): Double;OverLoad;
Var
Bitmap1 : TBitmap;
Bitmap2 : TBitmap;
begin
Result:=0.0;
Bitmap1 := TBitmap.Create();
Bitmap2 := TBitmap.Create();
Try
If Not FileExists(BitmapFile1) Then Exit;
If Not FileExists(BitmapFile2) Then Exit;
Bitmap1.LoadFromFile(BitmapFile1);
Bitmap2.LoadFromFile(BitmapFile2);
Result:=BitmapSimilarity(Bitmap1, Bitmap2);
Finally
Bitmap1.Free;
Bitmap2.Free;
End;
end;
//Unit Description UnitIndex Master IndexFunction BitmapsSimilar(BitmapFile1,BitmapFile2: String;PercentDif:Double): Boolean; Begin Result:=((100-BitmapSimilarity(BitmapFile1,BitmapFile2))Unit Description UnitIndex Master Index Function JpegSimilarity(JpegFile1,JpegFile2: String): Double;OverLoad; Var Bitmap1 : TBitmap; Bitmap2 : TBitmap; begin Result :=0.0; If Not FileExists(JpegFile1) Then Exit; If Not FileExists(JpegFile2) Then Exit; Bitmap1 := TBitmap.Create(); Bitmap2 := TBitmap.Create(); Try If JpegFileToBitmap(JpegFile1,Bitmap1) Then Begin If JpegFileToBitmap(JpegFile2,Bitmap2) Then Begin Result:=BitmapSimilarity2(Bitmap1, Bitmap2); End; End; Finally Bitmap1.Free; Bitmap2.Free; End; end; //Unit Description UnitIndex Master IndexFunction JpegsSimilar(JpegFile1,JpegFile2: String;PercentDif:Double): Boolean; Var r : Double; Begin r:= JpegSimilarity(JpegFile1,JpegFile2); Result:=((100-r)Unit Description UnitIndex Master Index Function JpegFileToBitmap(JpegFile: String;Bitmap: TBitmap): Boolean; Var Jpeg : TJpegImage; Begin Result := False; If Not FileExists(JpegFile) Then Exit; Jpeg := TJpegImage.Create(); Try Try Jpeg.LoadFromFile(JpegFile); Bitmap.Assign(JPeg); Result:=True; Except Result := False; End; Finally Jpeg .Free; End; End; //Unit Description UnitIndex Master IndexFunction JpegFileRenameToSimilarity(JpegFileBaseLine,JpegFileCompare,TimeStamp: String;var FileName: String;DeletionLevel: Integer): Boolean; Var Similarity : Double; FilePath : String; FilePrefix : String; sgTempNum : String; i : Integer; Begin Result := False; If Not FileExists(JpegFileBaseLine) Then Exit; If Not FileExists(JpegFileCompare) Then Exit; If LowerCase(JpegFileBaseLine)=LowerCase(JpegFileCompare) Then Exit; TimeStamp:=Trim(TimeStamp); If TimeStamp<>'' Then TimeStamp:=TimeStamp+'_'; Try Similarity:= JpegSimilarity(JpegFileBaseLine,JpegFileCompare); If Similarity>=DeletionLevel Then Begin Exit; End; If Similarity>=100.0 Then Similarity:= 99.99999; FilePath := ExtractFilePath(JpegFileCompare); FilePrefix:= FormatFloat('00.00000',Similarity); FilePrefix:= StringReplace(FilePrefix,'.','_',[]); FilePrefix:= TimeStamp+FilePrefix; For i:=0 To 9999 Do Begin sgTempNum:='0000'+IntToStr(i); sgTempNum:=Copy(sgTempNum,Length(sgTempNum)-3,4); If FileExists(FilePath+FilePrefix+sgTempNum+'.jpg') Then Continue; RenameFile(JpegFileCompare,FilePath+FilePrefix+sgTempNum+'.jpg'); FileName:=FilePath+FilePrefix+sgTempNum+'.jpg'; Result:=True; Break; End; Except End; End; end. //