Bildhelligkeit ändern



  • Mit AlphaBlend() lassen sich doch die Farben ausblenden? So wird es auch in den Beiträgen genutzt. Ich will aber das Bild komplett erhalten. Das Ziel wäre als Beispiel: hellbraun --> mittelbraun --> dunkelbraun --> umbra / und auch wieder zurück, je nachdem, ob man das Bild heller oder dunkler macht. Und das natürlich für alle Farben im ganzen Bild wirksam.



  • Hi🤡

    Wenn Du mit ScanLine arbeitest weißt Du ja schon, wie Du auf die Pixel eines Bildes zugreifst. Die einfachste Methode wäre nun jeden Farbwert von jedem Pixel um 1 zu incrementieren und direkt wieder zurückzuschreiben. Du must natürlich einen "Überlauf" Abfangen (z.B if (temp<0) temp=0;if (temp>255) temp=255;)

    Wer nicht fragt bleibt dumm ;)...



  • ich habe das hier in delphi gefunden

    void RGBtoHSL( COLORREF rgb, double *H, double *S, double *L )
    {
      double delta;
      double r = (double)GetRValue(rgb)/255;
      double g = (double)GetGValue(rgb)/255;
      double b = (double)GetBValue(rgb)/255;
      double cmax = max(r,max(g,b));
      double cmin = min(r,min(g,b));
      *L=(cmax+cmin)/2.0;
      if(cmax==cmin) {
         *S = 0;
         *H = 0; // it's really undefined
      } else {
         if(*L < 0.5) 
            *S = (cmax-cmin)/(cmax+cmin);
         else
            *S = (cmax-cmin)/(2.0-cmax-cmin);
         delta = cmax - cmin;
         if(r==cmax)
             *H = (g-b)/delta;
         else if(g==cmax)
             *H = 2.0 +(b-r)/delta;
         else
             *G=4.0+(r-g)/delta;
         *H /= 6.0;
         if(*H < 0.0)
             *H += 1;
      }
    }
    
    To convert HSL to RGB use code like this: 
    
    static double HuetoRGB(double m1, double m2, double h )
    {
      if( h < 0 ) h += 1.0;
      if( h > 1 ) h -= 1.0;
      if( 6.0*h < 1 )
         return (m1+(m2-m1)*h*6.0);
      if( 2.0*h < 1 )
         return m2;
      if( 3.0*h < 2.0 )
         return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
      return m1;
    }
    
    COLORREF HLStoRGB( double H, double L, double S )
    {
     double r,g,b;
     double m1, m2;
    
     if(S==0) {
        r=g=b=L;
     } else {
        if(L <=0.5)
           m2 = L*(1.0+S);
        else
           m2 = L+S-L*S;
        m1 = 2.0*L-m2;
        r = HuetoRGB(m1,m2,H+1.0/3.0);
        g = HuetoRGB(m1,m2,H);
        b = HuetoRGB(m1,m2,H-1.0/3.0);
     }
     return RGB((BYTE)(r*255),(BYTE)(g*255),(BYTE)(b*255));
    }
    

    also RGB in HSL konvertiern L-Parameter ändern und dann umgekert

    [ Dieser Beitrag wurde am 07.04.2003 um 14:52 Uhr von Xqgene editiert. ]



  • blub 😉



  • Dank euch für die Infos und Recherchen. @Xqgene, bei Pascal-Code hatte ich allerdings nicht geschaut. Dazu sollte ich die Sprache besser kennen. Der hier sieht aber auf den ersten Blick gut umsetzbar aus. Allerdings:

    Aus *G werd ich nicht schlau. Hab es als double nachdeclariert, seh aber keine Verwendung.

    min und max liefern "undefiniertes Symbol". Hab das einfach mal durch 0 und 255 ersetzt - wird aber falsch sein?

    Dann der Aufruf "RGBtoHSL(rgb, *H, *S, *L);" bringt ein "Incompatible Typconversion".

    Da wären also noch C++-Nüsse zu knacken. Ich seh noch kein Land. Wird es überhaupt notwendig sein, über HSL zu konvertieren? - Sorry, die Frage declariert mich sicher als "unresolved External" auf dem Gebiet. Soll es auch, denn in der Tat, den Bereich der Welt will ich mir erst erschließen.

    @AFR, nach dem von dir vorgeschlagenen Weg hab ich gefahndet. Ich teste momentan eine gefundene und erweiterte Syntax. Die Zeile in der inneren for-Schleife "*ptr = (*ptr+12>255 ? 255 : *ptr+12);" kommt mir allerdings seltsam und eigentlich falsch vor. Kann das Pascal-Syntax sein? Sie bringt auch eine CompilerWarnung (unsignificant). Mir gelingt aber nichts signifikantes. 🙄 Hier mal die komplette Funktion. Was sagt ihr dazu? Grundsätzlich brauchbar? Denn sie funktioniert. 🙂 🙄 Aber am kritischen Punkt eine Warnung, dabei ist mir nicht wohl. Wie könnte ich das besser machen?

    void __fastcall TForm::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);
        int i,j;
        unsigned char *ptr;
        if (Image->Picture->Bitmap->PixelFormat == pf1bit ||
                Image->Picture->Bitmap->PixelFormat == pf4bit ||
                Image->Picture->Bitmap->PixelFormat == pf8bit)
        {
            try
            {
                for (i=0;i < hellpict->Height;i++)
                {
                    unsigned char *aptr = (byte*)hellpict->ScanLine[i];
                    for (j=0;j < hellpict->Width;j++)
                    {
                        ptr  = aptr + j;
                        *ptr = (*ptr+12>255 ? 255 : *ptr+12);
                    }
                }
            }
            catch (...)
            {};
        }
        if (Image->Picture->Bitmap->PixelFormat == pf16bit)
        {
            try
            {
                for (i=0;i < hellpict->Height;i++)
                {
                    unsigned char *aptr = (byte*)hellpict->ScanLine[i];
                    for (j=0;j < hellpict->Width*2;j++)
                    {
                        ptr  = aptr + j;
                        *ptr = (*ptr+12>255 ? 255 : *ptr+12);
                    }
                }
            }
            catch (...)
            {};
        }
        if (Image->Picture->Bitmap->PixelFormat == pf24bit)
        {
            try
            {
                for (i=0;i < hellpict->Height;i++)
                {
                    unsigned char *aptr = (byte*)hellpict->ScanLine[i];
                    for (j=0;j < hellpict->Width*3;j++)
                    {
                        ptr  = aptr + j;
                        *ptr = (*ptr+12>255 ? 255 : *ptr+12);
                    }
                }
            }
            catch (...)
            {};
        }        
        if (Image->Picture->Bitmap->PixelFormat == pf32bit)
        {
            try
            {
                for (i=0;i < hellpict->Height;i++)
                {
                    unsigned char *aptr = (byte*)hellpict->ScanLine[i];
                    for (j=0;j < hellpict->Width*4;j++)
                    {
                        ptr  = aptr + j;
                        *ptr = (*ptr+12>255 ? 255 : *ptr+12);
                    }
                }
            }
            catch (...)
            {};
        }
        Image->Picture->Bitmap = hellpict;
        delete hellpict;
    }
    


  • schau dir mal folgendes an, wenn du lediglich die farbe deines bildes ändern möchtest:

    //---------------------------------------------------------------------------
    // ändert ein bild in die farbe des übergebenen rgb-triples (24bit)
    //---------------------------------------------------------------------------
    void __fastcall TForm1::RGBToColor(Graphics::TBitmap *bmp, RGBTRIPLE NewColor)
    {
      Graphics::TBitmap *bmp_cl= new Graphics::TBitmap();
    
      bmp_cl->Assign(bmp);
    
      for (int j = 0; j < bmp_cl->Height; j++)
      {
        RGBTRIPLE *SL = (RGBTRIPLE *) bmp_cl->ScanLine[j];
    
        for (int i = 0; i < bmp_cl->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;
        }
      }
    
      Image1->Picture->Bitmap->Width  = bmp_cl->Width;
      Image1->Picture->Bitmap->Height = bmp_cl->Height;
      Image1->Picture->Bitmap         = bmp_cl;
    
      delete bmp_cl;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      RGBTRIPLE NewColor;
    
      // ein grünes bild erzeugen (max-werte jeweils 255)
      NewColor.rgbtRed   = 0;
      NewColor.rgbtGreen = 128;
      NewColor.rgbtBlue  = 0;
    
      RGBToColor(Image1->Picture->Bitmap, NewColor);
    }
    //---------------------------------------------------------------------------
    


  • *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.


Anmelden zum Antworten