![]() |
Farbe wird verändert
![]() 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:
Eine andere Fehlerquelle könnte auch diese sein.
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;
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:
sorry ASM ist ein rotes Tuch für mich.
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; 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 |
AW: Farbe wird verändert
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; |
AW: Farbe wird verändert
Zitat:
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 |
AW: Farbe wird verändert
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
Delphi-Quellcode:
pBits: PRGBQuad;
Delphi-Quellcode:
AlphaCoef: Single;
Delphi-Quellcode:
definition
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; AlphaCoef: Byte;
Delphi-Quellcode:
Aber beide bringen nicht den gewünschten Effekt.
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; Die Transparente Farbe verändert sich. siehe Shot. gruss |
AW: Farbe wird verändert
[QUOTE=EWeiss;1370598]
Zitat:
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. |
AW: Farbe wird verändert
Danke für die Info. ;)
Habe sie mal eingebaut das Resultat sehe ich spätestens dann wenn meine Farbe funktioniert ;) gruss |
AW: Farbe wird verändert
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 |
AW: Farbe wird verändert
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; |
AW: Farbe wird verändert
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:
Also deine geänderte Version zerschießt die ganze Transparenz.
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; Habe es extra mal getestet. gruss |
AW: Farbe wird verändert
So hab wieder die ganze Nacht rumgemacht jetzt funktionieren die Farben wie sie sollen.
Zum vergleich.. ![]() Damit ist das erst mal erledigt. gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz