Как я могу изменить цвет изображения PNG с белого на черный в Delphi?
Я использую TPNGList из Густаво Дауда версии 1.4 в Delphi XE2
Он содержит изображения PNG 256x256, которые я использую в качестве изображений кнопок.
Однако необходимо изменить цвет фона, и контрастность изображения не является хорошей.
Так что теперь у меня есть белые изображения на темном фоне.
Мне нужно изменить их на черный для светлого фона.
Есть прозрачность и ее следует сохранить. Есть только белые пиксели. Но универсальный источник для целевой функции был бы также хорош.
РЕДАКТИРОВАТЬ: После предложения для "пойти на это" я попробовал следующее, но получить только черные или белые коробки:
procedure PNGInvertWB(Image: TPngImage; AWhite: Boolean);
procedure WBInvertRGB(var R, G, B: Byte);
var
color: LongInt;
begin
if AWhite then
begin
if RGB(R, G, B) = clWhite then
begin
Color := ColorToRGB(clBlack);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
end;
end
else
begin
if RGB(R, G, B) = clBlack then
begin
Color := ColorToRGB(clWhite);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
end;
end;
end;
var
X, Y, PalCount: Integer;
Line: PRGBLine;
PaletteHandle: HPalette;
Palette: array[Byte] of TPaletteEntry;
begin
if not (Image.Header.ColorType in [COLOR_GRAYSCALE, COLOR_GRAYSCALEALPHA]) then begin
if Image.Header.ColorType = COLOR_PALETTE then begin
PaletteHandle := Image.Palette;
PalCount := GetPaletteEntries(PaletteHandle, 0, 256, Palette);
for X := 0 to PalCount - 1 do
WBInvertRGB(Palette[X].peRed, Palette[X].peGreen, Palette[X].peBlue);
SetPaletteEntries(PaletteHandle, 0, PalCount, Palette);
Image.Palette := PaletteHandle;
end
else begin
for Y := 0 to Image.Height - 1 do begin
Line := Image.Scanline[Y];
for X := 0 to Image.Width - 1 do
WBInvertRGB(Line[X].rgbtRed, Line[X].rgbtGreen, Line[X].rgbtBlue);
end;
end;
end;
end;
Я звоню, используя этот код:
procedure TDBNavigator.UpdateColor;
var
PNGImage: TPngImage;
HCColor : TColor;
procedure Invert(AImage: TImage; AWhite: boolean);
begin
ConvertToPNG(AImage.Picture.Graphic, PNGImage);
PNGInvertWB(PNGImage, not AWhite);
AImage.Picture.Graphic := PNGImage;
end;
begin
Color := ThemeManager.CurrentPallete.Color[FThemeColor];
HCColor := ThemeManager.CurrentPallete.HighContrast(FThemeColor);
if HCColor <> FCurrentColor then
begin
Invert(uiPrevious, HCColor = clWhite);
Invert(uiNext, HCColor = clWhite);
Invert(uiInsert, HCColor = clWhite);
Invert(uiPost, HCColor = clWhite);
Invert(uiCancel, HCColor = clWhite);
Invert(uiDelete, HCColor = clWhite);
Invert(uiRefresh, HCColor = clWhite);
FCurrentColor := HCColor;
end;
end;
Не уверен, какая часть не так. Это часть одного компонента, и я пытаюсь изменить изображение, назначенное во время разработки. Это было изображение PNG, которое я загрузил, 256x256 с прозрачностью.
Мне нужно использовать это изображение, я знаю, что это не кнопка. И, вероятно, есть компоненты, которые делают это. Мне нужно сделать самостоятельно, потому что конкретная библиотека, которую я использую.
Я получил идею PNGInvertWB от одной из функций Густаво в функциях PNG:
procedure MakeImageGrayscale(Image: TPngImage; Amount: Byte = 255);
Итак, у меня нет опыта работы с изображениями, что не так с этим кодом?
Вот как это выглядит на компоненте, где у меня есть изображения:
Оригинал:
После:
Я использовал следующую функцию из PNGFunctions, чтобы попробовать это:
procedure MakeImageGrayscale(Image: TPngImage; Amount: Byte = 255);
procedure GrayscaleRGB(var R, G, B: Byte);
var
X: Byte;
begin
X := Round(R * 0.30 + G * 0.59 + B * 0.11);
R := Round(R / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1));
G := Round(G / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1));
B := Round(B / 256 * (256 - Amount - 1)) + Round(X / 256 * (Amount + 1));
end;
var
X, Y, PalCount: Integer;
Line: PRGBLine;
PaletteHandle: HPalette;
Palette: array[Byte] of TPaletteEntry;
begin
//Don't do anything if the image is already a grayscaled one
if not (Image.Header.ColorType in [COLOR_GRAYSCALE, COLOR_GRAYSCALEALPHA]) then begin
if Image.Header.ColorType = COLOR_PALETTE then begin
//Grayscale every palette entry
PaletteHandle := Image.Palette;
PalCount := GetPaletteEntries(PaletteHandle, 0, 256, Palette);
for X := 0 to PalCount - 1 do
GrayscaleRGB(Palette[X].peRed, Palette[X].peGreen, Palette[X].peBlue);
SetPaletteEntries(PaletteHandle, 0, PalCount, Palette);
Image.Palette := PaletteHandle;
end
else begin
//Grayscale every pixel
for Y := 0 to Image.Height - 1 do begin
Line := Image.Scanline[Y];
for X := 0 to Image.Width - 1 do
GrayscaleRGB(Line[X].rgbtRed, Line[X].rgbtGreen, Line[X].rgbtBlue);
end;
end;
end;
end;
Где я изменил GrayscaleRGB, так как он получал каждый пиксель и менял его на оттенки серого, поэтому я полагал, что могу соответственно изменить цвет на черный или белый.
2 ответа
Будет хорошо увидеть, что у вас есть оригинал и что вы получите после выполнения этого кода
и вопрос таков: действительно ли вы уверены, что цвет всего фона равен черному или белому или близок к черному или почти к белому? Потому что вы сравниваете точный цвет RGB(R, G, B) = clWhite
попробуй это
procedure WBInvertRGB(var R, G, B: Byte);
var
color: LongInt;
begin
if AWhite then
begin
if ((R>240) and (G>240) and (B>240)) then
begin
Color := ColorToRGB(clBlack);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
end;
end
else
begin
if ((R<15) and (G<15) and (B<15)) then
begin
Color := ColorToRGB(clWhite);
R := GetRValue(Color);
G := GetGValue(Color);
B := GetBValue(Color);
end;
end;
end;
что ты получишь после?
- Тогда я полагаю, что это из-за прозрачности (измените нижний левый угол на другой цвет)
я не знаю подробностей об этом компоненте png и не знаю, есть ли у него свойство пикселей, но поставлю это в конце процедуры
Line := Image.Scanline[Image.Height - 1];
Line[0].rgbtRed:= 5;
Line[0].rgbtGreen:= 5;
Line[0].rgbtBlue:= 5;
любое изменение в результате?
- или вы идете внутри палитры кода, чем полноцветные ставят точки останова, и вы увидите, где ваш код ломается
и добавьте комментарий здесь, если это цветовая палитра - это имеет значение, потому что вы не можете изменить цвет на белый, а другой на черный. Вам нужно три ступени, одна из которых меняется с белого на красный, например, черный на белый и красный на черный