Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Bitmap-Ausschnitt einfärben (https://www.delphipraxis.net/179225-bitmap-ausschnitt-einfaerben.html)

stahli 21. Feb 2014 07:26

Bitmap-Ausschnitt einfärben
 
Ich möchte einen Teil eines Bitmaps/Canvas einfärben.
Es soll ein kleiner Effekt erkennbar sein (etwas dunkler oder etwas blauer z.B.).
Der Effekt soll in zwei Variationen anwendbar sein (mehr oder weniger abgedunkelt oder etwas anders eingefärbt).

Möglichst will ich mit dem normalen Bitmap arbeiten.

Versuche mit CopyRect und StretchBlt durchblicke ich nicht. Die Zielfläche wird meist weiß oder schwarz und ich habe kein Grundverständnis, wo ich drehen muss.

Es soll ein kleiner und einfacher Effekt sein. Ich will nur einen kleinen Unterschied zum Originalausschnitt erkennen (so eine Art Mouseover-Effekt).

Hat jemand einen Tipp?

Popov 21. Feb 2014 08:03

AW: Bitmap-Ausschnitt einfärben
 
Ich denke du kommst um ScanLine nicht herum.

Wie bekommt man nun die Farbe etwas heller oder dunkler? Ich bin an der Frage mal fast verzweifelt, die Lösung (Trick) war letztendlich simpel. Nicht versuchen die Farbe heller oder dunkler zu berechnen, sondern einfach prozentual mit weiß (heller) oder schwarz (dunkler) mischen. Das Ergebnis ist heller oder dunkler.

baumina 21. Feb 2014 08:20

AW: Bitmap-Ausschnitt einfärben
 
Zitat:

Zitat von Popov (Beitrag 1248916)
Wie bekommt man nun die Farbe etwas heller oder dunkler? Ich bin an der Frage mal fast verzweifelt, die Lösung (Trick) war letztendlich simpel. Nicht versuchen die Farbe heller oder dunkler zu berechnen, sondern einfach prozentual mit weiß (heller) oder schwarz (dunkler) mischen. Das Ergebnis ist heller oder dunkler.

Oder man verwendet die Funktion ColorAdjustLuma.

Popov 21. Feb 2014 08:30

AW: Bitmap-Ausschnitt einfärben
 
Erstens: Selbst ist der Mann

Zweitens: Kennt meine OH von D7 nicht. Und was der Bauer nicht kennt...

DeddyH 21. Feb 2014 08:59

AW: Bitmap-Ausschnitt einfärben
 
ColorAdjustLuma

Namenloser 21. Feb 2014 09:46

AW: Bitmap-Ausschnitt einfärben
 
Mach das einfach mit Scanline... es ist nicht so kompliziert wie es sich vielleicht anhört.

Ich habs grad einfach mal aus dem Kopf runtergeschrieben, weil es glaub ich länger dauern würde, es mit Worten zu erklären, und dann immer noch unklarer wäre:
Delphi-Quellcode:
function Clamp(Value: Integer; Min, Max: Integer); inline;
begin
  Result := Value;
  if Result < Min then Result := Min;
  if Result > Max then Result := Max;
end;

procedure AdjustLuminance(Bmp: TBitmap; Offset: SmallInt)
  Bmp: TBitmap;
  Pixel: PRGBQuad;
  x,y: integer;
begin
  Bmp.PixelFormat := pf32Bit;
  for y := 0 to Bmp.Height - 1 do
  begin
    // Pointer auf 1. Pixel in der Zeile holen
    Pixel := Bmp.Scanline[y];
    for x := 0 to Bmp.Width - 1 do
    begin
      Pixel^.R := Clamp(Pixel^.R + Offset, 0, 255);
      Pixel^.G := Clamp(Pixel^.G + Offset, 0, 255;
      Pixel^.B := Clamp(Pixel^.B + Offset, 0, 255);

      // ein Pixel nach rechts gehen
      inc(Pixel);
    end;
  end;
end;
Delphi-Quellcode:
AdjustLuminance(Bmp, 50); // Aufhellen
AdjustLuminance(Bmp, -50); // Abdunkeln
Für PRGBQuad musst du irgendeine Unit einbinden, ich hab es grad nicht im Kopf, welche. Oder du deklarierst dir den Record einfach selbst:
Delphi-Quellcode:
type
  PRGBQuad = ^TRGBQuad;
  TRGBQuad = packed record
    B, G, R, A: Byte;
  end;
PS: Kann sein, dass Luminance hier formal gesehen der richtige Begriff ist. Aber für einen Hover-Effekt reicht es allemal, und wenn nicht, kann man die Berechnung in der Schleife ja einfach austauschen.

stahli 21. Feb 2014 10:26

AW: Bitmap-Ausschnitt einfärben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ihr seid Helden und eine Heldin! :-)

Anbei mal meine Versuche und zwei Exen.
Ich werde es erst mal bei DrawTransparentBitmap lassen.
Das ist natürlich nicht performant, aber im Moment stört das nicht.

Mit der Lumi-Variante ist der Text nicht mehr lesbar bzw. bei positiven Werten werden weiße Flächen schwarz.

Da ich kein Verständnis für Farbänderungen habe lasse ich es erst mal dabei.
Für meinen kleinen Test reicht es erst mal.


Delphi-Quellcode:
...
unit Winapi.Windows;
...

  function Clamp(Value: Integer; Min, Max: Integer): Byte; inline;
  begin
    Result := Value;
    if Result < Min then
      Result := Min;
    if Result > Max then
      Result := Max;
  end;

  procedure AdjustLuminance(Bmp: TBitmap; Offset: SmallInt);
  var
    // Bmp: TBitmap;
    Pixel: PRGBQuad;
    X, Y: Integer;
  begin
    Bmp.PixelFormat := pf32Bit;
    for Y := ClientRect.Top to ClientRect.Bottom do
    begin
      // Pointer auf 1. Pixel in der Zeile holen
      Pixel := Bmp.Scanline[Y];
      System.Inc(Pixel, ClientRect.Left);
      for X := ClientRect.Left to ClientRect.Right do
      begin
        Pixel^.rgbRed := Clamp(Pixel^.rgbRed + Offset, 0, 255);
        Pixel^.rgbGreen := Clamp(Pixel^.rgbGreen + Offset, 0, 255);
        Pixel^.rgbBlue := Clamp(Pixel^.rgbBlue + Offset, 0, 255);

        // ein Pixel nach rechts gehen
        System.Inc(Pixel);
      end;
    end;
  end;

  procedure UnderMouseEffect;
  var
    tmpBitmap: TBitmap;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Style := bsDiagCross;
    tmpBitmap.Canvas.Brush.Color := clWhite;
    tmpBitmap.Canvas.FillRect(TRect.Create(0, 0, tmpBitmap.Width,
      tmpBitmap.Height));
    // tmpBitmap.SaveToFile('xxx.bmp');
    DrawTransparentBitmap(tmpBitmap, aBitmap.Canvas, ClientRect, $07);
    // aBitmap.Canvas.Brush.Color := clYellow;
    // aBitmap.Canvas.FillRect(aRect);
    // SetStretchBltMode(aBitmap.Canvas.Handle, COLORONCOLOR);
    // StretchBlt(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
    // ClientRect.Width, ClientRect.Height, tmpBitmap.Canvas.Handle, 0, 0,
    // tmpBitmap.Width, tmpBitmap.Height, SRCCOPY);
    // aBitmap.Canvas.CopyMode := cmWhiteness;
    // aBitmap.Canvas.CopyRect(ClientRect, tmpBitmap.Canvas,
    // tmpBitmap.Canvas.ClipRect);
    tmpBitmap.Free;
  end;

  procedure MouseDownEffect;
  var
    tmpBitmap: TBitmap;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Style := bsDiagCross;
    tmpBitmap.Canvas.Brush.Color := clWhite;
    tmpBitmap.Canvas.FillRect(TRect.Create(0, 0, tmpBitmap.Width,
      tmpBitmap.Height));
    // tmpBitmap.SaveToFile('xxx.bmp');
    DrawTransparentBitmap(tmpBitmap, aBitmap.Canvas, ClientRect, $10);
    // aBitmap.Canvas.Brush.Color := clYellow;
    // aBitmap.Canvas.FillRect(aRect);
    // SetStretchBltMode(aBitmap.Canvas.Handle, COLORONCOLOR);
    // StretchBlt(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
    // ClientRect.Width, ClientRect.Height, tmpBitmap.Canvas.Handle, 0, 0,
    // tmpBitmap.Width, tmpBitmap.Height, SRCCOPY);
    // aBitmap.Canvas.CopyMode := cmWhiteness;
    // aBitmap.Canvas.CopyRect(ClientRect, tmpBitmap.Canvas,
    // tmpBitmap.Canvas.ClipRect);
    tmpBitmap.Free;
  end;

  procedure UnderMouseEffectLumi;
  begin
    AdjustLuminance(aBitmap, -2); // Abdunkeln
  end;

  procedure MouseDownEffectLumi;
  begin
    AdjustLuminance(aBitmap, -5); // Abdunkeln
  end;

uligerhardt 21. Feb 2014 10:47

AW: Bitmap-Ausschnitt einfärben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Vielleicht ist auch Alphablending für dich interessant, z.B. hier: http://itinerantdeveloper.blogspot.d...-gdi-part.html.
Damit könntest du sowas erzielen:
Anhang 40760

Namenloser 21. Feb 2014 11:12

AW: Bitmap-Ausschnitt einfärben
 
Komisch, versuch es mal so:
Delphi-Quellcode:
      Pixel^.rgbRed := Clamp(integer(Pixel^.rgbRed) + Offset, 0, 255);
      Pixel^.rgbGreen := Clamp(integer(Pixel^.rgbGreen) + Offset, 0, 255);
      Pixel^.rgbBlue := Clamp(integer(Pixel^.rgbBlue) + Offset, 0, 255);

stahli 21. Feb 2014 11:37

AW: Bitmap-Ausschnitt einfärben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ja, AlphaBlend passt gut. :thumb:

Für den Fall, dass jemand in dem Bereich Infos sucht, hier der aktuelle Stand:

Delphi-Quellcode:
  procedure UnderMouseEffectDrawTransp;
  var
    tmpBitmap: TBitmap;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Style := bsDiagCross;
    tmpBitmap.Canvas.Brush.Color := clWhite;
    tmpBitmap.Canvas.FillRect(TRect.Create(0, 0, tmpBitmap.Width,
      tmpBitmap.Height));
    // tmpBitmap.SaveToFile('xxx.bmp');
    DrawTransparentBitmap(tmpBitmap, aBitmap.Canvas, ClientRect, $07);
    // aBitmap.Canvas.Brush.Color := clYellow;
    // aBitmap.Canvas.FillRect(aRect);
    // SetStretchBltMode(aBitmap.Canvas.Handle, COLORONCOLOR);
    // StretchBlt(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
    // ClientRect.Width, ClientRect.Height, tmpBitmap.Canvas.Handle, 0, 0,
    // tmpBitmap.Width, tmpBitmap.Height, SRCCOPY);
    // aBitmap.Canvas.CopyMode := cmWhiteness;
    // aBitmap.Canvas.CopyRect(ClientRect, tmpBitmap.Canvas,
    // tmpBitmap.Canvas.ClipRect);
    tmpBitmap.Free;
  end;

  procedure MouseDownEffectDrawTransp;
  var
    tmpBitmap: TBitmap;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Style := bsDiagCross;
    tmpBitmap.Canvas.Brush.Color := clWhite;
    tmpBitmap.Canvas.FillRect(TRect.Create(0, 0, tmpBitmap.Width,
      tmpBitmap.Height));
    // tmpBitmap.SaveToFile('xxx.bmp');
    DrawTransparentBitmap(tmpBitmap, aBitmap.Canvas, ClientRect, $10);
    // aBitmap.Canvas.Brush.Color := clYellow;
    // aBitmap.Canvas.FillRect(aRect);
    // SetStretchBltMode(aBitmap.Canvas.Handle, COLORONCOLOR);
    // StretchBlt(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
    // ClientRect.Width, ClientRect.Height, tmpBitmap.Canvas.Handle, 0, 0,
    // tmpBitmap.Width, tmpBitmap.Height, SRCCOPY);
    // aBitmap.Canvas.CopyMode := cmWhiteness;
    // aBitmap.Canvas.CopyRect(ClientRect, tmpBitmap.Canvas,
    // tmpBitmap.Canvas.ClipRect);
    tmpBitmap.Free;
  end;

  function Clamp(Value: Integer; Min, Max: Integer): Byte; inline;
  begin
    Result := Value;
    if Result < Min then
      Result := Min;
    if Result > Max then
      Result := Max;
  end;

  procedure AdjustLuminance(Bmp: TBitmap; Offset: SmallInt);
  var
    // Bmp: TBitmap;
    Pixel: PRGBQuad;
    X, Y: Integer;
  begin
    Bmp.PixelFormat := pf32Bit;
    for Y := ClientRect.Top to ClientRect.Bottom do
    begin
      // Pointer auf 1. Pixel in der Zeile holen
      Pixel := Bmp.Scanline[Y];
      System.Inc(Pixel, ClientRect.Left);
      for X := ClientRect.Left to ClientRect.Right do
      begin
        Pixel^.rgbRed := Clamp(Integer(Pixel^.rgbRed) + Offset, 0, 255);
        Pixel^.rgbGreen := Clamp(Integer(Pixel^.rgbGreen) + Offset, 0, 255);
        Pixel^.rgbBlue := Clamp(Integer(Pixel^.rgbBlue) + Offset, 0, 255);

        // ein Pixel nach rechts gehen
        System.Inc(Pixel);
      end;
    end;
  end;

  procedure UnderMouseEffectLumi;
  begin
    AdjustLuminance(aBitmap, -2); // Abdunkeln
  end;

  procedure MouseDownEffectLumi;
  begin
    AdjustLuminance(aBitmap, -5); // Abdunkeln
  end;

  procedure UnderMouseEffectAlpha;
  var
    tmpBitmap: TBitmap;
    BlendFunc: TBlendFunction;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Color := clHighlight;
    tmpBitmap.Canvas.FillRect(Rect(0, 0, tmpBitmap.Width, tmpBitmap.Height));

    // Blend a foreground image over the top - constant alpha, not per-pixel
    BlendFunc.BlendOp := AC_SRC_OVER;
    BlendFunc.BlendFlags := 0;
    BlendFunc.SourceConstantAlpha := 5;
    BlendFunc.AlphaFormat := 0;
    AlphaBlend(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
      tmpBitmap.Width, tmpBitmap.Height, tmpBitmap.Canvas.Handle, 0, 0,
      tmpBitmap.Width, tmpBitmap.Height, BlendFunc);

    tmpBitmap.Free;
  end;

  procedure MouseDownEffectAlpha;
  var
    tmpBitmap: TBitmap;
    BlendFunc: TBlendFunction;
  begin
    tmpBitmap := TBitmap.Create;
    tmpBitmap.Width := ClientRect.Width;
    tmpBitmap.Height := ClientRect.Height;
    tmpBitmap.Canvas.Brush.Color := clHighlight;
    tmpBitmap.Canvas.FillRect(Rect(0, 0, tmpBitmap.Width, tmpBitmap.Height));

    // Blend a foreground image over the top - constant alpha, not per-pixel
    BlendFunc.BlendOp := AC_SRC_OVER;
    BlendFunc.BlendFlags := 0;
    BlendFunc.SourceConstantAlpha := 20;
    BlendFunc.AlphaFormat := 0;
    AlphaBlend(aBitmap.Canvas.Handle, ClientRect.Left, ClientRect.Top,
      tmpBitmap.Width, tmpBitmap.Height, tmpBitmap.Canvas.Handle, 0, 0,
      tmpBitmap.Width, tmpBitmap.Height, BlendFunc);

    tmpBitmap.Free;
  end;
@Namenloser: Brachte keine Besserung (für mich jetzt auch nicht dringend).


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:11 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz