2012-05-16 31 views
5

I zostały eksperymentowanie z przykładu Change HUE/Saturation znaleźć na stronie internetowej EFG: http://www.efg2.com/Lab/Library/Delphi/Graphics/Color.htmZmienić HUE bitmapy, ale zachować kolor tła?

enter image description here

chcę użyć technik znalezione w tym przykładzie zmiany wartości kolorów niektórych bitmap (być używany na TImage). Jest jeden problem, z którym mam do czynienia, i to jest z TImages, które mają przezroczyste bitmapy; Nie chcę, aby kolor tła zmieniał jego HUE, a raczej tylko rzeczywiste dane obrazu.

Weź ten przykładowy obraz możemy pracować (chociaż każdy obraz z przejrzystości może być używany):

enter image description here

  • Pobierz demo Change HUE/Saturation z linku na górze.
  • Załaduj obrazek przycisku powyżej do ImageOriginal.
  • Ustaw nasycenie delta na 1.
  • Uruchom projekt.

Niektóre wyniki wyjściowe:

enter image description hereenter image description here

Jakie chciałbym się zdarzyć Oto zachować oryginalny kolor tła (określony przez lewej dolnej najwięcej piksel), a jedynie dopasować odcień dla reszty obrazu. Tak więc, wyniki wyjściowe faktycznie wyglądać następująco (edytowane w Paint.NET):

enter image description hereenter image description here

Pozwól mi użyć innego przykładowy obraz do przetestowania z tym zawiera więcej danych obrazu:

enter image description here

jak poprzednio z pierwszej próbki obrazu, wyniki mogłyby być coś takiego:

enter image description hereenter image description here

Gdy wyniki pragnę powinien wyglądać tak:

enter image description hereenter image description here

Jeden pomysł miałam po zmianie barwy, wymienić dolny lewy najwięcej koloru z kolorem od oryginału, ale jestem nie jestem pewien, czy to jest właściwe podejście, czy nie, a nawet jeśli nie jestem pewien, jak zastąpić kolor X dla innego koloru. (Grafika i matematyka są poza mną).

Na przykład, jeśli narysowałem dwa okręgi koloru niebieskiego na ucho Mickeya (niebieski był oryginalny kolor przezroczysty z lewej dolnej najwięcej piksel), a także kolorowe oczy:

enter image description here

ponownie Zmiana odcienia może wyglądać następująco:

enter image description here

gdy w rzeczywistości powinno się podoba:

enter image description here

Po prostu chciałbym zmienić HUE obrazu, niezależnie od tego, czy jest to metoda użyta w demo EFG, czy inne rozwiązanie. Przezroczysty kolor zdefiniowany przez dolny lewy górny piksel nie powinien być zmieniany po zmianie HUE, to powinno pozostać takie samo, jak pokazano na przykładowych obrazach.

Jak zmienić kolor mapy bitowej z zachowaniem koloru tła?

Odpowiedz

5

Odniesiony kod obejmuje wszystkie piksele na obrazie w celu zmiany odcienia/nasycenia. Można zmodyfikować kod tak, aby nie kolidować jeśli piksel ma specyficzny kolor:

PROCEDURE TFormChangeHS.UpdateBitmap; 
    .. 
    S    : TReal; 
    V    : TReal; 

    FixColor: TRGBTriple;       // New variable 
BEGIN 
    DeltaSaturation := SpinEditDeltaSaturation.Value; 
    NewHue := TrackBarHue.Position; 

    Bitmap := TBitmap.Create; 
    TRY 
    Bitmap.Width := ImageOriginal.Width; 
    Bitmap.Height := ImageOriginal.Height; 
    Bitmap.PixelFormat := ImageOriginal.Picture.Bitmap.PixelFormat; 
    ASSERT(Bitmap.PixelFormat = pf24bit); 

    // save bottom left color 
    FixColor := PRGBTripleArray(
        ImageOriginal.Picture.Bitmap.ScanLine[Bitmap.Height - 1])^[0]; 
    //-- 

    FOR j := 0 TO Bitmap.Height-1 DO 
    BEGIN 
     RowIn := ImageOriginal.Picture.Bitmap.Scanline[j]; 
     RowOut := Bitmap.Scanline[j]; 
     FOR i := 0 TO Bitmap.Width-1 DO 
     BEGIN 
     WITH RowIn[i] DO 
     BEGIN 

      // copy the color to target and continue with next iteration 
      if (RowIn[i].rgbtBlue = FixColor.rgbtBlue) and 
       (RowIn[i].rgbtGreen = FixColor.rgbtGreen) and 
       (RowIn[i].rgbtRed = FixColor.rgbtRed) then begin 
      RowOut[i] := FixColor; 
      Continue; 
      end; 
      //-- 

      // convert pixel coordinates to HSV 
      RGBtoHSV(rgbtRed, rgbtGreen, rgbtBlue, H, S, V); 
     END; 
     .. 
     .. 


wyjściowa:

enter code here

+0

Doskonały Sertac, który działa tak, jak miałem nadzieję. Czy mógłbyś wyjaśnić tę linijkę: "FixColor: = PRGBTripleArray ( ImageOriginal.Picture.Bitmap.ScanLine [Bitmap.Height - 1])^[0];" Czy to jest odpowiednik użycia Pixels [], ale czy jest szybszy? Nie jestem pewien, co robi bit [0]. –

+1

@Blobby - Możesz w rzeczywistości usunąć '^', nie jest to potrzebne (do czego wskazuje PRGBTripleArray, ale kompilator może go rozwiązać bez '^'), lewa część to TRGBTripleArray, stąd [0] jest pierwszy element tablicy. Szybkość nie jest ważna, ponieważ czytamy tylko jeden piksel, można bardzo dobrze wykorzystać Pixels. –

+0

Wielkie dzięki za oczyszczenie tego. Myślę, że rozumiem również drugi kod - 'if (RowIn [i] .rgbtBlue = FixColor.rgbtBlue) i' .. to sprawdza kolor każdego piksela w kanale RGB i czy każdy z komponentów RGB jest równy FixColor przekształcić go w FixColor? –

2

Teoretycznie można na przykład:

pierwsze, trzeba określić, co jest w tle ... (prawdopodobnie wybranie koloru konkretnego piksela jak Delphi dokłada ...)

Następnie , z tym kolorem tła, można utworzyć maskę opartą na tym kolorze ...

powielać obraz ... zastosować odcień ...

scalić swoje 2 bitmapy za pomocą maski ...

+0

brzmi jak dobry pomysł, nigdy nie pracował z maskami przed jednak. –

+1

sprawdź je .. mogą być bardzo przydatne; o) najtrudniejszą częścią jest być może, ** efektywnie ** stworzyć maskę z ** skompresowanym ** jpeg – Whiler

+0

Ponieważ jest to odpowiedź Sertaca działa idealnie, ale dzięki twojej odpowiedzi myślę, że mogę spojrzeć dalej w maski, mam pomysł, co one są, ale na pewno otrzymam informacje na ich temat :) –

Powiązane problemy