Bir formu Renkli'den Gri Tonlamaya dönüştürmek. (AlphaBlend)

Yazdığınız makaleleri ve üyelerimizin işine yarayacağını düşündüğünüz kodlarınızı gönderebilirsiniz. Bu foruma soru sormayın!
Cevapla
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Bir formu Renkli'den Gri Tonlamaya dönüştürmek. (AlphaBlend)

Mesaj gönderen mrmarman »

Merhaba.

- Biliyorsunuz, görmüşsünüzdür WindowsXP shutdown diyaloğunda güzel bir animasyon uygular. Tüm ekran bir süre içerisinde gri tonlamaya bürünür.

- Bunun nasıl yapılacağını ilk o zaman araştırıp uygulamıştım. Şimdi bir soru geldi, onu buradan yayınlama gereği duydum. 8)

- Kodu yayınlamamdaki gaye, bilinmesi gereken ve farklı alanlarda da uygulama alanı olan bu vereceğim iki fonksiyonun ön planda oluşundandır. Bunun için aşağıda beş procedure ile bir button altına bunları hayata geçiren uygulama hazırladık.

- Graphics Device Interface (GDI) komutları ile Device Context (DC) ile geliştirilmiştir. Direkt ekrandan okunur ve ekrana geri basılır. Böylece Form'un başlığı da içine alınmış bir snapshot alınarak gerekli grileştirme yapılır ve sonuç eskisinin üzerine basılır. Buradaki işlem bir ilüzyon ne de olsa :lol:

- İnceleyin, geliştirin, kullanın... Afiyet olsun.. 8)

:arrow: Renkli bir Resmi GrayScale (Gri Tonlama) halinde dönüştürme için procedure...

Kod: Tümünü seç

procedure Grayscale(Bitmap: TBitmap);
type
  pRGBLine     = ^TRGBLine;
  TRGBLine     = Array[word] of TRGBTriple;
  pRGBQuadLine = ^TRGBQuadLine; 
  TRGBQuadLine = Array[word] of TRGBQuad; 
var 
  Line    : Pointer; 
  i, j    : Integer; 
  palCount: Word;
  MaxPal  : TMaxLogPalette;
  pf24    : boolean;
begin
  case Bitmap.PixelFormat of
    pf1bit, pf4bit, pf8bit:  // Palette
    begin
      // Retrieve the number of palette entries
      GetObject(Bitmap.Palette, sizeof(word), @palCount);
      MaxPal.palVersion := $0300;
      MaxPal.palNumEntries := PalCount;
      GetPaletteEntries(Bitmap.Palette, 0, PalCount,
        MaxPal.palpalentry);
      FOR j := 0 to PalCount - 1 DO
        with MaxPal.palPalEntry[j] do 
        begin 
          peRed := (peRed + peGreen + peBlue) div 3; 
          peGreen := peRed; 
          peBlue := peRed; 
        end;
      Bitmap.Palette := CreatePalette(PLogPalette(@MaxPal)^);
    end;
    pf15bit, pf16bit:
       raise Exception.Create('15bit and 16bit bitmap grayscale conversion not supported');
    pf24bit, pf32bit:  // 24 bit
    begin
      pf24 := (Bitmap.PixelFormat = pf24bit);

      FOR j := 0 TO Bitmap.Height - 1 DO
      begin
        Line := Bitmap.Scanline[j];
        FOR i := 0 TO Bitmap.Width - 1 DO
        if pf24 then
          with pRGBLine(Line)[i] do
          begin
            rgbtRed := (rgbtRed + rgbtGreen + rgbtBlue) div 3;
            rgbtgreen := rgbtred;
            rgbtblue := rgbtred;
          end
        else
          with pRGBQuadLine(Line)[i] do
          begin
            rgbRed := (rgbRed + rgbGreen + rgbBlue) div 3;
            rgbgreen := rgbred;
            rgbblue := rgbred;
          end
      end;
    end;
  end;
end;
:arrow: Source (Kaynak) ve Dest (Hedef) Bitmap resmi Alpha değeri ölçüsünde birleştirip Dest Bitmap üreten Procedure

Kod: Tümünü seç

procedure yAlphaBlend(Dest, Source:TBitmap; Alpha:Integer );
var TB       :TBLENDFUNCTION;
    SRect,
    DRect    :TRect;
begin
   SRect := Source.Canvas.ClipRect;
   DRect   := Dest.Canvas.ClipRect;
   TB.BlendOp    := 0;
   TB.BlendFlags := 0;
   TB.SourceConstantAlpha := alpha;
   TB.AlphaFormat:= 0;
   Alphablend( Dest.Canvas.Handle,     DRect.Left,   DRect.Top,
               DRect.Right-DRect.Left, DRect.Bottom- DRect.Top,
               Source.Canvas.Handle,   SRect.Left,   SRect.Top,
               SRect.Right-SRect.Left, SRect.Bottom- SRect.Top, TB);
end;
:arrow: Formun ekran görüntüsünün Bitmap'e kopyalanması için procedure

Kod: Tümünü seç

Procedure FormDC(hWin:THandle; Bitmap:TBitmap);
var
  DC, DCWind        : HWND;
  rc                : TRect;
begin
  DCWind := hWin;
  GetWindowRect(DCWind, rc);
  with Bitmap do
  try
    Width  := abs(rc.Right - rc.Left);
    Height := abs(rc.Bottom - rc.Top);
    DC := GetDC(GetDesktopWindow);
    try
      BitBlt( Canvas.Handle, 0, 0, Width, Height, DC, rc.Left, rc.Top, SRCCOPY);
    finally
      ReleaseDC(GetDesktopWindow, DC);
    end;
  finally
    ReleaseDC(hWin, DCWind);
  end;
end;
:arrow: Bitmap'i DC ile ekrana basmak için procedure

Kod: Tümünü seç

procedure xPaintToDC(DC:HDC; x,y:Integer; Bitmap:TBitmap);
begin
  With TCanvas.Create do begin
    Handle := DC;
    Draw(x, y, Bitmap);
    Free;
  end;
end;
:arrow: Form'un veya parametre NIL verilmişse Tüm Windows Ekranı* için yapılan animatif siyah beyaz uygulama procedure

Kod: Tümünü seç

procedure SiyahBeyazForm( Form: TForm );
var
  X, Y, Eksiltme : Integer;
  Hand : HWND;
  Bitmap,
  Bitmap1,
  Bitmap2 : TBitmap;
  Sayac   : integer;
  DC      : HWND;
begin
  If Form = Nil then begin
    Hand := GetDesktopWindow;
    X := 0;
    Y := 0;
  end else begin
    Hand := Form.Handle;
    X := Form.Left;
    Y := Form.Top;
  end;

  // Kaynak Bitmap
  Bitmap1 := TBitmap.Create;
  FormDC( Hand, Bitmap1 );
  Bitmap1.PixelFormat := pf24Bit;

  // Hedef Bitmap
  Bitmap2 := TBitmap.Create;
  Bitmap2.Assign( Bitmap1 );
  Bitmap2.PixelFormat := pf24Bit;

  // GrayScale ( gri tonlamalı ) dönüştürme
  Grayscale(Bitmap2);

  // AlphaBlend için Bitmap
  Bitmap := TBitmap.Create;
  Bitmap.PixelFormat := pf24Bit;

  // Operasyon Vakti :)
  DC       := GetDC(0);
  Sayac    := 0;
  // Büyük yüzeylerde işi hızlandırmak, ortalama hızı eşitlemek için
  Eksiltme := Bitmap1.Width * Bitmap1.Height div 15000;

  While Sayac < 255 do begin
    Bitmap.Assign(Bitmap1);
    yAlphaBlend( Bitmap, Bitmap2, Sayac );
    xPaintToDC( DC, X, Y, Bitmap );
    Inc(Sayac, Eksiltme);
  end;
  ReleaseDC(0, DC);
end;
:arrow: Son olarak TButton ile tetikleyerek uygulayalım

:arrow: Size bonus iki alternatifli yaptım. Aşağıda alt alta iki alternatif tanımı da görüyorsunuz.

Kod: Tümünü seç

  SiyahBeyazForm( Self );
derseniz sadece aktif form siyahbeyaz olacaktır. :idea:

Kod: Tümünü seç

  SiyahBeyazForm( Nil );
derseniz bu sefer tüm ekran siyahbeyaz olacaktır. :o

:arrow: Bir bonus daha. Ekranı eski haline getiren yani refresh eden kodu da buna eklemek için şöyle bir yöntem buldum. SetTimer ile 3 saniyelik bir bekleme yaptırıp sonucunda ekranı eski haline döndürüyoruz.

Kod: Tümünü seç

procedure TForm1.Button1Click(Sender: TObject);
Var Timer_ID:Integer;
  procedure MesajTimer;
  begin
    SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, Nil,
    SPIF_SENDWININICHANGE);
    KillTimer(Handle, Timer_ID);
  end;
begin
  Timer_ID := 0;
  // 1. Alternatif Sadece Form
     SiyahBeyazForm( Self );
  // 2. Alternatif Tüm Desktop
  // SiyahBeyazForm( Nil );

  // Üç saniye sonra eski rengine dönmesini sağlamak için (bu da bonus)...
  Timer_ID := SetTimer(Handle, 0, 3000, @MesajTimer);
end;
- Çalışmalarınızda başarılar...
En son mrmarman tarafından 14 Oca 2007 09:50 tarihinde düzenlendi, toplamda 8 kere düzenlendi.
Resim
Resim ....Resim
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Bazı bileşenlere dokunmuyorsa da güzel olmuş hocam, eline emeğine sağlık :)
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Recep hocam kanıma girdin ben de kolları sıvadım... :o

- Şimdiki halini daha çok seveceksin. İlk seferinde bahsettiğim şekilde GDI ile yaptım.

- Önce tüm formun (başlığı dahil) detaylı bir resmini çekilip öyle uygulamaya koydurdum.

- AlphaBlend procedure değişikliği yaptım daha hızlı bir method vardı onu koydum.

- Afiyet olsun.... 8)
Resim
Resim ....Resim
Kullanıcı avatarı
TRSoft
Kıdemli Üye
Mesajlar: 636
Kayıt: 13 Şub 2004 11:39
Konum: Konya
İletişim:

Mesaj gönderen TRSoft »

@mrmarman abi ellerine sağlık..

Bende dün bu konuda bir araştırma yapmaya başlamıştım ve bugün burada sen yayınlamışsın abi. :)

İşte ben bu forumu neden bu kadar çok seviyorum şimdi daha iyi anladım :lol:
İlimle geçen bir gece,
ibadetle geçen bin geceden hayırlıdır.
HZ. MUHAMMED (S.A.)
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

TRSoft yazdı:@mrmarman abi ellerine sağlık..

Bende dün bu konuda bir araştırma yapmaya başlamıştım ve bugün burada sen yayınlamışsın abi. :)

İşte ben bu forumu neden bu kadar çok seviyorum şimdi daha iyi anladım :lol:
İşin güzelliği de burada hocam :)
mrmarman yazdı:- Recep hocam kanıma girdin ben de kolları sıvadım... :o ...
Hocam gene döktürmişsin, eline sağlık çok güzel oldu.. bizzat denedim :wink:

Hocam gri tonlamaya çevirdikten sonra formun sağ üstündeki kapatma vs düğmelerinin üzerine gelince gece parlayan kedi gözleri gibi oluyor :lol: :lol:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
gkimirti
Admin
Mesajlar: 1956
Kayıt: 02 Eyl 2003 04:44
Konum: İstanbul

Mesaj gönderen gkimirti »

Ellerine sağlık Muharrem hocam,
peki eski haline nasıl getirebiliriz formun gri halini
ÜŞENME,ERTELEME,VAZGEÇME
Kullanıcı avatarı
bluekid
Kıdemli Üye
Mesajlar: 541
Kayıt: 11 Haz 2004 10:45
İletişim:

Mesaj gönderen bluekid »

:D
Kullanıcı avatarı
TRSoft
Kıdemli Üye
Mesajlar: 636
Kayıt: 13 Şub 2004 11:39
Konum: Konya
İletişim:

Mesaj gönderen TRSoft »

gkimirti yazdı:Ellerine sağlık Muharrem hocam,
peki eski haline nasıl getirebiliriz formun gri halini
Gökmen hocam ben denemelerimde formu refresh edince eski halini alıyor. Resim
İlimle geçen bir gece,
ibadetle geçen bin geceden hayırlıdır.
HZ. MUHAMMED (S.A.)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Selam..

Kod: Tümünü seç

  SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, Nil,
  SPIF_SENDWININICHANGE);
- Afiyet olsun
Resim
Resim ....Resim
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Arkadaşlar kodu güncelledim. Yeni halini öncekilerden de çok seveceksiniz.. :o

- Lütfen kodu bütünüyle tekrar deneyiniz, ekstra girdi var.

1. Button içindeki operasyon SiyahBeyaz isimli Procedure halini aldı.
2. Bu procedure'e Eksiltme diye bir değişken eklendi. Tüm ekranın siyah beyaz yapılması için gereken süre ile sadece küçük bir formunki ile dengelenmek için Büyük formda çok eksiltme, Küçük formda az eksiltme oluyor. Bu da While döngüsünden erken veya daha geç çıkma sonucu ile yaklaşık eşitliği yakaladım.
3. Aynı procedure için parametre olarak aktif formu verirseniz sadece o form içeriği, NIL verirseniz o zaman tüm windows ekranı siyahbeyaz etkiyi alıyor..
4. Button uygulamasına bir de formun eski halini aldığı kodu size göstermek için üç saniye sonra formun eski halini alan dynamic Timer ekledim.

- Afiyet olsun
Resim
Resim ....Resim
Kullanıcı avatarı
TRSoft
Kıdemli Üye
Mesajlar: 636
Kayıt: 13 Şub 2004 11:39
Konum: Konya
İletişim:

Mesaj gönderen TRSoft »

@mrmarman abi teşekkürler.

Ufak bir düzeltme yapmak istiyorum abi müsadenle

Kod: Tümünü seç

//Procedure FormDC(Form:TForm; Bitmap:TBitmap); 
Procedure FormDC(Form:HWDN; Bitmap:TBitmap);
var
  DC, DCWind        : HWND;
  rc                : TRect;
begin
//  DCWind := Form.Handle; 
  DCWind := Form;
  GetWindowRect(DCWind, rc);
  with Bitmap do
  try
    Width  := abs(rc.Right - rc.Left);
    Height := abs(rc.Bottom - rc.Top);
    DC := GetDC(GetDesktopWindow);
    try
      BitBlt( Canvas.Handle, 0, 0, Width, Height, DC, rc.Left, rc.Top, SRCCOPY);
    finally
      ReleaseDC(GetDesktopWindow, DC);
    end;
  finally
//    ReleaseDC(Form.Handle, DCWind); 
    ReleaseDC(Form, DCWind);
  end;
end;
remli satırlar yerine yukarıdaki şekilde düzeltince çalışdı.

siyahbeyaz proceduresinden formdc proceduresini çağırırken Tform yerine handle parametre olarak gönderdiğimiz için yukarıdaki şekilde düzeltme ihtiyacı duydum.
İlimle geçen bir gece,
ibadetle geçen bin geceden hayırlıdır.
HZ. MUHAMMED (S.A.)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

:lol: O bloğu güncelledim sanmıştım unutmuşum.. :oops: Düzelttim.
Resim
Resim ....Resim
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

Hocam camiyi yapt?n minare de tamam art?k :wink: :)
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4740
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Hocam her soruya bir minare kampanyası var :lol:
Resim
Resim ....Resim
Kullanıcı avatarı
rsimsek
Admin
Mesajlar: 4482
Kayıt: 10 Haz 2003 01:48
Konum: İstanbul

Mesaj gönderen rsimsek »

mrmarman yazdı:Hocam her soruya bir minare kampanyası var :lol:
:lol: :lol: :lol:
Bilgiyi paylaşarak artıralım! Hayatı kolaylaştıralım!!
Cevapla