AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Rundungs problem?

Ein Thema von EWeiss · begonnen am 1. Jun 2017 · letzter Beitrag vom 1. Jun 2017
Antwort Antwort
EWeiss
(Gast)

n/a Beiträge
 
#1

Rundungs problem?

  Alt 1. Jun 2017, 17:18
Kann diese Funktion ein Rundungs Problem verursachen?

Delphi-Quellcode:
        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;
wenn ja nehme ich besser

Delphi-Quellcode:
        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;
Ich möchte nur eine Bestätigung das es so ist... Danke.

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:
        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;
gruss

Geändert von EWeiss ( 1. Jun 2017 um 17:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.151 Beiträge
 
Delphi 12 Athens
 
#2

AW: Rundungs problem?

  Alt 1. Jun 2017, 17:39
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?
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
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 1. Jun 2017 um 17:51 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: Rundungs problem?

  Alt 1. Jun 2017, 17:41
Zitat:
je mehr, um so größer rgbReserved ist, bei beiden Versionen, aber kleiner, bei großem Multiplikator, also ja ... die 2.
Wenn ich dich richtig verstehe die 2. Version mit Shift 16 verwenden.
Die shift 8 könnte also ein Rundungs Problem generieren?

Zitat:
Aber warum das "gerundete" Zwischenergebnis und nicht gleich direkt gerechnet?
auf was beziehst du das bei welchen der 3 Varianten. ?

Danke.

gruss
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.151 Beiträge
 
Delphi 12 Athens
 
#4

AW: Rundungs problem?

  Alt 1. Jun 2017, 17:49
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ß.


pBits.rgbBlue := (pBits.rgbBlue * 255) div pBits.rgbReserved; = 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).
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 1. Jun 2017 um 17:55 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: Rundungs problem?

  Alt 1. Jun 2017, 17:58
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ß.
Ich habe da ein Beispiel in C von einem Forum wo ich gerade arbeite. (englisch nicht so mein Ding)

Da wird mir gesagt! Das rundungs Probleme auftreten auf der Basis dieser Berechnung.

Zitat:
it will be on some values...
for example alpha=250, color=251... then instead of 0 you will get 255,
same with 251:252, 252:253, 253:254, 254:255, ...
if use shift by 16, then there is no this problem
Shift 16 soll das Problem beheben mag ja in C++ zutreffend sein aber unter Delphi ?
Auf Grund dieser Berechnung.

Code:
      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);
         }
      }
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.
Deshalb der Post.

gruss

Geändert von EWeiss ( 1. Jun 2017 um 18:00 Uhr)
  Mit Zitat antworten Zitat
Michael II
Online

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
732 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Rundungs problem?

  Alt 1. Jun 2017, 18:55
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.
Michael Gasser
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: Rundungs problem?

  Alt 1. Jun 2017, 19:02
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.
Danke das habe ich ja gemacht.

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
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.151 Beiträge
 
Delphi 12 Athens
 
#8

AW: Rundungs problem?

  Alt 1. Jun 2017, 19:06
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:
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;
Wie das vorberechnet wird, ist dann egal. (Float, Int8 oder Int16)

Zitat:
Danke das habe ich ja gemacht.
Nee?

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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 1. Jun 2017 um 19:18 Uhr)
  Mit Zitat antworten Zitat
Michael II
Online

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
732 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Rundungs problem?

  Alt 1. Jun 2017, 19:27
Zitat:
es geht mir darum ob nun eine Rundungsfehler auftreten kann oder nicht..
Wir verstehen einander nicht. Mir geht's ja auch genau um die möglichen Rundungsfehler.

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.
Michael Gasser
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#10

AW: Rundungs problem?

  Alt 1. Jun 2017, 19:33
Zitat:
es geht mir darum ob nun eine Rundungsfehler auftreten kann oder nicht..
Wir verstehen einander nicht. Mir geht's ja auch genau um die möglichen Rundungsfehler.

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.
Ach so
Ja das könnte ich machen.

@himitsu
Danke für die Beispiele.

gruss
  Mit Zitat antworten Zitat
Antwort Antwort


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 14:00 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