2013-12-18 194 views
3

我使用德尔福XE2中Gustavo Daud版本1.4的TPNGList如何在Delphi中将PNG图像的颜色从白色更改为黑色?

它使用一些PNG 256x256图像作为按钮图像。

但是有必要改变背景颜色和图像的对比度不好。

所以我现在有黑色背景的白色图像。

我需要将它们更改为浅色背景。

有透明度,应保存。只有白色像素。但是,目标函数的一个通用源也是很棒的。

编辑: 继sugestion为“去了”我曾尝试以下,但只得到黑色或白色盒子:

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具有透明度。

我需要使用TImage,我知道它不是一个按钮。并且可能有组件会这样做。我需要自己制作,因为我正在使用特定的库。

我得到了PNGInvertWB想法从PNGFunctions的古斯塔沃功能之一:

procedure MakeImageGrayscale(Image: TPngImage; Amount: Byte = 255); 

所以,我必须与所有图像没有经验,什么是错的代码?

这是怎么看起来像在组件上,我有自己的设计:

原文: Original

后: After this funcion above

我用下面的函数从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; 

我在哪里改变了e GrayscaleRGB,因为它获取每个像素并将其更改为灰度,因此我相信我可以相应地变为黑色或白色。

+1

我会保留一对外部准备/修改的图像集。如果涉及部分透明度,则反锯齿(局部)部分在非预期的颜色值背景上看起来很糟糕。 –

回答

0

会很好看你有什么原来的一个,你这个代码后得到的执行

,问题是: 你真的要确保整个背景的颜色是EQU为黑色或白色,或者是接近黑色或接近白色? Becouse你比较精确的颜色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; 

你得到了什么之后?

+0

谢谢你,我已经测试了你的建议并保持不变。我已经更新了问题,并在前后添加了图片。它将所有像素变成白色或黑色,具体取决于所选内容。这就像获得所有的背景像素并进行转换。但它应该是透明的,不确定这是否意味着没有像素或某种代码。你会看到我用来派生函数的原始函数。非常感谢。 –

0
  1. 话,我想,这是becouse的透明度(左下角改变一些不同的颜色)

我不知道这个PNG组件的详细信息,如果有像素财产 不知道但把这个过程的结尾

Line := Image.Scanline[Image.Height - 1]; 
Line[0].rgbtRed:= 5; 
Line[0].rgbtGreen:= 5; 
Line[0].rgbtBlue:= 5; 

结果的任何变化?

  1. 或者你去palete代码里面比全彩 放断点,你会看到你的代码休息

这里添加评论,如果这是颜色palete - 这个让差becouse你不能改变颜色为白色,另一种为黑色。你需要三次陡峭的变化红黑到白和红到黑

相关问题