This repository has been archived on 2024-02-26. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
MyPresenter1.0/bgrabitmap/bgracolorint.pas
2015-02-08 16:52:18 -08:00

306 lines
7.1 KiB
ObjectPascal

unit BGRAColorInt;
{$mode objfpc}{$H+}
{$ifdef CPUI386}
{$define BGRACOLORINT_USEASM}
{$endif}
{$ifdef DARWIN}
{$undef BGRACOLORINT_USEASM}
{$endif}
interface
uses
BGRABitmapTypes;
type
TColorInt65536 = packed record
r,g,b,a: integer;
end;
function ColorInt65536(r,g,b,a: integer): TColorInt65536; inline; overload;
function ColorInt65536(r,g,b: integer): TColorInt65536; inline; overload;
function ColorFToColorInt65536(colorF: TColorF): TColorInt65536; inline;
function ColorInt65536ToColorF(color: TColorInt65536): TColorF;
operator +(const color1,color2: TColorInt65536): TColorInt65536; inline;
operator *(const color1,color2: TColorInt65536): TColorInt65536;
operator *(const color1: TColorInt65536; factor65536: integer): TColorInt65536;
function ColorIntToBGRA(const AColor: TColorInt65536): TBGRAPixel;
function BGRAToColorInt(const AColor: TBGRAPixel): TColorInt65536;
function BGRAToColorIntMultiply(const color1: TBGRAPixel; const color2: TColorInt65536): TColorInt65536;
implementation
function ColorInt65536(r, g, b, a: integer): TColorInt65536;
begin
result.r := r;
result.g := g;
result.b := b;
result.a := a;
end;
function ColorInt65536(r, g, b: integer): TColorInt65536;
begin
result.r := r;
result.g := g;
result.b := b;
result.a := 65536;
end;
function ColorFToColorInt65536(colorF: TColorF): TColorInt65536;
begin
result.r := round(colorF[1]*65536);
result.g := round(colorF[2]*65536);
result.b := round(colorF[3]*65536);
result.a := round(colorF[4]*65536);
end;
function ColorInt65536ToColorF(color: TColorInt65536): TColorF;
const oneOver65536 = 1/65536;
begin
result[1] := color.r*oneOver65536;
result[2] := color.g*oneOver65536;
result[3] := color.b*oneOver65536;
result[4] := color.a*oneOver65536;
end;
operator+(const color1, color2: TColorInt65536): TColorInt65536;
begin
result.r := color1.r+color2.r;
result.g := color1.g+color2.g;
result.b := color1.b+color2.b;
result.a := color1.a+color2.a;
end;
operator*(const color1, color2: TColorInt65536): TColorInt65536;
{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
asm
push edx
push ebx
push esi
mov ebx, Color1
mov esi, Color2
//ecx = @result
mov eax, [ebx] //r
imul [esi]
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx], edx
mov eax, [ebx+4] //g
imul [esi+4]
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+4], edx
mov eax, [ebx+8] //b
imul [esi+8]
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+8], edx
mov eax, [ebx+12] //a
imul [esi+12]
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+12], edx
pop esi
pop ebx
pop edx
end;
{$ELSE}
begin
result.r := int64(color1.r)*color2.r shr 16;
result.g := int64(color1.g)*color2.g shr 16;
result.b := int64(color1.b)*color2.b shr 16;
result.a := int64(color1.a)*color2.a shr 16;
end;
{$ENDIF}
operator*(const color1: TColorInt65536; factor65536: integer): TColorInt65536;
{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
asm
push edx
push ebx
push esi
mov ebx, Color1
mov esi, factor65536
//ecx = @result
mov eax, [ebx] //r
imul esi
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx], edx
mov eax, [ebx+4] //g
imul esi
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+4], edx
mov eax, [ebx+8] //b
imul esi
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+8], edx
mov eax, [ebx+12] //a
imul esi
shl edx, 16
shr eax, 16
or edx, eax
mov [ecx+12], edx
pop esi
pop ebx
pop edx
end;
{$else}
begin
result.r := int64(color1.r)*factor65536 shr 16;
result.g := int64(color1.g)*factor65536 shr 16;
result.b := int64(color1.b)*factor65536 shr 16;
result.a := int64(color1.a)*factor65536 shr 16;
end;
{$endif}
function BGRAToColorInt(const AColor: TBGRAPixel): TColorInt65536;
begin
result.r := AColor.red shl 8 + AColor.red + (AColor.red shr 7);
result.g := AColor.green shl 8 + AColor.green + (AColor.green shr 7);
result.b := AColor.blue shl 8 + AColor.blue + (AColor.blue shr 7);
result.a := AColor.alpha shl 8 + AColor.alpha+ (AColor.alpha shr 7);
end;
function BGRAToColorIntMultiply(const color1: TBGRAPixel;
const color2: TColorInt65536): TColorInt65536;
{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
asm
push ebx
push esi
mov esi, Color2
mov ebx, result
mov ecx, [Color1]
movzx eax, cl //b
mov edx, eax
shr edx, 7
add eax, edx
imul [esi+8]
shl edx, 24
shr eax, 8
or edx, eax
mov [ebx+8], edx
shr ecx, 8
movzx eax, cl //g
mov edx, eax
shr edx, 7
add eax, edx
imul [esi+4]
shl edx, 24
shr eax, 8
or edx, eax
mov [ebx+4], edx
shr ecx, 8
movzx eax, cl //r
mov edx, eax
shr edx, 7
add eax, edx
imul [esi]
shl edx, 24
shr eax, 8
or edx, eax
mov [ebx], edx
shr ecx, 8
movzx eax, cl //a
mov edx, eax
shr edx, 7
add eax, edx
imul [esi+12]
shl edx, 24
shr eax, 8
or edx, eax
mov [ebx+12], edx
pop esi
pop ebx
end;
{$ELSE}
begin
result.r := int64(color2.r)*(color1.red shr 7+color1.red) shr 8;
result.g := int64(color2.g)*(color1.green shr 7+color1.green) shr 8;
result.b := int64(color2.b)*(color1.blue shr 7+color1.blue) shr 8;
result.a := int64(color2.a)*(color1.alpha shr 7+color1.alpha) shr 8;
end;
{$ENDIF}
function ColorIntToBGRA(const AColor: TColorInt65536): TBGRAPixel;
var maxValue,invMaxValue,r,g,b: integer;
begin
if AColor.a <= 0 then
result.alpha := 0;
if AColor.a >= 65536 then
result.alpha := 255
else
result.alpha := AColor.a shr 8 - (AColor.a shr 15);
maxValue := AColor.r;
if AColor.g > maxValue then maxValue := AColor.g;
if AColor.b > maxValue then maxValue := AColor.b;
if maxValue <= 0 then
begin
result.red := 0;
result.green := 0;
result.blue := 0;
exit;
end;
if maxValue <= 65535 then
begin
if AColor.r <= 0 then result.red := 0 else
result.red := AColor.r shr 8 - (AColor.r shr 15);
if AColor.g <= 0 then result.green := 0 else
result.green := AColor.g shr 8 - (AColor.g shr 15);
if AColor.b <= 0 then result.blue := 0 else
result.blue := AColor.b shr 8 - (AColor.b shr 15);
exit;
end;
invMaxValue := (1073741824+maxValue-1) div maxValue;
maxValue := (maxValue-65535) shr 9;
if AColor.r < 0 then r := 0 else
r := AColor.r*invMaxValue shr 22 + maxValue;
if AColor.g < 0 then g := 0 else
g := AColor.g*invMaxValue shr 22 + maxValue;
if AColor.b < 0 then b := 0 else
b := AColor.b*invMaxValue shr 22 + maxValue;
if r >= 255 then result.red := 255 else
result.red := r;
if g >= 255 then result.green := 255 else
result.green := g;
if b >= 255 then result.blue := 255 else
result.blue := b;
end;
end.