Bildhelligkeit ändern



  • *edel*, @Sunday; also kann man mit RGBTRIPLE doch die Farbkanäle einzeln bearbeiten. Leider gelingt es mir nicht, den Code richtig zu implementieren. Hab es so versucht:

    private:
      void __fastcall RGBToColor(Graphics::TBitmap *bmp,
          RGBTRIPLE NewColor);
      Graphics::TBitmap *bmp;
      RGBTRIPLE NewColor;
    
    void __fastcall TForm1::HellerClick(TObject *Sender)
    {
      RGBToColor((Graphics::TBitmap*)bmp,NewColor);
    }
    

    So akzeptiert es der Compiler, aber zur Laufzeit (auch außerhalb der IDE) stimmt der Parameter nicht.

    Also hab ich auch mal versucht, die Function zu integrieren. Ich bekomm aber ein grünbetontes Bild, daß bei mehrmaligem Functionsaufruf dunkler und dann schwarz wird. Hab es so geschrieben:

    void __fastcall TForm1::HellerClick(TObject *Sender)
    {
        Graphics::TBitmap *hellpict = new Graphics::TBitmap();
        hellpict->Width = Image->Picture->Graphic->Width;
        hellpict->Height = Image->Picture->Graphic->Height;
        hellpict->Assign(Image->Picture);
      for (int j = 0; j < hellpict->Height; j++)
      {
        RGBTRIPLE *SL = (RGBTRIPLE *) hellpict->ScanLine[j];
        // muß hier declariert werden(?!), sonst entstehen Falschfarben
        RGBTRIPLE NewColor;
        for (int i = 0; i < hellpict->Width; i++)
        {
          BYTE red   = NewColor.rgbtRed;
          BYTE green = NewColor.rgbtGreen;
          BYTE blue  = NewColor.rgbtBlue;
          if (red == 0)   red   = 0;
          else            red   = SL[i].rgbtRed   * 100 / red;
    
          if (green == 0) green = 0;
          else            green = SL[i].rgbtGreen * 100 / green;
    
          if (blue == 0)  blue  = 0;
          else            blue  = SL[i].rgbtBlue  * 100 / blue;
          SL[i].rgbtRed   = red;
          SL[i].rgbtGreen = green;
          SL[i].rgbtBlue  = blue;
        }
      }
      Image->Picture->Bitmap->Width  = hellpict->Width;
      Image->Picture->Bitmap->Height = hellpict->Height;
      Image->Picture->Bitmap         = hellpict;
      delete hellpict;
    }
    

    Wo mach ich den Fehler? Konnte bis jetzt noch keinen Anhaltspunkt finden.

    -Wenn mal die Probs geknackt sind, würde mir der sehr Weg gefallen. Graustufen, Heller, dunkler, Gammakorrektur, alles mit der gleichen Grundfunction.

    Auch die Abfrage des PixelFormat'es kommt dann in eine separate function. Für die ScanLine-Methode hätte ich ja den Multiplikator, der würde einfach in einer Variavlen stehen. Bei der RGBTRIPLE-Methode seh ich allerdings nicht, warum dieser Code für 24bit gilt. Für einen Hinweis wäre ich seh dankbar.



  • Hallo,

    Mir sind bei diesem Code ein paar Sachen nicht klar.
    Du deklarierst die Variable NewColor und weist gleich darauf die Members anderen Variablen (red, green, blue) zu. Wo wird NewColor initialisiert ?
    Dann diese Konstruktion

    if (red == 0)   red   = 0;
    else            red   = SL[i].rgbtRed   * 100 / red;
    
    if (green == 0) green = 0;
    else            green = SL[i].rgbtGreen * 100 / green;
    
    if (blue == 0)  blue  = 0;
    else            blue  = SL[i].rgbtBlue  * 100 / blue;
    
    SL[i].rgbtRed   = red;
    SL[i].rgbtGreen = green;
    SL[i].rgbtBlue  = blue;
    

    Ok, ist nur ein Schönheitsfehler, aber sollte man das nicht so schreiben

    if (red == 0)   SL[i].rgbtRed   = 0;
    else            SL[i].rgbtRed   *= (100 / red);
    
    if (green == 0) SL[i].rgbtGreen = 0;
    else            SL[i].rgbtGreen *= (100 / green);
    
    if (blue == 0)  SL[i].rgbtBlue  = 0;
    else            SL[i].rgbtBlue  *= (100 / blue);
    

    Ciao

    [ Dieser Beitrag wurde am 09.04.2003 um 10:19 Uhr von Braunstein editiert. ]



  • Den Code umgibt was geheimnisvolles. Es geht auch ganz kurz:

    for (int j = 0; j < hellpict->Height; j++)
      {
        RGBTRIPLE *SL = (RGBTRIPLE *) hellpict->ScanLine[j];
        for (int i = 0; i < hellpict->Width; i++)
        {
          /* Das sind die Multiplikatoren aus dem Gray-Code * 1000
             Nach etlichen sinnlosen Iterationen kommt wieder das originalbild,
             aber farbverändert. */
          SL[i].rgbtRed   *= 299;
          SL[i].rgbtGreen *= 587;
          SL[i].rgbtBlue  *= 114;
        }
      }
          /* Das wär schon mal gut für die Dunkler-Routine,
             die Stufen sind gut. */
          SL[i].rgbtRed   *= 0.9;
          SL[i].rgbtGreen *= 0.9;
          SL[i].rgbtBlue  *= 0.9;
    

    Aber wie wird das Bild heller? Da gelingt mir nix.



  • Schade, heller scheint erst mal nicht zu gehen. Vielleicht hat aber jemand doch noch die Idee? :p 🙄

    Dann wär noch diese Codezeile im gefundenen Beispiel, die ich nicht versteh. Außerdem produziert sie nichtsignifikanten Code.

    *ptr = (*ptr+12>255 ? 255 : *ptr+12);

    Jemand eine Idee, wie ich das signifikant schreiben kann? Vorab werd ich diesen Code nehmen. Immerhin läuft er, während RGBTRIPLE leider nichts nützt, wenn es nicht gelingt, das Bild damit auch heller zu bekommen.



  • Original erstellt von <Malus>:
    *Dann wär noch diese Codezeile im gefundenen Beispiel, die ich nicht versteh.
    *ptr = (*ptr+12>255 ? 255 : ptr+12);

    if(*ptr + 12 > 255)
       *ptr = 255;
    else
       *ptr += 12;
    


  • das ist noch "signifikanter" 🙂

    if(*ptr + 12 > 255)
       *ptr = 255;
    else
       *ptr = *ptr + 12;
    


  • Hier, hier, ich weiss auch was!

    😉

    Vorraussetzungen: eine Form mit TImage (Bild geladen) und TTrackBar.

    Graphics::TBitmap *obmp;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
    {
      Image1->Picture->Bitmap->PixelFormat = pf24bit;
    
      obmp = new Graphics::TBitmap();
      obmp->Assign(Image1->Picture->Bitmap); // Originalbild "sichern"
    
      TrackBar1->Max = 53;
      TrackBar1->Position = TrackBar1->Max/2;
    
      DoubleBuffered = true; // nur für BCB6+
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormDestroy(TObject *Sender)
    {
      delete obmp;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::TrackBar1Change(TObject *Sender)
    {
      int step = (TrackBar1->Position - (TrackBar1->Max/2)) * 10;
    
      BYTE *optr, *nptr;
      for (int y = 0; y < Image1->Picture->Bitmap->Height; y++)   // jede Zeile
      {
        optr = (BYTE *)obmp->ScanLine[y];                   // Zeile des Originals
        nptr = (BYTE *)Image1->Picture->Bitmap->ScanLine[y];// neu zu zeichnende Zeile
    
        for (int x = 0; x < Image1->Picture->Bitmap->Width; x++)  // jeder Pixel
        {
          for (int z = 0; z < 3; z++)                             // 3 Byte pro Pixel
          {
            if (step < 0)   // dunkler
              nptr[x*3+z] = (optr[x*3+z] + step < 0 ? 0 : optr[x*3+z] + step);
            else            // heller
              nptr[x*3+z] = (optr[x*3+z] + step > 255 ? 255 : optr[x*3+z] + step);
          }
        }
      }
      Image1->Invalidate();
    }
    //---------------------------------------------------------------------------
    


  • Naja, funzt nur so halb. 😉



  • Wolle grad antworten, da seh ich @Jansens Idee. Ich poste trotzdem und geh dann sofort in die Exerzitien. 😉 @Jansen, danke, das sieht schon auf den ersten Blick nach Leckerbissen aus. 🕶

    Für eure Darstellung der Zeile in der gewohnten Form bedank ich mich. Jetzt wo ich es (für mich) verständlich geschrieben seh, kann ich die Syntax auch zuordnen.

    Bedingungsoperator
    Syntax
    logischer-OR-ausdruck ? ausdruck : conditional-ausdruck

    Das war einer der Bereiche, die immer viel zu abstrakt und unerreichbar wirkten. Nutzungssituationen gibt es in der Praxis grad genug. :p

    Der Compiler warnt natürlich weiter. Vielleicht muß man tatsächlich damit leben?...

    ...Und weiterknobeln. Irgendwann wird auch die Regelung der Farbkanäle klappen. Muß ja nicht alles den Profis vorbehalten bleiben. :p



  • Jetzt bin ich mir sicher: <Malus> == <OmegaX> ! 😉



  • Original erstellt von WebFritzi:
    funzt nur so halb

    Welche Hälfte fehlt denn?



  • Naja, bei mir ist das so, dass es soweit funzt, wenn man die TrackBar nur in eine Richtung bewegt. Wenn man zurückgeht wirds schwarz bzw. weiß. Kann allerdings am fehlenden DoubleBuffered bei mir liegen.



  • Muss auch ohne DB laufen, das dient hier auch nur der Flickerreduzierung.

    Hast du den Code 1:1 übernommen? Mal auf dem BCB6 getestet? Das funktioniert hier problemlos in beide Richtungen, ob mit DB oder ohne.



  • Hab den Code im BCB3 direkt übernommen. Da funzt es nicht (eben nur fast). Im BCB6 funzt es (auch ohne DoubleBuffering) super.



  • Jetzt bin ich mir sicher: <Malus> == <OmegaX> !
    @WebFritzi, danke für's Kompliment. Ich wär froh, ich hätte schon den Dbl. Logo hab ich das Thema gespannt mitverfolgt. Ein paar weitere Einblicke und...

    ...super + Dank @Jansen. 🙂 Eine Dialogvariante mit der TrackBar will ich ja später auch bauen. Hab allerdings die gleichen Probs wie @WebFritzi. Wechsel ich die Schieberichtung, verändert sich die Helligkeit erst mal weiter in der alten Richtung. Versuche, jede Bewegung auf die vorangegangene zu beziehen, wollten erst mal scheitern. Vielleicht muß man bei jeder Bewegung die +/- Position im Bezug auf die Mitte feststellen, alle benötigten Schritte auf einmal machen, das Bild praktisch komplett vom Original her neu aufbauen. Wenn ich mir den Code anschau, könnte es gut sein, daß der BCB6 genau das macht.

    Max nix, ich konnte schon mal die MenuItem/Tastatur-Variante satt optimieren. Zwischen 1bit und 8bit muß ich aber noch testen. Bei den höheren PixelFormaten läuft es (hier) schon mal prima:

    private:
      BYTE *ptr,*aptr;
    
    // PixelFormatCheck
    void __fastcall TPixi::PixelFormatCheck(TObject *Sender)
    {
        if (Image->Picture->Bitmap->PixelFormat == pf1bit ||
                Image->Picture->Bitmap->PixelFormat == pf4bit ||
                Image->Picture->Bitmap->PixelFormat == pf8bit)
        pf = 1;
      if (Image->Picture->Bitmap->PixelFormat == pf16bit)
        pf = 2;
      if (Image->Picture->Bitmap->PixelFormat == pf24bit)
        pf = 3;
        if (Image->Picture->Bitmap->PixelFormat == pf32bit)
        pf = 4;
    }
    //---------------------------------------------------------------------------
    // Heller
    void __fastcall TPixi::HellerClick(TObject *Sender)
    {
      PixelFormatCheck(Sender);
        Graphics::TBitmap *hellpict = new Graphics::TBitmap();
        hellpict->Width = Image->Picture->Graphic->Width;
        hellpict->Height = Image->Picture->Graphic->Height;
      hellpict->PixelFormat = Image->Picture->Bitmap->PixelFormat;
        hellpict->Assign(Image->Picture);
        int i,j;
      for (i=0;i < hellpict->Height;i++)
      {
        ptr = (BYTE *)hellpict->ScanLine[i];                   // Zeile des Originals
        aptr = (BYTE *)Image->Picture->Bitmap->ScanLine[i];// neu zu zeichnende Zeile
        for (j=0;j < hellpict->Width;j++)
        {
          for (int z = 0; z < pf; z++)
            ptr[j*pf+z] = (aptr[j*pf+z]+12>255?255:aptr[j*pf+z]+12);
        }
      }
        Image->Picture->Bitmap = hellpict;
        delete hellpict;
    }
    //---------------------------------------------------------------------------
    // Dunkler
    void __fastcall TPixi::DunklerClick(TObject *Sender)
    {  
      PixelFormatCheck(Sender);
        Graphics::TBitmap *darkpict = new Graphics::TBitmap();
        darkpict->Width = Image->Picture->Graphic->Width;
        darkpict->Height = Image->Picture->Graphic->Height;
        darkpict->Assign(Image->Picture);
        int i,j;
      for (i=0;i < darkpict->Height;i++)
      {
        ptr = (BYTE *)darkpict->ScanLine[i];                   // Zeile des Originals
        aptr = (BYTE *)Image->Picture->Bitmap->ScanLine[i];// neu zu zeichnende Zeile
        for (j=0;j < darkpict->Width;j++)
        {
          for (int z = 0; z < pf; z++)
            ptr[j*pf+z] = (aptr[j*pf+z]-12<0?0:aptr[j*pf+z]-12);
        }
      }
        Image->Picture->Bitmap = darkpict;
        delete darkpict;
    }
    //---------------------------------------------------------------------------
    

    Seht ihr Fehler/Fragwürdigkeiten? Die Digits sind aber auch jetzt nicht signifikant. (Liegt sicher am BCB3, der ollen Meckertante 😃 ).



  • Original erstellt von WebFritzi:
    Hab den Code im BCB3 direkt übernommen. Da funzt es nicht (eben nur fast).

    Hmmm, vielleicht ein Problem mit der TrackBar-Implementierung im BCB3? Lass doch mal step in der Caption anzeigen.



  • Nö. Hab die TrackBar schon des öfteren erfolgreich benutzt. Die geht!



  • Läuft step denn sauber in 10er-Schritten zwischen -260 und +260?

    Naja, ist ja auch egal, auf 'nem "richtigen" Compiler funktioniert das Ganze jedenfalls einwandfrei. 🙂
    Logische Fehler hat der (von mir geschriebene) Code m.E. nicht, also muss es am BCB3 bzw. dessen Bibliotheken liegen.



  • Also die Zusammenarbeit hier im Board ist echt 🕶 . Da möchte man richtig mithalten können. Klappt aber nicht so ganz. Bei mir ist wieder nur ne Frage draus geworden. 🙄

    Hab mir auch das Graustufenbeispiel aus dem Thread angeschaut (die URL dummerweise nicht gespeichert). Ich dachte, das kann ich ganz einfach für alle Formate gangbar bekommen.

    Die Feststufen-Variante hatte ich bald aufgegeben. Klappt nur bei 24bit, bei 8bit hängt sich das System komplett fest. Die Stufenversion klappt nur bei 24bit einwandfrei. Darunter kommen Nonsense-Farben, darüber wird es unscharf. Ich poste trotzdem mal den Stand. Hab es an das Beispiel angepasst. Wenn schon eine eigene Funktion für pf, dann können ja alle drauf zugreifen. @Jansen, deinen logischen Weg mit der 3. for-Schleife konnte ich hier gar nicht umsetzen.

    void __fastcall TForm1::GrayClick(TObject *Sender)
    {
      PixelFormatCheck(Sender);
      Graphics::TBitmap *graypict = new Graphics::TBitmap();
      graypict->Width = Image->Picture->Graphic->Width; 
      graypict->Height = Image->Picture->Graphic->Height;
      graypict->Assign(Image->Picture); 
      graypict->PixelFormat = Image->Picture->Bitmap->PixelFormat;
        for (int j = 0; j < graypict->Height; j++)
      {
            RGBTRIPLE *SL = (RGBTRIPLE *) graypict->ScanLine[j];
            for (int i = 0; i < graypict->Width*pf; i++)
        {
                BYTE gray;
          gray = (SL[i].rgbtRed * 0.299) + (SL[i].rgbtGreen *
                0.587) + (SL[i].rgbtBlue * 0.114);
          SL[i].rgbtRed   = gray;
          SL[i].rgbtGreen = gray;
          SL[i].rgbtBlue  = gray;
            }
        }
        Image->Picture->Bitmap = graypict;
        delete graypict;
    }
    

    PS: @WebFritzi, was meinst du mit dem Vergleich? Kannst du die Leute nach ihrem Schreibstil unterscheiden? 🕶 , ich würde mir sowas nicht zutraun. 🙂


Anmelden zum Antworten