TPNGImage
nie jest konieczne, tak samo jak kanał alpha. Wszystko co potrzebujesz można wykonać za pomocą standardowej klasy TBitmap
, przechowującej składowe pikseli w formacie BGR
.
Twój przypadek jest dość prosty w implementacji, dlatego że potrzebujesz ”wylać” kolor biały na istniejący obraz, a to nic innego jak rozjaśnienie obrazu. Dlatego zamiast robić protezę prezroczystości białego kwadratu, powinieneś się skupić na algorytmie rozjaśniającym piksele (a ten jest krótki i bardzo prosty). Natomiast namalowanie finalnej białej linii to nic innego jak wywołanie Canvas.MoveTo
i Canvas.LineTo
(AFAIR w Delphi 7 nie ma Canvas.Line
, więc dwie metody zamiast jednej).
Druga sprawa – Canvas.Pixels
jest powolny. Właściwość ta używa gettera, który najpierw pozyskuje wskaźnik na konkretny piksel w całym bloku danych obrazu, następnie łączy wszystkie składowe w 32-bitową liczbę i ją zwraca. Ty musiałbyś znów tę liczbę podzielić na składowe, zmodyfikować je, złączyć w jedną liczbę i za pomocą Canvas.Pixels
wpisać do pamięci obrazu. A setter tej właściwości znów musiałby szukać miejsca, rozdzielać wartość na składowe i wpisywać do pamięci. To dość powolne, choć w przypadku tak małego obrazu, efektywność nie ma większego znaczenia.
Sugeruję więc skorzystanie z właściwości TBitmap.ScanLine
do pozyskania wskaźników na pierwszy piksel każdego rzędu oraz z prostej arytmetyki do rozjaśniania składowych.
Poniżej podaję deklaracje potrzebnych struktur (te mogą istnieć w bibliotece standardowej), a także definicje funkcji rozjaśniającej składową oraz tej głównej, rozjaśniającej cały obraz. Kod pisany z palca, więc wymaga sprawdzenia. Tym bardziej, że Delphi 7 nie widziałem na oczy od wielu lat.
Kopiuj
type
TRGBTriple = packed record
B, G, R: Byte;
end;
type
PRGBTripleArr = ^TRGBTripleArr;
TRGBTripleArr = packed array [0 .. MaxInt div SizeOf(TRGBTriple) - 1] of TRGBTriple;
function LightenComponent(AComponent, APercent: Byte): Byte;
begin
APercent := 100 - APercent;
Result := Trunc(AComponent * APercent / 100) + Round(255 - APercent / 100 * 255);
end;
procedure LightenBitmap(ABitmap: TBitmap; APercent: Byte);
var
Line: PRGBTripleArr;
LineIndex, PixelIndex: Integer;
begin
ABitmap.BeginUpdate();
try
for LineIndex := 0 to ABitmap.Height - 1 do
begin
Line := ABitmap.ScanLine[LineIndex];
for PixelIndex := 0 to ABitmap.Width - 1 do
with Line^[PixelIndex] do
begin
B := LightenComponent(B, APercent);
G := LightenComponent(G, APercent);
R := LightenComponent(R, APercent);
end;
end;
finally
ABitmap.EndUpdate();
end;
end;
W razie czego możesz sobie stworzyć osobny typ dla procentażu:
Kopiuj
type
TPercent = 0 .. 100;
Taki typ możesz wykorzystać do deklaracji parametrów obu funkcji (dla APercent
).
Na koniec, jedyne co musisz zrobić, to wywołać funkcję LightenBitmap
– w pierwszym parametrze podać bitmapę źródłową, a w drugim procentowy stopień rozjaśnienia (im wyższy, tym obraz zostanie bardziej rozjaśniony; jeśli podasz 0
to kolory nie zmienią się, a jeśli 100
to obraz wyjdzie biały):
Kopiuj
LightenBitmap(Bitmap, 50);
I to tyle.