3

Delphi XE2 で Gustavo Daud バージョン 1.4 の TPNGList を使用しています

ボタン画像として使用する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;

どの部分が間違っているかわかりません。これは 1 つのコンポーネントの一部であり、設計時に割り当てられたイメージを変更しようとしています。私が読み込んだのは、透明度のある 256x256 の PNG 画像でした。

その TImage を使用する必要があります。ボタンではないことはわかっています。そして、おそらくそれを行うコンポーネントがあります。私が使用している特定のライブラリのため、自分で作成する必要があります。

PNGFunctions の Gustavo 関数の 1 つから PNGInvertWB のアイデアを得ました。

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 を変更したところ、それに応じて黒または白に変更できると信じていました。

4

2 に答える 2

0
  1. 次に、これは透明性のためだと思います(左下隅を別の色に変更します)

このpngコンポーネントの詳細がわからず、ピクセルプロパティがあるかどうかもわかりませんが、これを手順の最後に置きます

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

結果に変化は?

  1. または、フルカラーがブレークポイントを配置するよりもパレットコード内に移動すると、コードがどこで壊れているかがわかります

これがカラー パレットである場合は、ここにコメントを追加します。色を白に変更したり、別の色を黒に変更したりできないため、違いが生じます。白から赤、黒から白、赤から黒など、3 つの急勾配が必要です。

于 2013-12-21T19:11:08.340 に答える