Blending obrazków

0

zadanie niby proste - zmieszać kolory dwóch obrazków stosując dany współczynnik alpha
jednak wszystkie rozwiązania jakie znalazłem w Internecie polegają na przeleceniu po pikselach w unsafe kodzie - takie rozwiązanie mi się wydaje wbrew założeniom kodu zarządzanego
poza tym kod strasznie traci na czytelności i rozwiązania które znalazłem są strasznie długie w stosunku do zadania
tak więc napisałem na próbę własny kod:

        private void Form1_Load(object sender, EventArgs e)
        {
            using (Bitmap bmp1 = new Bitmap("e:\\a.jpg"))
            {
                img1 = bmp1.Clone(new Rectangle(0, 0, bmp1.Width, bmp1.Height), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }
            using (Bitmap bmp2 = new Bitmap("e:\\b.jpg"))
            {
                img2 = bmp2.Clone(new Rectangle(0, 0, bmp2.Width, bmp2.Height), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            }

            ia = new System.Drawing.Imaging.ImageAttributes();
            cm = new System.Drawing.Imaging.ColorMatrix();
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            cm.Matrix33 = (float)trackBar1.Value / 100f; // pomnożenie kanału alpha
            ia.SetColorMatrix(cm);

            img3 = (Image)img1.Clone();
            Graphics.FromImage(img3).DrawImage(img2, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height), 0f, 0f, img2.Width, img2.Height, GraphicsUnit.Pixel, ia);

            pictureBox1.Image = img3;
        }

w sumie wykorzystanie macierzy do zmiany kanału alpha może i jest głupie ale jak tak pomyślałem to daje wielkie możliwości rozbudowania efektu mieszania
wszystko działa pięknie i szybko ale mimo wszystko wydaje mi się że jednak za wolno ... :/
czy da się jakoś przyspieszyć ten kod lub ma ktoś pomysł jak to ładnie zakodować bez tworzenia brzydkich pętli ?

0

Poszukaj o: LockBits.

0

czytałem troche i z tego co wyczytałem LockBits wymusza wykorzystanie własnie unsafe kodu albo Marshal.Copy czyli dokładnie to czego nie chciałem :|

0

Tu jest o LockBits: http://zabanet.aspweb.cz/grafika/
Ale skoro nie chcesz, to kombinuj dalej - powodzenia, bo mi się nie udało do tej pory.

0

nie masz zbyt wielu możliwości, by szybko zblendować w C# dwa obrazy. w sumie mozliwosci masz 3 - dwie już wymienione:

  1. macierz kolorów - mówisz, ze powolne
  2. ręczne ustawienie kanału alphy przez Bitmap.Get/SetPixel - mega powolne lub LockBits - czyli to co chciałbyś wykluczyć.
  3. Reflections i wykorzystanie z GDI funkcji BlendAlpha (na XP błyskawica, na Viście ślimak) - jednak, jeśli w grę wchodzi tylko jedynie jedno rysowanie obrazu z blendowaniem i brak dalszego przetwarzania, narzut na transfery pomiędzy surface 'y GDI+ <-> GDI może być de facto sprawiać, że ta metoda będzie wolniejsza niż metoda z macierzami kolorów.
0

ach, przy okazji - System.Drawing.Imaging.PixelFormat.Format32bppPArgb - sprawia, ze proces blendowania powinien być szybszy.

0
_asd napisał(a)

ach, przy okazji - System.Drawing.Imaging.PixelFormat.Format32bppPArgb - sprawia, ze proces blendowania powinien być szybszy.

z tego co wyczytałem to PArgb różni się od Argb tym że jeśli narysuję linię koloru #7fffffff to w przypadku PArgb zblenduje się ona z kolorem który już tam był, a w wypadku samego Argb piksele zostaną po prostu zastąpione tym przeźroczystym kolorem więc nie wiem jak to miało by przyspieszyć ale sprawdziłem i różnicy w sumie nie ma żadnej (chociaż na logike Argb z DrawImage na nim w ogóle nie powinno działać)
w każdym razie sprawdziłem wszystkie metody i wszystkie okazały się tak samo "wolne"
wolne w cudzysłowie bo miałem małe przyćmienie - funkcje sprawdzałem na obrazkach 1024x768 i nie zmieniały się one płynnie w miarę zmiany pozycji Trackbara
z tym że bez cacheowania chyba jeszcze nie widziałem programu który zrobiłby to na moim procku szybciej, więc wróciłem do swojego pierwotnego kodu ze względu na jego intuicyjność, tym bardziej że w praktyce program pracuje na bitmapach 20x20 na których to rozwiązanie i tak jest wystarczające

0

w każdym razie dzięki wszystkim za pomoc

0
karafaka napisał(a)
_asd napisał(a)

ach, przy okazji - System.Drawing.Imaging.PixelFormat.Format32bppPArgb - sprawia, ze proces blendowania powinien być szybszy.

z tego co wyczytałem to PArgb różni się od Argb tym że jeśli narysuję linię koloru #7fffffff to w przypadku PArgb zblenduje się ona z kolorem który już tam był, a w wypadku samego Argb piksele zostaną po prostu zastąpione tym przeźroczystym kolorem więc nie wiem jak to miało by przyspieszyć ale sprawdziłem i różnicy w sumie nie ma żadnej (chociaż na logike Argb z DrawImage na nim w ogóle nie powinno działać)

a ja stestowałem to - 1000 razy rysowanie bitmapy 256x256 do drugiego obiektu Bitmap w opcjach:

  1. Argb->Argb -> ~6570ms
  2. PArgb->PArgb -> ~6130ms

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.