![]() |
Rundungs problem?
Kann diese Funktion ein Rundungs Problem verursachen?
Delphi-Quellcode:
wenn ja nehme ich besser
for y := 0 to (imgH - 1) do
begin for x := 0 to (imgW - 1) do begin if pBits.rgbReserved > 0 then begin AlphaCoef := (255 shl 8) div pBits.rgbReserved; pBits.rgbBlue := ((pBits.rgbBlue * AlphaCoef) shr 8); pBits.rgbGreen := ((pBits.rgbGreen * AlphaCoef) shr 8); pBits.rgbRed := ((pBits.rgbRed * AlphaCoef) shr 8); end; inc(pBits); end; end;
Delphi-Quellcode:
Ich möchte nur eine Bestätigung das es so ist... Danke.
for y := 0 to (imgH - 1) do
begin for x := 0 to (imgW - 1) do begin if pBits.rgbReserved > 0 then begin AlphaCoef := (255 shl 16) div pBits.rgbReserved; pBits.rgbBlue := ((pBits.rgbBlue * AlphaCoef) shr 16); pBits.rgbGreen := ((pBits.rgbGreen * AlphaCoef) shr 16); pBits.rgbRed := ((pBits.rgbRed * AlphaCoef) shr 16); end; inc(pBits); end; end; vorher hatte ich es so.. was aber bedingt durch single(float) um ein 4faches langsamer ist. bitmap: 4096x4096 elapsed: 2763 bei Verwendung von single. elapsed: 627 und ULong.
Delphi-Quellcode:
gruss
for IntI := (bm.bmWidth * bm.bmHeight) downto 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; |
AW: Rundungs problem?
je mehr, um so größer rgbReserved ist, bei beiden Versionen, aber kleiner, bei großem Multiplikator, also ja ... die 2.
Aber warum das "gerundete" Zwischenergebnis und nicht gleich direkt gerechnet?
Delphi-Quellcode:
pBits.rgbBlue := (pBits.rgbBlue * 255) div pBits.rgbReserved;
Wenn es schnell sein soll dan kann man die 3 Werte auch zusammen in einem MMX-Register verrechnen lassen. Und pssst
Delphi-Quellcode:
for allesineinerschleife := 0 to imgH * imgW - 1 do
// oder for allesineinerschleife := imgH * imgW - 1 downto 0 do // spart noch die interne Ende-Variable, da Ende immer 0 |
AW: Rundungs problem?
Zitat:
Die shift 8 könnte also ein Rundungs Problem generieren? Zitat:
Danke. gruss |
AW: Rundungs problem?
AlphaCoef ist ein gerundetes Zwischenergebnis.
Bei 16 ist das natürlich größer und somit die Rundung geringer. Aber die Rundung ist dennoch bei 8 und 16 drin, nur eben nicht gleich groß.
Delphi-Quellcode:
=
pBits.rgbBlue := (pBits.rgbBlue * 255) div pBits.rgbReserved;
Delphi-Quellcode:
pBits.rgbBlue := MulDiv(pBits.rgbBlue, 255, pBits.rgbReserved);
aber da deine Werte so klein sind, dass es keinen Überlauf gibt, wäre MulDiv egal (unnötig). |
AW: Rundungs problem?
Zitat:
Da wird mir gesagt! Das rundungs Probleme auftreten auf der Basis dieser Berechnung. Zitat:
Auf Grund dieser Berechnung.
Code:
Ich bin da jetzt etwas unsicher da ich ihm gesagt habe das ich mit Shift 8 eigentlich keine Sichtbaren unterschiede sehe da mein Icon die Transparenz hat die es haben soll.
int err = 0;
for (ULONG a = 0; a < 256; a++) { float rAlphaCoef = (float)((float)a / 255.0f); ULONG uAlphaCoef = a ? ((255 << 8) / a) : 0; for (ULONG c = 0; c < 256; c++) { BYTE n = (BYTE)(int)((float)c / rAlphaCoef); BYTE m = (BYTE)(((ULONG)c * uAlphaCoef) >> 8); if (n != m && abs(n - m) > 1) wprintf(L"error: a: %03d; c: %03d [n: %05d, m: %05d] %i\n", a, c, n, m, ++err); } } Deshalb der Post. ;) gruss |
AW: Rundungs problem?
Hallo A.Weiss
deine Funktion "Berechne Farbwert'" hängt ja von 2 Parametern Alpha und Farbwert ab. Wenn die Werte von Alpha und Farbwert in [0..255] liegen, dann schreib doch rasch eine Routine for Alpha := 0 to 255 do for FarbWert := 0 to 255 do... und berechne Farbwert' einerseits nach deiner alten "float basierten Version" und andererseits nach deinen beiden neuen "int Versionen" und vergleiche die Resultate. Dann weisst du ganz genau was Sache ist. |
AW: Rundungs problem?
Zitat:
bitmap: 4096x4096 elapsed: 2763 bei Verwendung von single. elapsed: 627 und ULong. es geht mir darum ob nun eine Rundungsfehler auftreten kann oder nicht.. Ich konnte keinen ausmachen aber es wird mir so im C++ Forum berichtet ;) Nun wem oder was soll man nun glauben. Also unter C++ soll er auftreten und in Delphi nach meinen Tests aber nicht. Was stimmt denn nun. gruss |
AW: Rundungs problem?
Och, so viel ist das auch nicht, da kann man docg problemlos alle Varianten vorberechnen und dann nur noch aus der Liste picken.
Delphi-Quellcode:
Wie das vorberechnet wird, ist dann egal. (Float, Int8 oder Int16)
type
PColorArray = ^TColorArray; TColorArray = array[0..255] of Integer; TAlphaArray = array[0..255] of TColorArray; var AlphaArray: TAlphaArray; ColorArray: PColorArray; for IntI := (bm.bmWidth * bm.bmHeight) - 1 downto 0 do begin if pBits.rgbReserved <> 0 then begin ColorArray := @AlphaArray[pBits.rgbReserved] pBits.rgbBlue := ColorArray[pBits.rgbBlue]; pBits.rgbGreen := ColorArray[pBits.rgbGreen]; pBits.rgbRed := ColorArray[pBits.rgbRed]; end; Inc(pBits); end; Zitat:
Einmal alle Werte mit deiner Variante berechnen, dann nochmal mit 8 und/oder 16 und sie nebeneinander stellen.
Delphi-Quellcode:
for rgbReserved := 0 to 255 do
for rgbBlue := 0 to 255 do begin AlphaCoef1 := 255 div rgbReserved; // auch mal zum Spaß die extemen Rundungsfehler rgbBlue1 := (rgbBlue * AlphaCoef1); AlphaCoef8 := (255 shl 8) div rgbReserved; rgbBlue8 := ((rgbBlue * AlphaCoef8) shr 8); AlphaCoef16 := (255 shl 16) div rgbReserved; rgbBlue16 := ((rgbBlue * AlphaCoef16) shr 16); AlphaCoefF := (rgbReserved / 255); rgbBlueF := Trunc(rgbBlue / AlphaCoefF); // Trunc statt Round, damit es vergleichbar ist, da DIV/SHR auch abrundet //rgbBlueF := Trunc(rgbBlue / (rgbReserved / 255)); // frei nach den mathematischen Regeln auflösen //rgbBlueF := Trunc(rgbBlue / rgbReserved * 255); //rgbBlueF := Trunc(rgbBlue * 255 / rgbReserved); rgbBlueD := (rgbBlue * 255) div rgbReserved; AddToMemo(rgbReserved, rgbBlue, rgbBlue1, rgbBlue8, rgbBlue16, rgbBlueF, rgbBlueD); end; |
AW: Rundungs problem?
Zitat:
Du kannst leicht testen, ob Rundungsfehler auftreten, indem du einfach alle möglichen Resultate für alle drei Varianten ausrechnest. Noch einmal: Da dein Alpha Werte in [0..255] und deine Farbwerte Werte in [0..255] annehmen können, musst du pro Variante genau 256x256 Resultate berechnen (und diese miteinander vergleichen) und weisst danach ganz genau, ob Rundungsfehler auftreten oder nicht. Grund: Du hast dann alle Fälle, welche auftreten können berücksichtigt. |
AW: Rundungs problem?
Zitat:
Ja das könnte ich machen. @himitsu Danke für die Beispiele. gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:52 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-2025 by Thomas Breitkreuz