Skip to content

Commit

Permalink
dev
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Jan 29, 2024
1 parent a05ed94 commit 6abcd22
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 62 deletions.
224 changes: 167 additions & 57 deletions Source/image/simba.image.pas
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,10 @@ TSimbaImage = class(TSimbaBaseClass)
procedure DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor);

procedure SetSize(NewWidth, NewHeight: Integer);

procedure SetAlpha(Value: Byte); overload;
procedure SetAlpha(Points: TPointArray; Value: Byte); overload;
procedure SetAlpha(Color: TColor; Value: Byte); overload;

function ResizeNN(NewWidth, NewHeight: Integer): TSimbaImage;
function ResizeBilinear(NewWidth, NewHeight: Integer): TSimbaImage;
Expand Down Expand Up @@ -1312,6 +1314,40 @@ function TSimbaImage.RotateBilinear(Radians: Single; Expand: Boolean): TSimbaIma
var
CosAngle, SinAngle: Single;

function ShouldRotate(var p0, p1, p2, p3: TColorBGRA): Boolean; inline;
begin
if (p0.A > 0) or (p1.A > 0) or (p2.A > 0) or (p3.A > 0) then
begin
if (p0.A = 0) then
begin
if (p1.A > 0) then p0 := p1 else
if (p2.A > 0) then p0 := p2 else
if (p3.A > 0) then p0 := p3;
end;
if (p1.A = 0) then
begin
if (p0.A > 0) then p1 := p0 else
if (p2.A > 0) then p1 := p2 else
if (p3.A > 0) then p1 := p3;
end;
if (p2.A = 0) then
begin
if (p0.A > 0) then p2 := p0 else
if (p1.A > 0) then p2 := p1 else
if (p3.A > 0) then p2 := p3;
end;
if (p3.A = 0) then
begin
if (p0.A > 0) then p3 := p0 else
if (p1.A > 0) then p3 := p1 else
if (p2.A > 0) then p3 := p2;
end;

Result := True;
end else
Result := False;
end;

procedure RotateNoExpand;
var
x, y, w, h: Integer;
Expand All @@ -1323,6 +1359,7 @@ function TSimbaImage.RotateBilinear(Radians: Single; Expand: Boolean): TSimbaIma
MidX, MidY: Single;
begin
Result.SetSize(FWidth, FHeight);
Result.SetAlpha(0);

MidX := (FWidth - 1) / 2;
MidY := (FHeight - 1) / 2;
Expand Down Expand Up @@ -1353,18 +1390,22 @@ function TSimbaImage.RotateBilinear(Radians: Single; Expand: Boolean): TSimbaIma
p2 := FData[cY * FWidth + fX];
p3 := FData[cY * FWidth + cX];

TopR := dxMinus1 * p0.R + dx * p1.R;
TopG := dxMinus1 * p0.G + dx * p1.G;
TopB := dxMinus1 * p0.B + dx * p1.B;
BtmR := dxMinus1 * p2.R + dx * p3.R;
BtmG := dxMinus1 * p2.G + dx * p3.G;
BtmB := dxMinus1 * p2.B + dx * p3.B;

with Result.Data[Y * Result.Width + X] do
if ShouldRotate(p0, p1, p2, p3) then
begin
R := EnsureRange(Round(dyMinus1 * TopR + dy * BtmR), 0, 255);
G := EnsureRange(Round(dyMinus1 * TopG + dy * BtmG), 0, 255);
B := EnsureRange(Round(dyMinus1 * TopB + dy * BtmB), 0, 255);
TopR := dxMinus1 * p0.R + dx * p1.R;
TopG := dxMinus1 * p0.G + dx * p1.G;
TopB := dxMinus1 * p0.B + dx * p1.B;
BtmR := dxMinus1 * p2.R + dx * p3.R;
BtmG := dxMinus1 * p2.G + dx * p3.G;
BtmB := dxMinus1 * p2.B + dx * p3.B;

with Result.Data[Y * Result.Width + X] do
begin
R := EnsureRange(Round(dyMinus1 * TopR + dy * BtmR), 0, 255);
G := EnsureRange(Round(dyMinus1 * TopG + dy * BtmG), 0, 255);
B := EnsureRange(Round(dyMinus1 * TopB + dy * BtmB), 0, 255);
A := ALPHA_OPAQUE;
end;
end;
end;
end;
Expand All @@ -1388,6 +1429,7 @@ function TSimbaImage.RotateBilinear(Radians: Single; Expand: Boolean): TSimbaIma
MidY := (NewHeight - 1) / 2;

Result.SetSize(NewWidth, NewHeight);
Result.SetAlpha(0);

Dec(NewWidth);
Dec(NewHeight);
Expand Down Expand Up @@ -1415,18 +1457,22 @@ function TSimbaImage.RotateBilinear(Radians: Single; Expand: Boolean): TSimbaIma
p2 := FData[cY * FWidth + fX];
p3 := FData[cY * FWidth + cX];

TopR := dxMinus1 * p0.R + dx * p1.R;
TopG := dxMinus1 * p0.G + dx * p1.G;
TopB := dxMinus1 * p0.B + dx * p1.B;
BtmR := dxMinus1 * p2.R + dx * p3.R;
BtmG := dxMinus1 * p2.G + dx * p3.G;
BtmB := dxMinus1 * p2.B + dx * p3.B;

with Result.Data[Y * Result.Width + X] do
if ShouldRotate(p0, p1, p2, p3) then
begin
R := EnsureRange(Round(dyMinus1 * TopR + dy * BtmR), 0, 255);
G := EnsureRange(Round(dyMinus1 * TopG + dy * BtmG), 0, 255);
B := EnsureRange(Round(dyMinus1 * TopB + dy * BtmB), 0, 255);
TopR := dxMinus1 * p0.R + dx * p1.R;
TopG := dxMinus1 * p0.G + dx * p1.G;
TopB := dxMinus1 * p0.B + dx * p1.B;
BtmR := dxMinus1 * p2.R + dx * p3.R;
BtmG := dxMinus1 * p2.G + dx * p3.G;
BtmB := dxMinus1 * p2.B + dx * p3.B;

with Result.Data[Y * Result.Width + X] do
begin
R := EnsureRange(Round(dyMinus1 * TopR + dy * BtmR), 0, 255);
G := EnsureRange(Round(dyMinus1 * TopG + dy * BtmG), 0, 255);
B := EnsureRange(Round(dyMinus1 * TopB + dy * BtmB), 0, 255);
A := ALPHA_OPAQUE;
end;
end;
end;
end;
Expand Down Expand Up @@ -1456,11 +1502,15 @@ function TSimbaImage.GreyScale: TSimbaImage;

for i := (FHeight * FWidth - 1) downto 0 do
begin
Lum := Round(Src^.R * 0.3 + Src^.G * 0.59 + Src^.B * 0.11);
Dest^.A := Src^.A;
if (Dest^.A > 0) then
begin
Lum := Round(Src^.R * 0.3 + Src^.G * 0.59 + Src^.B * 0.11);

Dest^.R := Lum;
Dest^.G := Lum;
Dest^.B := Lum;
Dest^.R := Lum;
Dest^.G := Lum;
Dest^.B := Lum;
end;

Inc(Src);
Inc(Dest);
Expand Down Expand Up @@ -1504,9 +1554,13 @@ function TSimbaImage.Invert: TSimbaImage;

for I := (FHeight * FWidth - 1) downto 0 do
begin
Dest^.R := not Src^.R;
Dest^.G := not Src^.G;
Dest^.B := not Src^.B;
Dest^.A := Src^.A;
if (Dest^.A > 0) then
begin
Dest^.R := not Src^.R;
Dest^.G := not Src^.G;
Dest^.B := not Src^.B;
end;

Inc(Src);
Inc(Dest);
Expand All @@ -1528,9 +1582,13 @@ function TSimbaImage.Posterize(Value: Integer): TSimbaImage;

for I := (FHeight * FWidth - 1) downto 0 do
begin
Dest^.R := Min(Round(Src^.R / Value) * Value, 255);
Dest^.G := Min(Round(Src^.G / Value) * Value, 255);
Dest^.B := Min(Round(Src^.B / Value) * Value, 255);
Dest^.A := Src^.A;
if (Dest^.A > 0) then
begin
Dest^.R := Min(Round(Src^.R / Value) * Value, 255);
Dest^.G := Min(Round(Src^.G / Value) * Value, 255);
Dest^.B := Min(Round(Src^.B / Value) * Value, 255);
end;

Inc(Src);
Inc(Dest);
Expand Down Expand Up @@ -1991,6 +2049,19 @@ procedure TSimbaImage.SetAlpha(Points: TPointArray; Value: Byte);
FData[P.Y * FWidth + P.X].A := Value;
end;

procedure TSimbaImage.SetAlpha(Color: TColor; Value: Byte);
var
BGRA: TColorBGRA;
X, Y: Integer;
begin
BGRA := Color.ToBGRA();

for Y := 0 to FHeight - 1 do
for X := 0 to FWidth - 1 do
if FData[Y * FWidth + X].EqualsIgnoreAlpha(BGRA) then
FData[Y * FWidth + X].A := Value;
end;

function TSimbaImage.ResizeNN(NewWidth, NewHeight: Integer): TSimbaImage;
var
X, Y, W, H: Integer;
Expand All @@ -2006,6 +2077,41 @@ function TSimbaImage.ResizeNN(NewWidth, NewHeight: Integer): TSimbaImage;
end;

function TSimbaImage.ResizeBilinear(NewWidth, NewHeight: Integer): TSimbaImage;

function ShouldResize(var p0, p1, p2, p3: TColorBGRA): Boolean; inline;
begin
if (p0.A > 0) or (p1.A > 0) or (p2.A > 0) or (p3.A > 0) then
begin
if (p0.A = 0) then
begin
if (p1.A > 0) then p0 := p1 else
if (p2.A > 0) then p0 := p2 else
if (p3.A > 0) then p0 := p3;
end;
if (p1.A = 0) then
begin
if (p0.A > 0) then p1 := p0 else
if (p2.A > 0) then p1 := p2 else
if (p3.A > 0) then p1 := p3;
end;
if (p2.A = 0) then
begin
if (p0.A > 0) then p2 := p0 else
if (p1.A > 0) then p2 := p1 else
if (p3.A > 0) then p2 := p3;
end;
if (p3.A = 0) then
begin
if (p0.A > 0) then p3 := p0 else
if (p1.A > 0) then p3 := p1 else
if (p2.A > 0) then p3 := p2;
end;

Result := True;
end else
Result := False;
end;

var
X, Y, OldX, OldY: Integer;
p0, p1, p2, p3: TColorBGRA;
Expand All @@ -2016,6 +2122,7 @@ function TSimbaImage.ResizeBilinear(NewWidth, NewHeight: Integer): TSimbaImage;
begin
Result := TSimbaImage.Create(NewWidth, NewHeight);

Color := DefaultPixel;
SrcRows := RowPtrs;

RatioX := (FWidth - 1) / NewWidth;
Expand All @@ -2034,31 +2141,34 @@ function TSimbaImage.ResizeBilinear(NewWidth, NewHeight: Integer): TSimbaImage;
p2 := SrcRows[OldY + 1, OldX ];
p3 := SrcRows[OldY + 1, OldX + 1];

dX := ratioX * X - OldX;
dY := ratioY * Y - OldY;

Color.R := Trunc(
p0.R * (1-dX) * (1-dY) +
p1.R * (dX * (1-dY)) +
p2.R * (dY * (1-dX)) +
p3.R * (dX * dY)
);

Color.G := Trunc(
p0.G * (1-dX) * (1-dY) +
p1.G * (dX * (1-dY)) +
p2.G * (dY * (1-dX)) +
p3.G * (dX * dY)
);

Color.B := Trunc(
p0.B * (1-dX) * (1-dY) +
p1.B * (dX * (1-dY)) +
p2.B * (dY * (1-dX)) +
p3.B * (dX * dY)
);

Result.Data[Y * NewWidth + X] := Color;
if ShouldResize(p0, p1, p2, p3) then
begin
dX := ratioX * X - OldX;
dY := ratioY * Y - OldY;

Color.R := Trunc(
p0.R * (1-dX) * (1-dY) +
p1.R * (dX * (1-dY)) +
p2.R * (dY * (1-dX)) +
p3.R * (dX * dY)
);

Color.G := Trunc(
p0.G * (1-dX) * (1-dY) +
p1.G * (dX * (1-dY)) +
p2.G * (dY * (1-dX)) +
p3.G * (dX * dY)
);

Color.B := Trunc(
p0.B * (1-dX) * (1-dY) +
p1.B * (dX * (1-dY)) +
p2.B * (dY * (1-dX)) +
p3.B * (dX * dY)
);

Result.Data[Y * NewWidth + X] := Color;
end;
end;
end;

Expand Down
2 changes: 1 addition & 1 deletion Source/image/simba.image_gaussblur.pas
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ procedure imgGaussBlur(radius: Double; var r, g, b: TByteArray; width, height: I

boxes := boxesForGauss(radius, 3);

gaussBlur_4(r, outR, width, height-1, radius, boxes);
gaussBlur_4(r, outR, width, height, radius, boxes);
gaussBlur_4(g, outG, width, height, radius, boxes);
gaussBlur_4(b, outB, width, height, radius, boxes);

Expand Down
Loading

0 comments on commit 6abcd22

Please sign in to comment.