- 12V Akku mit 280 Ah bauen         
Seite 5 von 7 ErsteErste ... 34567 LetzteLetzte
Ergebnis 41 bis 50 von 63

Thema: Farben nach R,G,B umwandeln in 4-stell. hex-code?

  1. #41
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Anzeige

    E-Bike
    Ich habe gestern Abend ja noch diese Varianten ausprobiert.

    Die Eine:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t)((color16 / 2048)*8);
       G = (uint8_t)((color16 & 2016)/8);
       B = (uint8_t)((color16 & 31)*8);
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    und die Andere:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = uint8_t((color16 / 2048)*8);
       G = uint8_t((color16 & 2016)/8);
       B = uint8_t((color16 & 31)*8);
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    Beide liefern dasselbe Ergebnis (sogar heute Morgen noch):
    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72
    Dasselbe Ergebnis erzielst Du auch mit:
    Code:
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t)(color16 / 2048)*8;
       G = (uint8_t)((color16 & 2016)/8);
       B = (uint8_t)(color16 & 31)*8;
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    habe ich auch gerade probiert. Und funktioniert erwartungsgemäß. Hier ist die Frage dann, warum soll das so funktionieren? Das liegt daran, dass bei der Berechnung von R schon nach der ersten Operation - color16 geteilt durch 2048 - nur noch 8 Bit benötigt werden und dieser Ausdruck ist geklammert. Bei der Berechnung von G funktioniert es nicht mehr, weil nach der Rechnung - color16 UND 2016 - 11 Bit übrig bleiben, die erst mit dem Teilen durch 8 auf 8 Bit reduziert werden. Bei der Berechnung von B - color16 UND 31 - geht es nur um die untersten 5 Bit, die hier maskiert werden und durch die Multiplikation mit 8 dann auf 8 Bit erweitert werden.

    Gestern war der Kopf schon etwas voll, vom ganzen Hin und Her.
    Um das Ergebnis und nicht einzelne Rechenschritte umzuwandeln, hätte man gleich die Klammerung der gesamten Rechnung versuchen sollen
    Code:
    G = (uint8_t)(....);
    Zumal Du das an anderer Stelle ja auch schon von Anfang an gemacht hast, nämlich hier:
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (uint16_t)((R/8)*2048) | (uint16_t)((G/4)*32) | (uint16_t)(B/8);
    }
    Um das alles richtig zu verstehen, muss man Bit-Rechnung verinnerlicht haben. Einfach mal so da was zu übernehmen, sich nicht bewusst sein, was es bedeutet und deshalb nicht die richtigen Schlüsse ziehen können, ist eben nicht der richtige Ansatz. Aber ausreichend erklärt sollte ich es nun haben, denke ich.

    Leider hast Du noch nicht geschrieben, ob das Ergebnis nun so ist wie Du es benötigst. Ich kann nur davon ausgehen - tue ich jetzt auch. Denn Ceos kam zum selben Ergebnis von R=248,G=100,B=72. So dass der Rechenweg hier nicht falsch war, wie Du es zwischenzeitlich angenommen hast.
    Geändert von Moppi (11.09.2018 um 08:18 Uhr)

  2. #42
    HaWe
    Gast
    hallo,
    der Grund für die verschiedenen Ergebnisse mit verschiedener Klammerung ist mir ja klar, ich hatte ja auch beide getestet - aber mit anderem Ergebnis als das, das du oben listest. Bisher hatte es nie gestimmt bei mir.

    Ich bin nun auch kein C++ Spezialist, aber ich vermute, dass
    uint8_t((color16 / 2048 )*8 )
    kein legaler C/C++ Code ist und nur zufällig (!) hier das gleiche liefert wie
    (uint8_t) ((color16 / 2048 )*8 )

    Wo ist denn dein kompletter Sketch Code, fertig zum Kompilieren? Ich will nicht wieder was falsch einfügen.

    Ich kopiere den kompletten Code noch mal und compiliere ihn neu, wenn ich ihn habe, vlt hat irgendwo anders was nicht gestimmt bei meinen Versuchen. Es gingen ja auch sehr viele verschiedene Versionen durcheinander.

    Melde mich dann, wenn ichs habe, habe grade keinen Arduino.

  3. #43
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Zum Optimieren habe ich dann mal diesen Entwurf:
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (R>>3<<11) | (G>>2<<5) | (B>>3);
    }
    
    
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t) (color16 >> 11) << 3;
       G = (uint8_t)((color16 & 2016) >> 3);
       B = (uint8_t) (color16 & 31) << 3;
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    Ausgabe:
    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72
    Mann kann R>>3<<11 und G>>2<<5 übrigens nicht zusammenfassen zu R<<8 und G<<3, weil durch die jeweils erste Shift-Operation die untersten Bit gelöscht werden - was wichtig ist. Man müsste dann zusätzlich wieder ein UND anhängen, um die untersten Bits zu löschen, damit wird der Ausdruck nicht kürzer. Beim Verschieben nach Rechts werden die unteren Bits ins Nirvana verschoben und beim Verschieben nach Links werden Nullen eingefügt. Das sind Standardoperationen, wo das Überlaufbit immer gelöscht ist, bzw. nicht berücksichtigt wird. Für bestimmte Zwecke gibt es das auf Maschinenspracheebene auch noch mit Berücksichtigung des Überlaufbits - ist hier nicht wichtig.
    Geändert von Moppi (11.09.2018 um 09:49 Uhr)

  4. #44
    HaWe
    Gast
    danke, das sieht nun schon ganz anders aus alles andere, das ich bisher probiert habe.
    Verständnisfrage:
    Was bedeutet per Rechen-Preferenz
    (R>>3<<11)
    ?

    vermutlich das gleiche wie
    ((R>>3)<<11)
    oder ?

    durch >> schneidest du ja auch die letztem Ziffern ab, wäre "runden" nicht besser?

  5. #45
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    40
    Beiträge
    3.416
    Mann kann R>>3<<11 und G>>2<<5 übrigens nicht zusammenfassen
    Aber man könnte es durch ( R & 0xF8 ) << ( 11-3 ) ersetzen und so wertvolle Takte sparen (kommt auf den Prozessor und seine Intructions an ob ein Bitshift nur einen oder mehrere Takte dauert) ... die 11-3 sollte man natürlich durch 8 ersetzen, damit es ein literal bleibt und nciht erst noch vom vompiler in eine formel verwandelt wird

    Für G wäre dass dann ( G & 0xFC ) << 3
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  6. #46
    HaWe
    Gast
    hi,
    ich sehe schon, da sind 2 bitakrobatikspezialisten unter sich...
    für mich ist das zu hoch oder besser: zu low-level.

    Immerhin:

    ES GEHT!
    (@moppi: mit deinem letzten Code)
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (R>>3<<11) | (G>>2<<5) | (B>>3);
    }
    
    
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t) (color16 >> 11) << 3;
       G = (uint8_t)((color16 & 2016) >> 3);
       B = (uint8_t) (color16 & 31) << 3;
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    Code:
    Hauptprogramm vor Aufruf:
    col16=0
    r=255
    g=102
    b=78
    
    Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):
    col16=64297
    r=0
    g=0
    b=0
    
    Unterprogramm color16 zu RGB:
    color16=64297
    R=248
    G=100
    B=72
    
    Hauptprogramm nach col16 zu rgb:
    col16=64297
    r=248
    g=100
    b=72
    irgendwo muss gestern der Wurm drin gewesen sein.
    Vielen herzlichen Dank! (y)


    Zum Verständnis noch 1 Frage:
    ein r=255 Wert wird ja zu r=248, das liegt ja an der kleineren 5bit-Codierbreite.
    Kann man das bei der Rückumwandlung wieder sinnvoll auf 255 hochskalieren, also runden, analog auch für die mittleren 6bit Werte?

  7. #47
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    40
    Beiträge
    3.416
    nein leider nicht, das problem ist eine verlorene information kann man nicht wiederherstellen, wenn 2 bzw. 3 bits fehlen, fehlen sie, man könnte höchstens auf R und B +4 oder +3 aufaddieren, denn (2^3bit) -1 = 7, davon die Hälfte ungefähr 3 bis 4 um wenigstens etwas annähernd den original wert wieder her zu stellen. Auf G müsstest du dann +2 oder +1 aufaddieren
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  8. #48
    HaWe
    Gast
    ja, ich hatte da an einen Multiplikationsfaktor gedacht, der größere Zahlen bevorzugt und kleine vernachlässigt, so dass keine 1,2,3 oder 4 auf eine Null aufaddiert werden.

    also was in der Art
    R*= 255/248
    G*= 255/252
    B*= 255/248

    edit:
    Worauf ich eigentlich hinaus wollte - klar kann man es "irgendwie" machen, so oder so, meine Frage geht eher in die Richtung, wie es standardmäßig gmacht wird, denn für die Umrechnung R,G,B in color16bit und zurück gibts ja sicher Standardverfahren, damit alle immer dasselbe Ergebnis rauskriegen, egal ob Geforce, Intel, Adobe oder Broadcom.
    Geändert von HaWe (11.09.2018 um 14:09 Uhr)

  9. #49
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Zitat Zitat von Ceos Beitrag anzeigen
    Aber man könnte es durch ( R & 0xF8 ) << ( 11-3 ) ersetzen und so wertvolle Takte sparen (kommt auf den Prozessor und seine Intructions an ob ein Bitshift nur einen oder mehrere Takte dauert) ... die 11-3 sollte man natürlich durch 8 ersetzen, damit es ein literal bleibt und nciht erst noch vom vompiler in eine formel verwandelt wird

    Für G wäre dass dann ( G & 0xFC ) << 3
    Ja, so meinte ich Früher zu Zeiten, als IBM-Computer die ersten PCs waren und dort noch TTL-Schaltkreise verbaut waren, da war das sicher so, beim 286er glaub ich auch noch. Weil jeder Shift-Befehl normalerweise pro verschobenem Bit einen Takt benötigt. UND könnte daher schneller sein, wenn auf einmal alle Bits verknüpft werden. Allerdings weiß ich nicht, wie das heute ist. Ich könnte mir aber vorstellen, dass bei den neueren CPUs die Shift-Vorgänge auch schon in einem Taktzyklus erledigt werden. Bei Controllern weiß ich es nicht. Da muss mal jemand anders sagen, was schneller geht.

    @HaWe
    Code:
    (R>>3<<11)
    ?
    
    vermutlich das gleiche wie
    ((R>>3)<<11)
    oder ?
    In beiden Fällen passiert dasselbe, mit und ohne Klammer. Bloß wenn man noch mit UND, ODER etc. arbeitet, um Einzelergebnisse zu verknüpfen, sieht das wieder anders aus.
    Code:
    return  (R>>3<<11) | (G>>2<<5) | (B>>3);
    
    ist nicht gleichbedeutend mit
    
    return  R>>3<<11 | G>>2<<5 | B>>3;
    ------------------------------------------------------------

    Aber, solch ein Ausdruck:
    Code:
    (color16 & 2016)/8)
    ist logisch eindeutig. Wenn der Compiler gut ist, macht er aus diesem Ausdruck in Maschinensprache das, was auf der Zielhardware am schnellsten verarbeitet wird und setzt also selber Logikbefehle statt Arithmetischer ein. Dann wäre dieser Ausdruck der Universellste.


    ---------------------------------------------------------------
    Sketch
    ---------------------------------------------------------------
    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  (R>>3<<11) | (G>>2<<5) | (B>>3);  //Ersatzweise: ((R & 248)<<8) | ((G & 252)<<3) | (B>>3)
    }
    
    
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t) (color16 >> 11) << 3;    //Ersatzweise: (color16 >> 8) & 248
       G = (uint8_t)((color16 & 2016) >> 3);    //Ersatzweise: (color16 >> 3) & 252 
       B = (uint8_t) (color16 & 31) << 3;    //Ersatzweise: (color16 << 3) & 248
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    
    void setup() {
      // put your setup code here, to run once:
    
       uint16_t r=255, g=102, b=78, 
                col16=0;               // 0xFF66B2;  // Dark Pink (255,102,78)
    
    
       Serial.begin(115200);
       delay(3000);
       
       Serial.println("Hauptprogramm vor Aufruf:");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);
       Serial.println("");
       
       col16=ColorRGB216bit(r,g,b);
       r=g=b=0; // Rücksetzen!
    
       Serial.println("Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);
       
       Color16bit2colorRGB(col16, r, g, b);
       Serial.println("");
       Serial.println("Hauptprogramm nach col16 zu rgb:");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);   
        
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    Nochmal die andere (dritte) Variante:

    Code:
    uint16_t ColorRGB216bit(uint16_t R, uint16_t G, uint16_t B) {
    
       return  ((R & 248)<<8) | ((G & 252)<<3) | (B>>3);   //Die Klammern müssen so sein, sonst stimmt die Logik nicht
    }
    
    
    void Color16bit2colorRGB(uint16_t color16, uint16_t &R, uint16_t &G, uint16_t &B) {
    
       R = (uint8_t) (color16 >> 8) & 248;        //Das funktioniert jetzt ohne zusätzliche Klammerung,
       G = (uint8_t) (color16 >> 3) & 252;        //weil schon nach dem Shift-Befehl die oberen 8 Bit nicht mehr von Bedeutung sind,
       B = (uint8_t) (color16 << 3) & 248;        //bzw. die Bits, die wir brauchen, in die unteren 8 Bit verschoben wurden. (uint8_t) richtet keinen "Schaden" mehr an.
       
       Serial.println("");
       Serial.println("Unterprogramm color16 zu RGB:");
       Serial.println( (String)"color16="+(String)color16);
       Serial.println( (String)"R="+(String)R);
       Serial.println( (String)"G="+(String)G);
       Serial.println( (String)"B="+(String)B); 
    }
    
    void setup() {
      // put your setup code here, to run once:
    
       uint16_t r=255, g=102, b=78, 
                col16=0;               // 0xFF66B2;  // Dark Pink (255,102,78)
    
    
       Serial.begin(115200);
       delay(3000);
       
       Serial.println("Hauptprogramm vor Aufruf:");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);
       Serial.println("");
       
       col16=ColorRGB216bit(r,g,b);
       r=g=b=0; // Rücksetzen!
    
       Serial.println("Hauptprogramm nach rgb zu col16-Berechnung (rgb gelöscht):");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);
       
       Color16bit2colorRGB(col16, r, g, b);
       Serial.println("");
       Serial.println("Hauptprogramm nach col16 zu rgb:");
       Serial.println( (String)"col16="+(String)col16);
       Serial.println( (String)"r="+(String)r);
       Serial.println( (String)"g="+(String)g);
       Serial.println( (String)"b="+(String)b);   
        
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    getestet sind die.
    Geändert von Moppi (11.09.2018 um 14:45 Uhr)

  10. #50
    HaWe
    Gast
    jap, kommt das gleiche raus, danke!
    Ich dachte allerdings bis jetzt, dass shiften in C immer schneller geht als Multipl./Division.
    (Rein akademisch, denn das ist momentan absolut nicht zeitkritisch bei mir.)

Seite 5 von 7 ErsteErste ... 34567 LetzteLetzte

Ähnliche Themen

  1. String nach Array umwandeln (?)
    Von slavezero im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 07.06.2012, 18:21
  2. Chips die nach Seriell umwandeln
    Von dundee12 im Forum Elektronik
    Antworten: 13
    Letzter Beitrag: 12.08.2010, 10:08
  3. word nach byte umwandeln
    Von magic33 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 10
    Letzter Beitrag: 21.02.2007, 17:04
  4. C-Code in hex umwandeln
    Von elkokiller im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 16.02.2006, 10:41
  5. PAL-Videosignal irgendwie nach seriell umwandeln?
    Von Trabukh im Forum Elektronik
    Antworten: 39
    Letzter Beitrag: 14.09.2005, 14:15

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen