AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Farbe wird verändert

Ein Thema von EWeiss · begonnen am 8. Mai 2017 · letzter Beitrag vom 17. Mai 2017
Antwort Antwort
Seite 1 von 2  1 2   
EWeiss
(Gast)

n/a Beiträge
 
#1

Farbe wird verändert

  Alt 8. Mai 2017, 08:09
Ich verwende diese Funktion um Bitmaps Transparent abzuspeichern.

Das Problem ist nur das diese anscheinend nicht korrekt arbeitet.
Was könnte da falsch sein. ?

oder aber ich initialisiere das TBitmap falsch.

zum vergleich "1" das dunkle ist von dieser Funktion das andere Original.
Delphi-Quellcode:
procedure TSkinEngine.SaveBitmapToFile(ImgFile: WideString; hbmp: HBITMAP);
var
  png: TPNGImage;
  ext : string;
  Bitmap: TBitmap;
begin
  ext := ExtractFileExt(ImgFile) ;
  if SameText(ext, '.png') then
  begin
    Bitmap := TBitmap.Create;
    Bitmap.Handle := hbmp;
    Bitmap.PixelFormat := pf32bit;
    Png := PNG4TransparentBitMap(Bitmap);
    try
      png.SaveToFile(ImgFile);
    finally
      png.Free;
      Bitmap.Free;
    end;
  end;
end;
Eine andere Fehlerquelle könnte auch diese sein.

Delphi-Quellcode:
procedure SetupAlphaChannel(DC: HDC);
var
  bm: BITMAP;
  P: integer;
  Alpha: Byte;
  pBits: PRGBQuad;
begin

  FillChar(bm, sizeof(bm), 0);

  GetObject(GetCurrentObject(DC, OBJ_BITMAP), sizeof(bm), @bm);
  pBits := bm.bmBits;
  for P := (bm.bmWidth * bm.bmHeight) downto 1 do
  begin
    Alpha := SKAERO_Rgb2Gray(RGB(pBits.rgbRed, pBits.rgbGreen, pBits.rgbBlue)) and $000000FF;
    if (Alpha = 0) and (pBits.rgbReserved = 0) then
      pBits.rgbReserved := 0
    else if (pBits.rgbReserved = 0) then
      pBits.rgbReserved := 255;

    inc(pBits);
  end;
end;
Delphi-Quellcode:
function TSkinEngine.Rgb2Gray(RGBValue: COLORREF): COLORREF;
asm
  XOR ESI, ESI
  XOR EDX, EDX
  MOV ECX, RGBValue

  // Red
  MOV EAX, 19595
  MOV DL, CL
  MUL EDX
  ADD ESI, EAX

  // Green
  MOV EAX, 38470
  SHR ECX, 8
  MOV DL, CL
  MUL EDX
  ADD ESI, EAX

  // Blue
  MOV EAX, 7471
  SHR ECX, 8
  MOV DL, CL
  MUL EDX
  ADD ESI, EAX

  SHR ESI, 16
  MOV EDX, ESI

  //' Put Gray Value to a DWORD (0GGG)
  XOR EAX, EAX
  OR AL, DL
  SHL EAX, 8
  OR AL, DL
  SHL EAX, 8
  OR AL, DL

  MOV RESULT, EAX
end;
sorry ASM ist ein rotes Tuch für mich.
Wenn ich jedoch SetupAlphaChannel deaktiviere habe ich das gleiche Resultat.
Entweder ist diese in Verbindung mit RGB2Gray fehlerhaft so das es keine rolle spielt ob ich diese deaktiviere
oder die obere(der Link) berechnet die Farben nicht korrekt.


gruss

Geändert von EWeiss (11. Jul 2019 um 16:47 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.039 Beiträge
 
Delphi XE2 Professional
 
#2

AW: Farbe wird verändert

  Alt 8. Mai 2017, 10:46
Die Funktion Rgb2Gray macht im Prinzip folgendes
Gray:=Trunc(R*0.299 + G*0.587 + B*0.114)
Result:=Gray shl 16 or Gray shl 8 or Gray
Hierbei sind R,G,B die im RgbValue enthaltenen Farbanteile

Bedenklich erscheint mir, dass das Register ESI verändert wird was zu unvorhersehbaren Problemen führen kann.
Vermutlich ist das aber nicht die Ursache für dein Problem, denn die Abweichung tritt ja auch dann auf wenn die Funktion Rgb2Gray nicht eingesetzt wird.

Unabhängig hiervon würde ich abraten, die Funktion Rgb2Gray zu benutzen oder am Anfang ein Push ESI und am Ende ein Pop ESI einzufügen.

Alternativ kannst du die nachstehende Funktion RgbToGray verwenden, die deutlich kompakter ist, identische Resultate liefert und zusätzlich zu eax,edx,ecx keine weiteren Register braucht.

Code:
FUNCTION RGBtoGray(Value:ColorRef):ColorRef;
asm
      movzx   edx,al
      imul    edx,19595  // Red
      movzx   ecx,ah
      imul    ecx,38470  // Greean
      shr     eax,16
      imul    eax,7471   // Blue
      add     eax,ecx
      add     eax,edx
      shr     eax,16
      mov     ah,al
      shl     eax,8
      mov     al,ah
end;
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: Farbe wird verändert

  Alt 8. Mai 2017, 17:30
Zitat:
Alternativ kannst du die nachstehende Funktion RgbToGray verwenden
.
Danke ich werde sie mal testen und kann dabei nur auf dein wissen bezgl. ASM vertrauen.

Wo wird denn die Farbe zurück gegeben?
Bei (meiner) Funktion mit RESULT.

Wie gesagt ist ein rotes Tuch für mich.
Danke.

gruss

Geändert von EWeiss ( 8. Mai 2017 um 17:32 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#4

AW: Farbe wird verändert

  Alt 8. Mai 2017, 18:16
Es ist ein alt bekanntes Problem das beim laden von Transparenten PNG's die Transparenz verändert werden kann.
Deshalb habe ich ja diese Funktion um das zu verhindern.


Definition
  pBits: PRGBQuad; AlphaCoef: Single;
Delphi-Quellcode:
        for y := 0 to (h - 1) do
        begin
          for x := 0 to (w - 1) do
          begin
            if pBits.rgbReserved > 0 then
            begin
              AlphaCoef := (pBits.rgbReserved / 255);
              pBits.rgbBlue := round(pBits.rgbBlue / AlphaCoef);
              pBits.rgbGreen := round(pBits.rgbGreen / AlphaCoef);
              pBits.rgbRed := round(pBits.rgbRed / AlphaCoef);
            end;
            inc(pBits);
          end;
        end;
definition
AlphaCoef: Byte;
Delphi-Quellcode:
        for y := 0 to (h - 1) do
        begin
          for x := 0 to (w - 1) do
          begin
            if pBits.rgbReserved > 0 then
            begin
              AlphaCoef := pBits.rgbReserved div 255;
              if AlphaCoef > 0 then
              begin
                pBits.rgbBlue := pBits.rgbBlue div AlphaCoef;
                pBits.rgbGreen := pBits.rgbGreen div AlphaCoef;
                pBits.rgbRed := pBits.rgbRed div AlphaCoef;
              end if
            end;
            inc(pBits);
          end;
        end;
Aber beide bringen nicht den gewünschten Effekt.
Die Transparente Farbe verändert sich.

siehe Shot.

gruss

Geändert von EWeiss (11. Jul 2019 um 16:47 Uhr)
  Mit Zitat antworten Zitat
Amateurprofi

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.039 Beiträge
 
Delphi XE2 Professional
 
#5

AW: Farbe wird verändert

  Alt 8. Mai 2017, 21:04
[QUOTE=EWeiss;1370598]
Zitat:
Wo wird denn die Farbe zurück gegeben?
Bei (meiner) Funktion mit RESULT.
Bei meiner im Prinzip auch.
Assemblerfunktionen geben ordinale 32Bit-Werte in EAX zurück, 16Bit-Werte in AX und 8Bit-Werte in AL.
Das MOV Result,EAX in deiner Version ist also nicht erforderlich, denn das Ergebnis steht ja schon in EAX.
Tatsächlich ist solch eine Konstruktion eher schädlich denn sie wird in etwa so umgesetzt:
MOV [EBP-4], EAX
MOV EAX, [EBP-4]
also Speichern von EAX ins RAM, dann Lesen des soeben gespeicherten Wertes aus dem RAM in EAX.

Du kannst die korrekte Funktion ja prüfen, indem du für alle möglichen Colorref werte prüfst, ob meine Funktion die gleichen Ergebnisse bringt wie deine.
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: Farbe wird verändert

  Alt 8. Mai 2017, 21:22
Danke für die Info.

Habe sie mal eingebaut das Resultat sehe ich spätestens dann wenn meine Farbe funktioniert

gruss
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: Farbe wird verändert

  Alt 10. Mai 2017, 07:04
Mein Icon hat jetzt die richtige Farbe von daher ist das Thema erst mal erledigt.
Es lag aber nicht an der Funktion RGB2GRAY.

Ich musste dazu extra noch die Alpha Werte neu zuordnen.

gruss

Geändert von EWeiss (11. Jul 2019 um 16:47 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Farbe wird verändert

  Alt 10. Mai 2017, 10:22
Ich habe mich mal an der Funktion "PNG4TransparentBitMap" versucht, eigentlich sollte nur für das AlphaFormat "afPremultiplied" einer Sonderbehandlung notwendig sein.
Delphi-Quellcode:
function PNG4TransparentBitMap(bmp: TBitmap): TPNGImage;
var
  x, y: Integer;
  vBmpRGBA: ^TRGBAArray;
  vPngRGB: ^TRGB;
  vAlpha: Single;
begin
  Result := TPNGImage.CreateBlank(COLOR_RGBALPHA, 8, bmp.Width , bmp.Height);
  Result.CreateAlpha;

// {Wenn diese Alphaformate nicht gesondert behandelt werden müssen:}
// if bmp.AlphaFormat in [afIgnored, afDefined] then
// begin
// Result.Canvas.CopyMode:= cmSrcCopy;
// Result.Canvas.Draw(0,0,bmp);
// end
// else

  for y := 0 to pred(bmp.Height) do
  begin
    vBmpRGBA := bmp.ScanLine[y];
    vPngRGB := Result.Scanline[y];

    for x := 0 to pred(bmp.width) do
    begin
      Result.AlphaScanline[y][x] := vBmpRGBA[x].A;
      vPngRGB^.b := vBmpRGBA[x].b;
      vPngRGB^.r := vBmpRGBA[x].r;
      vPngRGB^.g := vBmpRGBA[x].g;

      case bmp.AlphaFormat of
        afIgnored:
          Result.AlphaScanline[y][x] := 255;
        afPremultiplied:
          begin
            if vBmpRGBA[x].A <> 0 then
            begin
              vAlpha := 255 / vBmpRGBA[x].A;
              vPngRGB^.b := round(vPngRGB^.b * vAlpha);
              vPngRGB^.r := round(vPngRGB^.r * vAlpha);
              vPngRGB^.g := round(vPngRGB^.g * vAlpha);
            end
            else
            begin
              {voll transparente Bereiche weiß}
              vPngRGB^.b := 255;
              vPngRGB^.r := 255;
              vPngRGB^.g := 255;
            end
          end;
        afDefined:
          ;
      end;

      inc(vPngRGB);
    end;
  end;
end;
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: Farbe wird verändert

  Alt 10. Mai 2017, 16:43
Hmm.. also ich muss das teil nochmal extra durch diese Funktion jagen damit mein Image die Transparente Farbe behält.
Lasse ich sie weg ist das Image Grau.
Delphi-Quellcode:
         if GetObject(hbmReturn, sizeof(bm), @bm) <> 0 then
         begin
           pBits := bm.bmBits;

           for a := 0 to (Height - 1) do
           begin
             for b := 0 to (Width - 1) do
             begin
               if pBits.rgbReserved > 0 then
               begin
                 AlphaCoef := (pBits.rgbReserved / 255);
                 pBits.rgbBlue := round(pBits.rgbBlue / AlphaCoef);
                 pBits.rgbGreen := round(pBits.rgbGreen / AlphaCoef);
                 pBits.rgbRed := round(pBits.rgbRed / AlphaCoef);
               end;
               inc(pBits);
             end;
           end;
         end;
Also deine geänderte Version zerschießt die ganze Transparenz.
Habe es extra mal getestet.

gruss

Geändert von EWeiss (11. Jul 2019 um 16:47 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#10

AW: Farbe wird verändert

  Alt 11. Mai 2017, 08:41
So hab wieder die ganze Nacht rumgemacht jetzt funktionieren die Farben wie sie sollen.

Zum vergleich.. das Bild in diesen Beitrag und das hier.
Damit ist das erst mal erledigt.

gruss

Geändert von EWeiss (11. Jul 2019 um 16:47 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:19 Uhr.
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