Python Imaging
                          Kütüphanesi




                                                 Mustafa Başer

                          © 2007 by Mustafa Başer1 <mbaser (at) ibu.edu.tr>

                                   Son Güncelleme: 18:11 18 Nisan 2007




1   Yazardan izin alınmaksızın yayımlanamaz, ticari amaçla kullanılamaz ve İnternet üzerinden
    dağıtılamaz, başka bir sitede barındırılamaz. Her türlü eğitim amaçlı ve kişisel kullanımlar için
    serbesttir. Diğer kullanımlar için yazara danışılmalıdır.
1 Giriş


       1.1 Imaging (PIL) Nedir?


              Imaging       (PIL),   Pythonware      (http://www.pythonware.com/products/pil/)
              tarafından Python için geliştirilmiş resim işleme ve oluşturma kütüphanesidir.
              Perl, PHP ve diğer betik programlama dillerinde sık kullanılan GD (graphic
              Driver) modülünden farklı olarak, PIL birçok özellik sunar. Bunlar arasında, var
              olan resimden bir kısmı kopyalayıp başka bir reim üzerine kopyalama, resim
              filtreleri gibi bir resim düzenleme programında olan özellikleri sunar. Bu sayede
              yeni oluşturulacak bir resmin veya daha önceden var olan resim için
              programlayıcıya, GIMP veya benzeri resim işleme araçlarında yapabileceklerinin
              bazılarını Python programı altında yapması için olanak sunar. Bu işlemler
              özellikle web üzerinden dinamik resim sunmayı amaçlayan programcılar için
              oldukça yaralıdır. Yoksa bir resmin bir köşesine başka bir resmi yapıştırmak için
              Python programı yazmak için değildir. Bu amaç için GIMP'i kullanabilirsiniz.

              Imaging, diğer adıyla PIL oldukça kompleks resim işleme yapabilme kabiliyetine
              bağlı olarak, kullanılmasında bazı güçlükler vardır. Aslında buna güçlük demek
              yerine kompleks bir yapıya sahip demek daha doğru olacaktır. Eğer basit resim
              oluşturacaksanız PIL muhtemelen size fazla gelecektir. Bu gibi programcıların
              gd-modul'ü kullanması tavsiye edilir. gd-module'ün indirmek ve kullanımı ile ilgili
              detaylara ulaşmak için http://newcenturycomputers.net/projects/gdmodule.html
              adresini kullanabilirsiniz. Gd-module birkaç fonksiyondan başka bir şey
              sunmayan basit (fakat hızlı) resim oluşturma programıdır.

              Imaging ile arşivleme işlemleri yapabilirsiniz. Thumbnail oluşturabilir, resim
              biçimlerini    birbirine çevirebilirsiniz. Postscript çıktı   alabilir,   PDF2
              oluşturabilirsiniz.

              Bu rehber hazırlanırken çoğunlukla Python Imaging Library Handbook el
              kitabından yararlanılmıştır. Bu rehber hazırlanırken Fedora Core 6 ve üzerinde
              kurulu python-2.4.4-1.fc6 ve Image-1.1.5 kullanılmıştır.

              Rehberi okuyanın Python programlama dilinin temellerini bildiği ve resim
              biçimleri ile ilgili genel bilgiye sahip olduğu varsayılmıştır.




2   Her ne kadar PIL ile PDF oluşturabilseniz de, eğer amacınız Python altında PDF dokümanları oluşturmak ise,
    PIL yerine ReportLab (http://www.reportlab.org/rl_toolkit.html) geliştirilen kütüphaneyi kullanmalısınız.


2                                                                                 © Mustafa Başer – 2007
Imaging (PIL) Nasıl Elde Edilir?


     1.2 Imaging (PIL) Nasıl Elde Edilir?


          Imaging (PIL) hemen her Python dağıtımı ile birlikte ön tanımlı olarak gelir. Bu
          nedenle, Python'un doğal resim işleme kütüphanesi olarak tanımlanır.

          Python komut satırını açıp aşağıdaki komutu işleterek sisteminizde yüklü olup
          olmadığını anlayabilirsiniz:
             >>> import Image

          Eğer sisteminizde yüklü değilse http://www.pythonware.com/products/pil/
          adresinden, sisteminize uygun sürümü indirip kurabilirsiniz. Image sürümünü
          öğrenmek Image modülündeki VERSION sabitine bakabilirsiniz:
             >>> Image.VERSION
             '1.1.5'

          Bu rehberde kullanılan sürüm 1.1.5 olduğundan, eski ya da yeni sürümlerinde
          birtakım değişikliklerin olması normaldir.




© Mustafa Başer – 2007                                                                   3
2 Rehber


    2.1 Image Sınıfı


        PIL'in en önemli sınıfı Image 'dir. Image aynı isimli modüle içerisindedir. Image
        sınıfını kullanarak birçok resim işlemi yapabilir veya yeniden resim
        oluşturabilirsiniz.

        Daha önceden var olan bir resmi açmak için Image modülündeki open metodu
        kullanmalısınız:
          >>> import Image
          >>> res=Image.open("python-logo.gif") # http://www.python.org/images/python-
          logo.gif

        Eğer sonuç başarılı ise, metot Image nesnesini döndürecektir. Bu nesneye ait
        metotları kullanarak, resim üzerindeki işlemlerinizi yapabilirsiniz. Nesne
        içerisindeki metotları dir fonksiyonu ile görebilirsiniz.

        Örneğin resim biçimi, resim boyutu (piksel olarak) ve resim kipi görüntüleyelim:
          >>> print res.format, res.size, res.mode
          GIF (211, 71) P

        Burada görüldüğü gibi resim biçimimiz GIF, resmimizin boyu 211x71 (enxboy)
        piksel ve resim kipimiz P'dir. Resim kipi, resimdeki band sayısı ve resmi ile
        piksel ve derinlik bilgilerini içerir. Çok kullanılan resim kipleri; siyah-beyaz
        resimler için L, doğru renk resimler için RGB, ön baskı resimler için CMYK'dır.

        Resim nesnesini elde etmişseniz, resmi görüntülemek için show metodunu
        kullanabilirsiniz:
          >>> res.show()

        Bu metodu işlettiğinizde, sisteminizdeki ön tanımlı resim görüntüleyicisi
        içerisinde resminiz açılacaktır.




4                                                               © Mustafa Başer – 2007
Resimlerin Okunması ve Yazılması


     2.2 Resimlerin Okunması ve Yazılması


          PIL birçok resim biçimini desteklemektedir. Bir resim dosyasını açmak için open
          metodunu kullanmalısınız. PIL'de resim dosyalarını açarken, resim biçimini
          bilmenize gerek yoktur, PIL otomatik olarak resim biçimi algılar ve döndürülen
          nesnedeki metotlar ona göre adapte edilir.

          PIL'de dosyaları kaydederken, açılan resim nesnesindeki save metodu kullanılır.
          Resimler kaydedilirken, resim biçimi belirtilmediği taktirde, resim uzantısına
          göre resmin hangi biçimde kaydedileceği saptanmaya çalışılır.

          PIL'de resim açma ve kaydetmeye örnek olarak, yukarıda açtığımız python-
          logo.gif resmini JPG olarak kaydedelim:

             >>> res.save("python-logo.jpg")
             Traceback (most recent call last):
               File "<stdin>", line 1, in ?
               File "/usr/lib/python2.4/site-packages/PIL/Image.py", line 1305, in save
                 save_handler(self, fp, filename)
               File "/usr/lib/python2.4/site-packages/PIL/JpegImagePlugin.py", line 390, in
             _save
                 raise IOError("cannot write mode %s as JPEG" % im.mode)
             IOError: cannot write mode P as JPEG

          Burada görüldüğü gibi P kipindeki bir resmin JPG olarak kaydedilemeyeceği
          belirtiliyor. O halde resim kipini JPG olarak kaydedebileceğimiz bir kipe
          dönüştürmemiz gerekir. RGB JPG için geçerli bir kiptir:
             >>> res.mode="RGB"

          Şimdi resmi kaydedebiliriz:
             >>> res.save("python-logo.jpg")

          Programımızın tamamı aşağıdaki gibi olacaktır:
             >>>   import Image
             >>>   res=Image.open("python-logo.gif")
             >>>   res.mode="RGB"
             >>>   res.save("python-logo.jpg")

          Web programcıları, resimleri yayımlarken çoğunluka onların ön izlemesini
          ziyaretçilere göstermek ister. Bu sayede ziyaretçi, ilgilendiği resmin büyüğünü
          görebilir. Bunun nedeni hem ziyaretçi hem de yayımcı için daha az veri
          transferinin sağlanmasıdır. Eğer var olan resimlerinizin orijinal boyutlarını
          koruyarak, ziyaretçiye daha küçük ön izleme (thumbnail) göndermek
          istiyorsanız, bunu PIL ile bir iki satırda yapabilirsiniz. http://lwn.net/ adresinden
          alınan birkaç penguen resimleri penguenler klasörüne kaydedildi. Şimdi bu
          resimlerin küçük ön izleme (thumbnail) resimlerini oluşturalım:
             #!/usr/bin/python

             import os
             import Image

             klasor='penguenler'
             kucukler='onizleme'

             if not os.path.exists(kucukler):
                    os.mkdir(kucukler)


© Mustafa Başer – 2007                                                                        5
Resimlerin Okunması ve Yazılması

             for i in os.listdir(klasor):
                    res=Image.open(klasor+'/'+i)
                    res.thumbnail((100, 100))
                    res.save(kucukler+'/'+i)

          Eğer programınız bir web sayfasını yayımlayacaksa, o zaman bir CGI programı
          yazabilirsiniz. Bu program yeni oluşturulan küçük resimleri yeni bir klasöre
          yazmak yerine, doğrudan ekrana basmalıdır. “PIL ve CGI” bölümde, PIL ile
          oluşturulan resimlerin CGI ile nasıl yayımlanabileceğini öğreneceksiniz.



     2.3 Kesme, Yapıştırma ve Resimlerin Birleştirilmesi


          Image sınıfı size resim alanları üzerinde işlem yapmanızı sağlayacak birçok araç
          içermektedir. Bir resimden, dikdörtgen şeklindeki bir alanı almak için crop
          metodunu kullanmalısınız.

          Aşağıdaki resimde yakışıklı bir penguenin boydan resmi var.




                                 tux-thinkpad.gif (tam boy)



          Bu resimden yakışıklı bir vesikalık resim yapmak istiyoruz, o halde penguenin
          sadece kafa kısmına ihtiyacımız var. Bunun için önce resmi açalım, bu resimden
          dikdörtgen bir alan kopyalayalım ve bunu kaydedelim:
             >>>   res=Image.open("tux-thinkpad.gif")
             >>>   kutu=(60,6,150,96)
             >>>   alan=res.crop(kutu)
             >>>   alan.save('yeni.gif')

          Kaydettiğimiz yeni.gif resmi aşağıdaki gibi olacaktır.




© Mustafa Başer – 2007                                                                  6
Kesme, Yapıştırma ve Resimlerin Birleştirilmesi




                                        yeni.gif (vesikalık)


          Bu programda yaptıklarımızı açıklayalım. Öncelikle resmimizi res nesnesi açtık.
          Daha sonra bir kutu tanımladık. Bu kutu, resimden kopyalayacağımız alanı
          belirlemektedir. Bu kutu şu şekilde tanımlanır:

                                                  (X1, Y1, X2, Y2)

          Buradaki indisler şu şekildedir:

          X1: piksel olarak seçilecek alanın yatay başlangıç noktası
          X2: piksel olarak seçilecek alanın dikey başlangıç noktası
          Y1: piksel olarak seçilecek alanın yatay bitiş noktası
          Y2: piksel olarak seçilecek alanın dikey bitiş noktası

          Bun görsel olarak aşağıdaki şekilde olduğu gibi gösterebiliriz.

                             (X1, Y1)




                                                               (X2, Y2)


          res nesnesine atanan Orijinal resimden, kutu ile tanımlanan alanı alan
          nesnesine kopyalama için crop metodu kullanılmıştır. alan nesnesi yeni bir
          resim nesnesi, olduğundan herhangi bir resim üzerinde yapılabilecek tüm
          işlemler, yeni nesne için de geçerlidir. crop metodu tüp (ya da liste) şeklinde bir
          parametre alır. Bu tüp (Ya da liste) dört elemandan oluşmalıdır ve bunlar
          yukarıda belirtildiği gibi alanın başlangıç ve bitimini gösteren 4 sayı (integer)
          değer olmalıdır.

          Kopyaladığımız m 90x90 boyutundadır:
             >>> alan.size
             (90, 90)

          Herhangi bir resim nesnesinde saklı resmi istediğiniz bir açı ile döndürebilirsiniz.
          Döndürme işlemi rotate metodu ile yapılır. Örneğin vesikalık resmimizi tepe-
          taklak çevirelim:
             >>> ters=alan.rotate(180)
             >>> ters.save("ters-vesikalik.gif")

          ters-vesikalik.gif resmi aşağıdaki gibi olacaktır.




© Mustafa Başer – 2007                                                                       7
Kesme, Yapıştırma ve Resimlerin Birleştirilmesi




                          ters-vesikalik.gif (180o döndürülmüş )



          rotate metodu, bir resim nesnesini kendisine parametre olarak verilen açı
          (derece cinsinden) kadar döndürüp yeni bir resim nesnesi döndürür. Elbette ki
          bir resim nesnesini tersine döndürüp yine kendisine atayabilirsiniz:
             >>> alan=alan.rotate(180)

          Bu işlem, alan nesnesi içerisinde saklanan resmi 1800 döndürmüş olacaktır.

          Bir resim nesnesini, başka bir resim nesnesi üzerine yapıştırmak için paste
          metodu kullanılır. paste metodu iki parametre alır: birincisi, yapıştırılacak olan
          resim nesnesi, ikincisi resim nesnesinin yapıştırılacağı alanı belirleyen
          koordinat. Bu koordinat, yukarıda tanımlanan kutu şeklinde olmalıdır.
          Yapıştırılacak olan nesne'nin boyutu ile kutunun boyutu aynı olmalıdır.

          Tam boy penguen resminden vesikalık bir resim üretmiştik. Bu vesikalık resim
          penguen'in kafası idi. Daha sonra bu kafayı ters döndürdük. Şimdi bu kafayı aynı
          kutuyu kullanarak tam boy penguen resmine yapıştırırsak, penguenin kafasını
          tepe-taklak çevirmiş oluruz:
             >>> res.paste(alan, kutu)
             >>> res.save("ters-kafali-penguen.gif")

          ters-kafali-penguen.gif resmimiz aşağıdaki gibi olacaktır.




                      ters-kafali-penguen.gif (ters kafalı penguen! )




© Mustafa Başer – 2007                                                                    8
Kesme, Yapıştırma ve Resimlerin Birleştirilmesi

          PIL, çok bantlı resimlerde, bantlar üzerinde işlem yapmanızı, ya da bantları
          birleştirmenizi sağlayabilir. Çok bantlı bir resmin açıldığı resim nesnesinde,
          bantları ayırarak her birini bir resim nesnesine atamanızı sağlayacak olan metot
          split' dir. Aşağıdaki şekilde         RGBA kipine sahip lsap_tux.png resmi
          görünmektedir.




                                 RGBA kipli lsap_tux.png



          Şimdi bu resmi bir nesneye açalım ve resmi bantlarına ayıralım:
             >>> res=Image.open("lsap_tux.png")
             >>> r,g,b,a=res.split()

          Eğer r, g, b, ve a'yı kaydedecek olursak aşağıdaki gibi resimler elde ederiz:

          r.save("r.png"); g.save("g.png"); b.save("b.png"); a.save("a.png")




                  lsap_tux.png resminin sırası ile R, G, B ve A bantları



          Ayrışmış bantlar üzerinde çalıştıktan sonra bunları tekrar birleştirmek için merge
          metodunu kullanabilirsiniz. Yukarıda bantlarına ayrıştırdığımız resmi farklı bir
          sıra ile birleştirelim:
             >>> yeni=Image.merge("RGBA", (b, g, r, a))
             >>> yeni.save("yeni.png")

          yeni.png resmimiz aşağıdaki gibi olacaktır.




© Mustafa Başer – 2007                                                                    9
Kesme, Yapıştırma ve Resimlerin Birleştirilmesi




                    b,g,r,a sırası ile birleştirilmiş lsap_tux.png resmi




     2.4 Geometrik Dönüşümler


          Image sınıfı, resimleri yeniden boyutlandırmak için reisize ve döndürme işlemi
          yapmak için rotate metodunu içerir. rotate metodu daha önce anlatılmıştı.

          Bu resmin boyutlarını iki katına çıkarmak için aşağıdaki işlemi yapabiliriz:
             >>> en,boy=yeni.size
             >>> ikiKat=yeni.resize((2*en,2*boy))
             >>> ikiKat.save("ikiKat.png")

          Burada unutulmaması gereken resmin boyutunun iki katına çıkmış olmasıdır, bir
          resmin yanına (Ya da üstüne, altına) başka bir resim eklemek istiyorsanız, önce
          daha büyük tuvale sahip yeni bir resim oluşturmalı ve bu iki resmi bu tuvale
          yapıştırmalısınız. Örneğin tux-thinkpad.gif ve lsap_tux.png resimlerini yan
          yana yapıştırarak tek bir resim elde etmeye çalışalım. Öncelikle bu resimleri
          yeniden açalım:
             >>> res1=Image.open("tux-thinkpad.gif")
             >>> res2=Image.open("lsap_tux.png")

          Yeni tuvalimizin boyutunu bilmemiz gerekiyor. Resimleri yan yana
          yapıştıracağımıza göre, yeni tuvalin eni her iki resmin enleri toplamı kadar
          olmalıdır. O halde en'i şu şekilde hesaplayabiliriz:
             >>> en=res2.size[0]+res2.size[0]

          Şimdi boyunu belirleyelim. Yeni resmin boyu, büyük olan resmin boyu kadar
          olmalıdır. O halde önce kimin büyük olduğuna bakalım:
             >>> res1.size[1]
             249
             >>> res2.size[1]
             120

          Birinci resmin boyu daha büyük olduğuna göre, boy:
             >>> boy=res1.size[1]

          Şimdi yeni resmimizi oluşturalım:
             >>> res=Image.new("RGBA",(en,boy))



© Mustafa Başer – 2007                                                                    10
Geometrik Dönüşümler

          Önce birinci resmimizi yapıştıralım. Bunun için yukarıda anlatılan kutu şekilde
          olmalıdır:
             >>> kutu1=(0,0,res1.size[0], res1.size[1])
             >>> res.paste(res1, kutu1)

          Şimdi ikinci resmimizi yapıştırabiliriz. Bunun için belirleyeceğimiz kutunun X1
          (yatay) başlangıç noktası, ilk resmin eninin bittiği yerdir. Y1 (dikey başlangıç
          noktası ise 0'dır. O halde:
             >>> X1=res1.size[0]
             >>> Y1=0

          Resmin yatay bitiş noktası (X2), ilk resmin yatay bitişi ile ikinci resmin eninin
          toplamıdır. Dikey bitiş noktası (Y2) ise ikinci resmin enidir:
             >>> X2=res1.size[0]+res2.size[0]
             >>> Y2=res2.size[1]

          Şimdi ikinci resmi yapıştırabiliriz:
             >>> res.paste(res2, (X1,Y1,X2,Y2))
             >>> res.save("ikili_penguen.png")

          ikili_penguen.png aşağıdaki gibidir.




                         ikili_penguen.png (iki penguen yanyana)



     2.5 Kip Dönüşümü


          Image nesnesinde kip dönüşümünü iki şekilde yapabilirsiniz. Ya resim nesnesine
          convert metodunu uygulayabilir veya, resim nesnesinin mode uzantısını
          istediğiniz   kipe    eşitleyebilirsiniz. Eğer    var    olan   resminizin   kipini
          değiştirecekseniz, mode uzantısını eşitleyin. Eğer var olan resim nesnesinin kipini
          değiştirip başka bir nesneye atayacaksanız convert metodunu kullanın. Daha iyi
          anlamak için şu örneğe bakalım:
             >>> ikiKat.mode


© Mustafa Başer – 2007                                                                    11
Kip Dönüşümü

             'RGBA'
             >>> ikiKat.mode="L"
             >>> ikiKat.mode
             'L'

          Burada resmimizin kipini değiştirdik. Aşağıdaki programda yeni kipte (siyah-
          beyaz) başka bir resim nesnesi elde ettik:
             >>> ikiKat=yeni.resize((2*en,2*boy))
             >>> ikiKat.mode
             'RGBA'
             >>> baska=ikiKat.convert("L")
             >>> baska.mode
             'L'



     2.6 Resim Artırma (Enhancement)


          PIL resim artırmak için birçok metot ve modüle sağlamaktadır. Bunları sırası ile
          inceleyelim.


       Filtreler

          ImageFilter modülü ön tanımlı birçok filtre içerir. Bu filtreler, resim nesnesini
          filter metodu kullanılarak uygulanır. Örneğin yukarıdaki penguene EMBOSS
          filtresini uygulayalım:
             >>>   import ImageFilter
             >>>   res=Image.open("lsap_tux.png")
             >>>   embosRes=res.filter(ImageFilter.EMBOSS)
             >>>   embosRes.save("lsap_tux_emboss.png")

          Resmimize bakacak olursak aşağıdaki şekilde olduğu gibi görünecektir.




                          EMBOSS filtresi uygulanmış penguenimiz



          Diğer filtreler şunlardır: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE,
          EDGE_ENHANCE_MORE, FIND_EDGES, SHARPEN, SMOOTH, SMOOTH_MORE.

          Örneğin yukarıdaki resme FIND_EDGES filtresi uygularsak:
             >>> res.filter(ImageFilter.FIND_EDGES).save("kenarlar.png")

          kenarlar.png resmimiz aşağıdaki gibi olur.



© Mustafa Başer – 2007                                                                  12
Resim Artırma (Enhancement)




                                  Penguenin kenarları




       Artırma

          İleri resim artırma için, ImageEnhance modülü içerisindeki sınıfları kullanmanız
          gerekir. Bu sayede resminizde kontrast, parlaklık ve renk dengesini
          ayarlayabilirsiniz. Yukarıdaki resmimizin kontrastını değiştirelim:




© Mustafa Başer – 2007                                                                 13
3 ImageDraw Modülü

     Bir programlama dili altında resimlerle uğraşmanın belkide en temel nedeni,
     eldeki verileri grafikler halinse sunmaktır. Özellikle web programcılarının sıklıkla
     kullandığı bir yöntemdir. Eldeki veriyi grafik halinde sunmak için PIL yeteri kadar
     çizim fonksiyonu sunar. Bu fonksiyonlar ImageDraw modülü içerisindedir.

     Başlangıç örneği olarak, penguen (lsap_tux.png) resmimizin kenarından 5 pixel
     uzaklıkta bir dikdörtgen çizelim:
       >>>   import Image, ImageDraw
       >>>   res = Image.open("lsap_tux.png")
       >>>   ciz = ImageDraw.Draw(res)
       >>>   ciz.rectangle((5,5,res.size[0]-5, res.size[1]-5), outline="#ff0000")
       >>>   del ciz
       >>>   res.save("cerceveli.png")

     Çerçeveli penguen resmimiz aşağıdaki gibi olacaktır.




                       Çerçeveli Penguen (cerceveli.png)




     Şimdi burada kullandığımız fonksiyon ve parametrelerine bir bakalım. Çizim
     işlemleri ile ilgili fonksiyonlar ImageDraw modulünde olduğundan ilk satırda Image
     ve ImageDraw modüllerini yükledik. Daha sonra resmimizi res nesnesine açtık.
     res nesnesinden çizim nesnemizi oluşturmak için ImageDraw.Draw (res) sınıfını
     kullandık. Artık resim üzerindeki tüm çizimler ciz nesnesi aracılığı ile
     yapılacaktır. Draw sınıfında bulunan rectangle metodu ile resmimizin etrafına bir
     çerçeve çizdik. Bu çerçeve, dıştan 5 piksel olacak şekildedir. rectangle ve diğer
     metotlarda kullanılan outline parametresi, çizimin rengini belirtir. Burada
     hexadecimal yazımını kullandık. Benzer şekilde rgb renklerini de kullanabilirdik.
     Örneğin kırmızı çerçeve çizmek için "rgb(100%,0%,0%)" yazımı da kullanılabilirdi.
     rectangle metodunun kullanımını aşağıda okuyabilirsiniz. Çiziminiz bitince ciz
     nesnesini hemen silmelisiniz, aksi halde hafızda boşuna yer kaplayacaktır.




14                                                             © Mustafa Başer – 2007
ImageDraw Metotları


     3.1 ImageDraw Metotları


       rectangle

          ciz.rectangle(kutu, secenekler)

          Resim üzerine dikdörtgen çizmek için kullanılır. burada kutu tanımı sayfa 7'da
          verilmiştir. Seçenekler ise birçok ImageDraw metodunda kullanılan outline ve
          fill parametrelerini belirti. outline dikdörtgenin rengini, fill ise dikdörtgenin
          içerisinin hangi renk ile doldurulacağını gösterir. Renk tanımlarını hexadecimal
          veya RGB olarak verebilirsiniz. Aşağıda yeni bir resim oluşturup, bu resim
          üzerine çizilen dikdörtgenler görünmektedir.
              import Image, ImageDraw
              res = Image.new("RGB",(200,200), "#EFECE9")
              ciz = ImageDraw.Draw(res)
              ciz.rectangle((5,5,50,95), fill="rgb(70%,40%,10%)")
              ciz.rectangle((5,100,195,195), outline="#0000ff", fill="#aabbcc")
              ciz.rectangle((55,5,195,95), outline="#00ff00")
              del ciz
              res.save("diktortgenler.png")

          Bu program geri zemin üzerine aşağıdaki resimde görünen dikdörtgenleri
          oluşturacaktır.




                          Çeşitli dikdörtgenler (diktortgenler.png)


       line

          ciz.line(kutu, secenekler)

          kutu (sayfa 7'daki tanıma bakınız) ile verilen dikdörtgenin sol üst köşesinden,
          sağ alt köşesine bir doğru çizer. Burada kutu tanımını şu şekilde de
          algılayabilirsiniz (x1,y1) çizginin başlangıç noktası, (x2,y2) çizginin bitiş noktası.
          Aşağıdaki program penguenin köşegenlerinden birer çizgi çekmektedir.
              >>> import Image, ImageDraw
              >>> res = Image.open("lsap_tux.png")
              >>> ciz = ImageDraw.Draw(res)


© Mustafa Başer – 2007                                                                       15
ImageDraw Metotları

             >>>   ciz.line((0,0,res.size[0], res.size[1]), fill="#ff0000")
             >>>   ciz.line((0,res.size[1], res.size[0], 0), fill="#00ff00")
             >>>   del ciz
             >>>   res.save("lsap_tux_carpi.png")

          Bu program kodu, lsap_tux.png resmini açacak ve köşegenlerinden kırmızı ve
          yeşil çizgi çizmiştir (aşağıdaki şekilde).




                         Bu pengueni çizmişleri (lsap_tux_carpi.png)




       arc

          ciz.arc(kutu, baslamaAcisi, bitmeAcisi, secenekler)

          Verilen  kutu (sayfa 7'daki tanıma bakınız) içerisinde başlangıç açısı
          baslamaAcisi ve bitiş açısı bitmeAcisi ile belirtilen bir yay çizer. Yay'ın
          seçenekleri fill olabilir. Bir yay kutu içerisine nasıl yerleşiyor bunu görmek için,
          önce arka planı sarı olan yeni bir resim tuvali oluşturalım, daha sonra bu tuval
          üzerine kutu ile verilen dikdörtgen çizelim ve içerisine aynı kutu ile verilen yarım
          çember çizelim. Yarım çember başlangıç açısı 0o ve bitiş açısı 180o olan yaydır.
          Aşağıdaki programı inceleyin:
             >>>   import Image, ImageDraw
             >>>   res = Image.new("RGB",(120,120), "#ffff00")
             >>>   ciz = ImageDraw.Draw(res)
             >>>   kutu=(10,10,110,110)
             >>>   ciz.rectangle(kutu, outline="#0000ff")
             >>>   ciz.arc(kutu, 0, 180, fill="#ff0000")
             >>>   del ciz
             >>>   res.save("yay.png")

          Bu program kodu aşağıdaki resmi üretecektir:




© Mustafa Başer – 2007                                                                     16
ImageDraw Metotları




                          Yayın kutu içerisine yerleşmesi (yay.png)




          Burada görüldüğü gibi, çizilen yay eğer tam çember ise kutu ile belirtilen alan
          içerisine tam sığacak şekilde yay çizilmektedir. 0o saat 3 konumundan başlayıp,
          saat yönünde derece cinsinden ölçülmektedir.

          Şimdi bu öğrendiğimizi kullanarak bir hilal çizelim. Hilalimiz kırmızı zemin
          üzerine beyaz renkli olsun. Aşağıdaki program kodunu inceleyin:
             import Image, ImageDraw
             res = Image.new("RGB",(120,120), "#ff0000")
             ciz = ImageDraw.Draw(res)
             ciz.arc((10,10,110,110), 0,180, fill="#ffffff")
             ciz.arc((10,20,110,100), 0,180, fill="#ffffff")
             del ciz
             res.save("hilal.png")

          Bu program kodu aşağıda görünen hilali çizecektir.




                     İki yayın kesişmesi ile ortaya çıkan hilal (hilal.png)




       chord

          ciz.chord(kutu, baslamaAcisi, bitmeAcisi, secenekler)

          arc (yay) ile aynıdır, ancak yayın başlama ve bitişi arasında bir çizgi çizer.
          Aşağıdaki örnekte, kutu içerisinde kirişin nasıl yerleştiğini görüyorsunuz:
             >>>   import Image, ImageDraw
             >>>   res = Image.new("RGB",(120,120), "#ff0000")
             >>>   ciz = ImageDraw.Draw(res)
             >>>   kutu = (10,10,110,110)
             >>>   ciz.rectangle(kutu, outline="#0000ff")


© Mustafa Başer – 2007                                                                        17
ImageDraw Metotları

             >>> ciz.chord(kutu, 0,180, outline="#0000ff", fill="#ffffff")
             >>> del ciz
             >>> res.save("kiris.png")

          Yukarıdaki programın ürettiği resim aşağıdaki şekilde görülmektedir:




                         Kutu içerisine kirişin yerleşmesi (kiris.png)




          Yukarıdaki hilal örneğimizde, hilalin içi beyaz olsun istiyorsak, ilkinin içi beyaz
          kiriş ikincisinin için kırmızı kiriş yapmamız gerekecektir:
             import Image, ImageDraw
             res = Image.new("RGB",(95,120), "#ff0000")
             ciz = ImageDraw.Draw(res)
             ciz.chord((10,10,85,110), 0,180, fill="#ffffff")
             ciz.chord((10,20,85,100), 0,180, fill="#ff0000")
             del ciz
             res.save("hilal.png")

          Bu program aşağıda görünen kırmızı zemin üzerinde beyaz hilalli oluşturacaktır:




                                  İçi beyaz hilal (hilal.png)




          Merkezine bir de yıldız kondurmamız gerekecek!


       ellipse

          ciz.ellipse(kutu, secenekler)

          Verilen kutu içerisine elips çizer.




© Mustafa Başer – 2007                                                                    18
ImageDraw Metotları


       pieslice

          ciz.pieslice(kutu, baslamaAcisi, bitmeAcisi, secenekler)

          acr (yay) ile aynıdır ancak yayın uçları ile merkez arasında bir çizgi çizer.
          Aşağıda basit bir örnek görünüyor:
             import Image, ImageDraw
             res = Image.new("RGB",(120,120), "#ff0000")
             ciz = ImageDraw.Draw(res)
             ciz.pieslice((10,10,110,110), 0,75, fill="#ffffff")
             del ciz
             res.save("dilim.png")

          Bu program aşağıdaki resmi üretecektir:




                            İçi beyaz bir karpuz dilimi (dilim.png)




          Web üzerinden verileri pasta grafik olarak yansıtmak için sıkça kullanacağınız
          metot olacaktır. Örneğin 4 seçenekten oluşan bir anket hazırladık ve bu anketin
          sonuçları şu şekilde bulundu

                                    Seçenek     Oy Sayısı
                                        A           80
                                        B           49
                                        C           32
                                        D           76

          Bu seçenekleri secenek listesinde aşağıdaki gibi tuttuğumuzu varlayalım:
             >>> secenek = [80, 49, 32, 76]

          Burada her bir seçeneği farklı bir renkteki karpuz dilimi olarak göstermemiz
          gerekir. Bir daire 360o'den oluştuğuna göre her oy sayısına karşılık gelen açıyı
          hesaplamalıyız. Bunun için:
             >>>   secenek = [80, 49, 32, 76]
             >>>   toplamOy=0
             >>>   for i in secenek:
             ...       toplamOy += i
             ...
             >>>   print toplamOy
             237




© Mustafa Başer – 2007                                                                 19
ImageDraw Metotları

          O halde toplam oy sayımız 237 dir. Şimdi oy oranlarına göre her bir dilim için
          açıyı bulalım:
             >>> secenekBasinaAci=[]
             >>> for i in secenek:
             ...     secenekBasinaAci.append(int(round(360*(i/float(toplamOy)))))
             ...
             >>> print secenekBasinaAci
             [122, 74, 49, 115]

          Şimdi rastgele renk üreten bir fonksiyon yazalım:
             >>> import random
             >>> def rastgeleRenk():
             >>>    renk='#'
             >>>    for i in range(6):
             >>>            renk=renk+random.choice('0123456789abcdfe')
             >>>    return renk

          Son olarak açılara denk gelen dilimleri resim üzerine çizmek gerekecek:
             >>> import Image, ImageDraw
             >>> res = Image.new("RGB",(120,120), "#cccccc")
             >>> ciz = ImageDraw.Draw(res)
             baslangic=0
             bitis=0
             for i in secenekBasinaAci:
                     bitis=baslangic+i
                     ciz.pieslice((10,10,110,110), baslangic,bitis, fill=rastgeleRenk())
                     baslangic=bitis

             del ciz
             res.save("pasta.png")

          Bunların hepsini bir program olarak yazarsak:
             #!/usr/bin/python

             import Image, ImageDraw, random

             secenek = [80, 49, 32, 76]
             toplamOy=0
             for i in secenek:
                    toplamOy += i

             secenekBasinaAci=[]

             for i in secenek:
                    secenekBasinaAci.append(int(round(360*(i/float(toplamOy)))))

             def rastgeleRenk():
                    renk='#'
                    for i in range(6):
                            renk=renk+random.choice('0123456789abcdfe')
                    return renk

             res = Image.new("RGB",(120,120), "#cccccc")
             ciz = ImageDraw.Draw(res)
             baslangic=0
             bitis=0
             for i in secenekBasinaAci:
                     bitis=baslangic+i
                     ciz.pieslice((10,10,110,110), baslangic,bitis, fill=rastgeleRenk())
                     baslangic=bitis

             del ciz
             res.save("pasta.png")



© Mustafa Başer – 2007                                                                     20
ImageDraw Metotları

          Bu programın ürettiği resim aşağıdaki gibi olacaktır (sizde pasta dilimleri farklı
          renkler olacaktır)




                     Verileri pasta grafik olarak sunmak (pasta.png)




© Mustafa Başer – 2007                                                                   21
4 PIL ve CGI

     Python'un web programcıları için içerdiği birçok araç, onun web programlamada
     vazgeçilmez bir dil olmasını sağlamaktadır. Şimdi PIL ile oluşturulan bir resmin
     web sayfasında nasıl




                                                 Devam Edecek....




22                                                          © Mustafa Başer – 2007

Python Image Kütüphanesi

  • 1.
    Python Imaging Kütüphanesi Mustafa Başer © 2007 by Mustafa Başer1 <mbaser (at) ibu.edu.tr> Son Güncelleme: 18:11 18 Nisan 2007 1 Yazardan izin alınmaksızın yayımlanamaz, ticari amaçla kullanılamaz ve İnternet üzerinden dağıtılamaz, başka bir sitede barındırılamaz. Her türlü eğitim amaçlı ve kişisel kullanımlar için serbesttir. Diğer kullanımlar için yazara danışılmalıdır.
  • 2.
    1 Giriş 1.1 Imaging (PIL) Nedir? Imaging (PIL), Pythonware (http://www.pythonware.com/products/pil/) tarafından Python için geliştirilmiş resim işleme ve oluşturma kütüphanesidir. Perl, PHP ve diğer betik programlama dillerinde sık kullanılan GD (graphic Driver) modülünden farklı olarak, PIL birçok özellik sunar. Bunlar arasında, var olan resimden bir kısmı kopyalayıp başka bir reim üzerine kopyalama, resim filtreleri gibi bir resim düzenleme programında olan özellikleri sunar. Bu sayede yeni oluşturulacak bir resmin veya daha önceden var olan resim için programlayıcıya, GIMP veya benzeri resim işleme araçlarında yapabileceklerinin bazılarını Python programı altında yapması için olanak sunar. Bu işlemler özellikle web üzerinden dinamik resim sunmayı amaçlayan programcılar için oldukça yaralıdır. Yoksa bir resmin bir köşesine başka bir resmi yapıştırmak için Python programı yazmak için değildir. Bu amaç için GIMP'i kullanabilirsiniz. Imaging, diğer adıyla PIL oldukça kompleks resim işleme yapabilme kabiliyetine bağlı olarak, kullanılmasında bazı güçlükler vardır. Aslında buna güçlük demek yerine kompleks bir yapıya sahip demek daha doğru olacaktır. Eğer basit resim oluşturacaksanız PIL muhtemelen size fazla gelecektir. Bu gibi programcıların gd-modul'ü kullanması tavsiye edilir. gd-module'ün indirmek ve kullanımı ile ilgili detaylara ulaşmak için http://newcenturycomputers.net/projects/gdmodule.html adresini kullanabilirsiniz. Gd-module birkaç fonksiyondan başka bir şey sunmayan basit (fakat hızlı) resim oluşturma programıdır. Imaging ile arşivleme işlemleri yapabilirsiniz. Thumbnail oluşturabilir, resim biçimlerini birbirine çevirebilirsiniz. Postscript çıktı alabilir, PDF2 oluşturabilirsiniz. Bu rehber hazırlanırken çoğunlukla Python Imaging Library Handbook el kitabından yararlanılmıştır. Bu rehber hazırlanırken Fedora Core 6 ve üzerinde kurulu python-2.4.4-1.fc6 ve Image-1.1.5 kullanılmıştır. Rehberi okuyanın Python programlama dilinin temellerini bildiği ve resim biçimleri ile ilgili genel bilgiye sahip olduğu varsayılmıştır. 2 Her ne kadar PIL ile PDF oluşturabilseniz de, eğer amacınız Python altında PDF dokümanları oluşturmak ise, PIL yerine ReportLab (http://www.reportlab.org/rl_toolkit.html) geliştirilen kütüphaneyi kullanmalısınız. 2 © Mustafa Başer – 2007
  • 3.
    Imaging (PIL) NasılElde Edilir? 1.2 Imaging (PIL) Nasıl Elde Edilir? Imaging (PIL) hemen her Python dağıtımı ile birlikte ön tanımlı olarak gelir. Bu nedenle, Python'un doğal resim işleme kütüphanesi olarak tanımlanır. Python komut satırını açıp aşağıdaki komutu işleterek sisteminizde yüklü olup olmadığını anlayabilirsiniz: >>> import Image Eğer sisteminizde yüklü değilse http://www.pythonware.com/products/pil/ adresinden, sisteminize uygun sürümü indirip kurabilirsiniz. Image sürümünü öğrenmek Image modülündeki VERSION sabitine bakabilirsiniz: >>> Image.VERSION '1.1.5' Bu rehberde kullanılan sürüm 1.1.5 olduğundan, eski ya da yeni sürümlerinde birtakım değişikliklerin olması normaldir. © Mustafa Başer – 2007 3
  • 4.
    2 Rehber 2.1 Image Sınıfı PIL'in en önemli sınıfı Image 'dir. Image aynı isimli modüle içerisindedir. Image sınıfını kullanarak birçok resim işlemi yapabilir veya yeniden resim oluşturabilirsiniz. Daha önceden var olan bir resmi açmak için Image modülündeki open metodu kullanmalısınız: >>> import Image >>> res=Image.open("python-logo.gif") # http://www.python.org/images/python- logo.gif Eğer sonuç başarılı ise, metot Image nesnesini döndürecektir. Bu nesneye ait metotları kullanarak, resim üzerindeki işlemlerinizi yapabilirsiniz. Nesne içerisindeki metotları dir fonksiyonu ile görebilirsiniz. Örneğin resim biçimi, resim boyutu (piksel olarak) ve resim kipi görüntüleyelim: >>> print res.format, res.size, res.mode GIF (211, 71) P Burada görüldüğü gibi resim biçimimiz GIF, resmimizin boyu 211x71 (enxboy) piksel ve resim kipimiz P'dir. Resim kipi, resimdeki band sayısı ve resmi ile piksel ve derinlik bilgilerini içerir. Çok kullanılan resim kipleri; siyah-beyaz resimler için L, doğru renk resimler için RGB, ön baskı resimler için CMYK'dır. Resim nesnesini elde etmişseniz, resmi görüntülemek için show metodunu kullanabilirsiniz: >>> res.show() Bu metodu işlettiğinizde, sisteminizdeki ön tanımlı resim görüntüleyicisi içerisinde resminiz açılacaktır. 4 © Mustafa Başer – 2007
  • 5.
    Resimlerin Okunması veYazılması 2.2 Resimlerin Okunması ve Yazılması PIL birçok resim biçimini desteklemektedir. Bir resim dosyasını açmak için open metodunu kullanmalısınız. PIL'de resim dosyalarını açarken, resim biçimini bilmenize gerek yoktur, PIL otomatik olarak resim biçimi algılar ve döndürülen nesnedeki metotlar ona göre adapte edilir. PIL'de dosyaları kaydederken, açılan resim nesnesindeki save metodu kullanılır. Resimler kaydedilirken, resim biçimi belirtilmediği taktirde, resim uzantısına göre resmin hangi biçimde kaydedileceği saptanmaya çalışılır. PIL'de resim açma ve kaydetmeye örnek olarak, yukarıda açtığımız python- logo.gif resmini JPG olarak kaydedelim: >>> res.save("python-logo.jpg") Traceback (most recent call last): File "<stdin>", line 1, in ? File "/usr/lib/python2.4/site-packages/PIL/Image.py", line 1305, in save save_handler(self, fp, filename) File "/usr/lib/python2.4/site-packages/PIL/JpegImagePlugin.py", line 390, in _save raise IOError("cannot write mode %s as JPEG" % im.mode) IOError: cannot write mode P as JPEG Burada görüldüğü gibi P kipindeki bir resmin JPG olarak kaydedilemeyeceği belirtiliyor. O halde resim kipini JPG olarak kaydedebileceğimiz bir kipe dönüştürmemiz gerekir. RGB JPG için geçerli bir kiptir: >>> res.mode="RGB" Şimdi resmi kaydedebiliriz: >>> res.save("python-logo.jpg") Programımızın tamamı aşağıdaki gibi olacaktır: >>> import Image >>> res=Image.open("python-logo.gif") >>> res.mode="RGB" >>> res.save("python-logo.jpg") Web programcıları, resimleri yayımlarken çoğunluka onların ön izlemesini ziyaretçilere göstermek ister. Bu sayede ziyaretçi, ilgilendiği resmin büyüğünü görebilir. Bunun nedeni hem ziyaretçi hem de yayımcı için daha az veri transferinin sağlanmasıdır. Eğer var olan resimlerinizin orijinal boyutlarını koruyarak, ziyaretçiye daha küçük ön izleme (thumbnail) göndermek istiyorsanız, bunu PIL ile bir iki satırda yapabilirsiniz. http://lwn.net/ adresinden alınan birkaç penguen resimleri penguenler klasörüne kaydedildi. Şimdi bu resimlerin küçük ön izleme (thumbnail) resimlerini oluşturalım: #!/usr/bin/python import os import Image klasor='penguenler' kucukler='onizleme' if not os.path.exists(kucukler): os.mkdir(kucukler) © Mustafa Başer – 2007 5
  • 6.
    Resimlerin Okunması veYazılması for i in os.listdir(klasor): res=Image.open(klasor+'/'+i) res.thumbnail((100, 100)) res.save(kucukler+'/'+i) Eğer programınız bir web sayfasını yayımlayacaksa, o zaman bir CGI programı yazabilirsiniz. Bu program yeni oluşturulan küçük resimleri yeni bir klasöre yazmak yerine, doğrudan ekrana basmalıdır. “PIL ve CGI” bölümde, PIL ile oluşturulan resimlerin CGI ile nasıl yayımlanabileceğini öğreneceksiniz. 2.3 Kesme, Yapıştırma ve Resimlerin Birleştirilmesi Image sınıfı size resim alanları üzerinde işlem yapmanızı sağlayacak birçok araç içermektedir. Bir resimden, dikdörtgen şeklindeki bir alanı almak için crop metodunu kullanmalısınız. Aşağıdaki resimde yakışıklı bir penguenin boydan resmi var. tux-thinkpad.gif (tam boy) Bu resimden yakışıklı bir vesikalık resim yapmak istiyoruz, o halde penguenin sadece kafa kısmına ihtiyacımız var. Bunun için önce resmi açalım, bu resimden dikdörtgen bir alan kopyalayalım ve bunu kaydedelim: >>> res=Image.open("tux-thinkpad.gif") >>> kutu=(60,6,150,96) >>> alan=res.crop(kutu) >>> alan.save('yeni.gif') Kaydettiğimiz yeni.gif resmi aşağıdaki gibi olacaktır. © Mustafa Başer – 2007 6
  • 7.
    Kesme, Yapıştırma veResimlerin Birleştirilmesi yeni.gif (vesikalık) Bu programda yaptıklarımızı açıklayalım. Öncelikle resmimizi res nesnesi açtık. Daha sonra bir kutu tanımladık. Bu kutu, resimden kopyalayacağımız alanı belirlemektedir. Bu kutu şu şekilde tanımlanır: (X1, Y1, X2, Y2) Buradaki indisler şu şekildedir: X1: piksel olarak seçilecek alanın yatay başlangıç noktası X2: piksel olarak seçilecek alanın dikey başlangıç noktası Y1: piksel olarak seçilecek alanın yatay bitiş noktası Y2: piksel olarak seçilecek alanın dikey bitiş noktası Bun görsel olarak aşağıdaki şekilde olduğu gibi gösterebiliriz. (X1, Y1) (X2, Y2) res nesnesine atanan Orijinal resimden, kutu ile tanımlanan alanı alan nesnesine kopyalama için crop metodu kullanılmıştır. alan nesnesi yeni bir resim nesnesi, olduğundan herhangi bir resim üzerinde yapılabilecek tüm işlemler, yeni nesne için de geçerlidir. crop metodu tüp (ya da liste) şeklinde bir parametre alır. Bu tüp (Ya da liste) dört elemandan oluşmalıdır ve bunlar yukarıda belirtildiği gibi alanın başlangıç ve bitimini gösteren 4 sayı (integer) değer olmalıdır. Kopyaladığımız m 90x90 boyutundadır: >>> alan.size (90, 90) Herhangi bir resim nesnesinde saklı resmi istediğiniz bir açı ile döndürebilirsiniz. Döndürme işlemi rotate metodu ile yapılır. Örneğin vesikalık resmimizi tepe- taklak çevirelim: >>> ters=alan.rotate(180) >>> ters.save("ters-vesikalik.gif") ters-vesikalik.gif resmi aşağıdaki gibi olacaktır. © Mustafa Başer – 2007 7
  • 8.
    Kesme, Yapıştırma veResimlerin Birleştirilmesi ters-vesikalik.gif (180o döndürülmüş ) rotate metodu, bir resim nesnesini kendisine parametre olarak verilen açı (derece cinsinden) kadar döndürüp yeni bir resim nesnesi döndürür. Elbette ki bir resim nesnesini tersine döndürüp yine kendisine atayabilirsiniz: >>> alan=alan.rotate(180) Bu işlem, alan nesnesi içerisinde saklanan resmi 1800 döndürmüş olacaktır. Bir resim nesnesini, başka bir resim nesnesi üzerine yapıştırmak için paste metodu kullanılır. paste metodu iki parametre alır: birincisi, yapıştırılacak olan resim nesnesi, ikincisi resim nesnesinin yapıştırılacağı alanı belirleyen koordinat. Bu koordinat, yukarıda tanımlanan kutu şeklinde olmalıdır. Yapıştırılacak olan nesne'nin boyutu ile kutunun boyutu aynı olmalıdır. Tam boy penguen resminden vesikalık bir resim üretmiştik. Bu vesikalık resim penguen'in kafası idi. Daha sonra bu kafayı ters döndürdük. Şimdi bu kafayı aynı kutuyu kullanarak tam boy penguen resmine yapıştırırsak, penguenin kafasını tepe-taklak çevirmiş oluruz: >>> res.paste(alan, kutu) >>> res.save("ters-kafali-penguen.gif") ters-kafali-penguen.gif resmimiz aşağıdaki gibi olacaktır. ters-kafali-penguen.gif (ters kafalı penguen! ) © Mustafa Başer – 2007 8
  • 9.
    Kesme, Yapıştırma veResimlerin Birleştirilmesi PIL, çok bantlı resimlerde, bantlar üzerinde işlem yapmanızı, ya da bantları birleştirmenizi sağlayabilir. Çok bantlı bir resmin açıldığı resim nesnesinde, bantları ayırarak her birini bir resim nesnesine atamanızı sağlayacak olan metot split' dir. Aşağıdaki şekilde RGBA kipine sahip lsap_tux.png resmi görünmektedir. RGBA kipli lsap_tux.png Şimdi bu resmi bir nesneye açalım ve resmi bantlarına ayıralım: >>> res=Image.open("lsap_tux.png") >>> r,g,b,a=res.split() Eğer r, g, b, ve a'yı kaydedecek olursak aşağıdaki gibi resimler elde ederiz: r.save("r.png"); g.save("g.png"); b.save("b.png"); a.save("a.png") lsap_tux.png resminin sırası ile R, G, B ve A bantları Ayrışmış bantlar üzerinde çalıştıktan sonra bunları tekrar birleştirmek için merge metodunu kullanabilirsiniz. Yukarıda bantlarına ayrıştırdığımız resmi farklı bir sıra ile birleştirelim: >>> yeni=Image.merge("RGBA", (b, g, r, a)) >>> yeni.save("yeni.png") yeni.png resmimiz aşağıdaki gibi olacaktır. © Mustafa Başer – 2007 9
  • 10.
    Kesme, Yapıştırma veResimlerin Birleştirilmesi b,g,r,a sırası ile birleştirilmiş lsap_tux.png resmi 2.4 Geometrik Dönüşümler Image sınıfı, resimleri yeniden boyutlandırmak için reisize ve döndürme işlemi yapmak için rotate metodunu içerir. rotate metodu daha önce anlatılmıştı. Bu resmin boyutlarını iki katına çıkarmak için aşağıdaki işlemi yapabiliriz: >>> en,boy=yeni.size >>> ikiKat=yeni.resize((2*en,2*boy)) >>> ikiKat.save("ikiKat.png") Burada unutulmaması gereken resmin boyutunun iki katına çıkmış olmasıdır, bir resmin yanına (Ya da üstüne, altına) başka bir resim eklemek istiyorsanız, önce daha büyük tuvale sahip yeni bir resim oluşturmalı ve bu iki resmi bu tuvale yapıştırmalısınız. Örneğin tux-thinkpad.gif ve lsap_tux.png resimlerini yan yana yapıştırarak tek bir resim elde etmeye çalışalım. Öncelikle bu resimleri yeniden açalım: >>> res1=Image.open("tux-thinkpad.gif") >>> res2=Image.open("lsap_tux.png") Yeni tuvalimizin boyutunu bilmemiz gerekiyor. Resimleri yan yana yapıştıracağımıza göre, yeni tuvalin eni her iki resmin enleri toplamı kadar olmalıdır. O halde en'i şu şekilde hesaplayabiliriz: >>> en=res2.size[0]+res2.size[0] Şimdi boyunu belirleyelim. Yeni resmin boyu, büyük olan resmin boyu kadar olmalıdır. O halde önce kimin büyük olduğuna bakalım: >>> res1.size[1] 249 >>> res2.size[1] 120 Birinci resmin boyu daha büyük olduğuna göre, boy: >>> boy=res1.size[1] Şimdi yeni resmimizi oluşturalım: >>> res=Image.new("RGBA",(en,boy)) © Mustafa Başer – 2007 10
  • 11.
    Geometrik Dönüşümler Önce birinci resmimizi yapıştıralım. Bunun için yukarıda anlatılan kutu şekilde olmalıdır: >>> kutu1=(0,0,res1.size[0], res1.size[1]) >>> res.paste(res1, kutu1) Şimdi ikinci resmimizi yapıştırabiliriz. Bunun için belirleyeceğimiz kutunun X1 (yatay) başlangıç noktası, ilk resmin eninin bittiği yerdir. Y1 (dikey başlangıç noktası ise 0'dır. O halde: >>> X1=res1.size[0] >>> Y1=0 Resmin yatay bitiş noktası (X2), ilk resmin yatay bitişi ile ikinci resmin eninin toplamıdır. Dikey bitiş noktası (Y2) ise ikinci resmin enidir: >>> X2=res1.size[0]+res2.size[0] >>> Y2=res2.size[1] Şimdi ikinci resmi yapıştırabiliriz: >>> res.paste(res2, (X1,Y1,X2,Y2)) >>> res.save("ikili_penguen.png") ikili_penguen.png aşağıdaki gibidir. ikili_penguen.png (iki penguen yanyana) 2.5 Kip Dönüşümü Image nesnesinde kip dönüşümünü iki şekilde yapabilirsiniz. Ya resim nesnesine convert metodunu uygulayabilir veya, resim nesnesinin mode uzantısını istediğiniz kipe eşitleyebilirsiniz. Eğer var olan resminizin kipini değiştirecekseniz, mode uzantısını eşitleyin. Eğer var olan resim nesnesinin kipini değiştirip başka bir nesneye atayacaksanız convert metodunu kullanın. Daha iyi anlamak için şu örneğe bakalım: >>> ikiKat.mode © Mustafa Başer – 2007 11
  • 12.
    Kip Dönüşümü 'RGBA' >>> ikiKat.mode="L" >>> ikiKat.mode 'L' Burada resmimizin kipini değiştirdik. Aşağıdaki programda yeni kipte (siyah- beyaz) başka bir resim nesnesi elde ettik: >>> ikiKat=yeni.resize((2*en,2*boy)) >>> ikiKat.mode 'RGBA' >>> baska=ikiKat.convert("L") >>> baska.mode 'L' 2.6 Resim Artırma (Enhancement) PIL resim artırmak için birçok metot ve modüle sağlamaktadır. Bunları sırası ile inceleyelim. Filtreler ImageFilter modülü ön tanımlı birçok filtre içerir. Bu filtreler, resim nesnesini filter metodu kullanılarak uygulanır. Örneğin yukarıdaki penguene EMBOSS filtresini uygulayalım: >>> import ImageFilter >>> res=Image.open("lsap_tux.png") >>> embosRes=res.filter(ImageFilter.EMBOSS) >>> embosRes.save("lsap_tux_emboss.png") Resmimize bakacak olursak aşağıdaki şekilde olduğu gibi görünecektir. EMBOSS filtresi uygulanmış penguenimiz Diğer filtreler şunlardır: BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, FIND_EDGES, SHARPEN, SMOOTH, SMOOTH_MORE. Örneğin yukarıdaki resme FIND_EDGES filtresi uygularsak: >>> res.filter(ImageFilter.FIND_EDGES).save("kenarlar.png") kenarlar.png resmimiz aşağıdaki gibi olur. © Mustafa Başer – 2007 12
  • 13.
    Resim Artırma (Enhancement) Penguenin kenarları Artırma İleri resim artırma için, ImageEnhance modülü içerisindeki sınıfları kullanmanız gerekir. Bu sayede resminizde kontrast, parlaklık ve renk dengesini ayarlayabilirsiniz. Yukarıdaki resmimizin kontrastını değiştirelim: © Mustafa Başer – 2007 13
  • 14.
    3 ImageDraw Modülü Bir programlama dili altında resimlerle uğraşmanın belkide en temel nedeni, eldeki verileri grafikler halinse sunmaktır. Özellikle web programcılarının sıklıkla kullandığı bir yöntemdir. Eldeki veriyi grafik halinde sunmak için PIL yeteri kadar çizim fonksiyonu sunar. Bu fonksiyonlar ImageDraw modülü içerisindedir. Başlangıç örneği olarak, penguen (lsap_tux.png) resmimizin kenarından 5 pixel uzaklıkta bir dikdörtgen çizelim: >>> import Image, ImageDraw >>> res = Image.open("lsap_tux.png") >>> ciz = ImageDraw.Draw(res) >>> ciz.rectangle((5,5,res.size[0]-5, res.size[1]-5), outline="#ff0000") >>> del ciz >>> res.save("cerceveli.png") Çerçeveli penguen resmimiz aşağıdaki gibi olacaktır. Çerçeveli Penguen (cerceveli.png) Şimdi burada kullandığımız fonksiyon ve parametrelerine bir bakalım. Çizim işlemleri ile ilgili fonksiyonlar ImageDraw modulünde olduğundan ilk satırda Image ve ImageDraw modüllerini yükledik. Daha sonra resmimizi res nesnesine açtık. res nesnesinden çizim nesnemizi oluşturmak için ImageDraw.Draw (res) sınıfını kullandık. Artık resim üzerindeki tüm çizimler ciz nesnesi aracılığı ile yapılacaktır. Draw sınıfında bulunan rectangle metodu ile resmimizin etrafına bir çerçeve çizdik. Bu çerçeve, dıştan 5 piksel olacak şekildedir. rectangle ve diğer metotlarda kullanılan outline parametresi, çizimin rengini belirtir. Burada hexadecimal yazımını kullandık. Benzer şekilde rgb renklerini de kullanabilirdik. Örneğin kırmızı çerçeve çizmek için "rgb(100%,0%,0%)" yazımı da kullanılabilirdi. rectangle metodunun kullanımını aşağıda okuyabilirsiniz. Çiziminiz bitince ciz nesnesini hemen silmelisiniz, aksi halde hafızda boşuna yer kaplayacaktır. 14 © Mustafa Başer – 2007
  • 15.
    ImageDraw Metotları 3.1 ImageDraw Metotları rectangle ciz.rectangle(kutu, secenekler) Resim üzerine dikdörtgen çizmek için kullanılır. burada kutu tanımı sayfa 7'da verilmiştir. Seçenekler ise birçok ImageDraw metodunda kullanılan outline ve fill parametrelerini belirti. outline dikdörtgenin rengini, fill ise dikdörtgenin içerisinin hangi renk ile doldurulacağını gösterir. Renk tanımlarını hexadecimal veya RGB olarak verebilirsiniz. Aşağıda yeni bir resim oluşturup, bu resim üzerine çizilen dikdörtgenler görünmektedir. import Image, ImageDraw res = Image.new("RGB",(200,200), "#EFECE9") ciz = ImageDraw.Draw(res) ciz.rectangle((5,5,50,95), fill="rgb(70%,40%,10%)") ciz.rectangle((5,100,195,195), outline="#0000ff", fill="#aabbcc") ciz.rectangle((55,5,195,95), outline="#00ff00") del ciz res.save("diktortgenler.png") Bu program geri zemin üzerine aşağıdaki resimde görünen dikdörtgenleri oluşturacaktır. Çeşitli dikdörtgenler (diktortgenler.png) line ciz.line(kutu, secenekler) kutu (sayfa 7'daki tanıma bakınız) ile verilen dikdörtgenin sol üst köşesinden, sağ alt köşesine bir doğru çizer. Burada kutu tanımını şu şekilde de algılayabilirsiniz (x1,y1) çizginin başlangıç noktası, (x2,y2) çizginin bitiş noktası. Aşağıdaki program penguenin köşegenlerinden birer çizgi çekmektedir. >>> import Image, ImageDraw >>> res = Image.open("lsap_tux.png") >>> ciz = ImageDraw.Draw(res) © Mustafa Başer – 2007 15
  • 16.
    ImageDraw Metotları >>> ciz.line((0,0,res.size[0], res.size[1]), fill="#ff0000") >>> ciz.line((0,res.size[1], res.size[0], 0), fill="#00ff00") >>> del ciz >>> res.save("lsap_tux_carpi.png") Bu program kodu, lsap_tux.png resmini açacak ve köşegenlerinden kırmızı ve yeşil çizgi çizmiştir (aşağıdaki şekilde). Bu pengueni çizmişleri (lsap_tux_carpi.png) arc ciz.arc(kutu, baslamaAcisi, bitmeAcisi, secenekler) Verilen kutu (sayfa 7'daki tanıma bakınız) içerisinde başlangıç açısı baslamaAcisi ve bitiş açısı bitmeAcisi ile belirtilen bir yay çizer. Yay'ın seçenekleri fill olabilir. Bir yay kutu içerisine nasıl yerleşiyor bunu görmek için, önce arka planı sarı olan yeni bir resim tuvali oluşturalım, daha sonra bu tuval üzerine kutu ile verilen dikdörtgen çizelim ve içerisine aynı kutu ile verilen yarım çember çizelim. Yarım çember başlangıç açısı 0o ve bitiş açısı 180o olan yaydır. Aşağıdaki programı inceleyin: >>> import Image, ImageDraw >>> res = Image.new("RGB",(120,120), "#ffff00") >>> ciz = ImageDraw.Draw(res) >>> kutu=(10,10,110,110) >>> ciz.rectangle(kutu, outline="#0000ff") >>> ciz.arc(kutu, 0, 180, fill="#ff0000") >>> del ciz >>> res.save("yay.png") Bu program kodu aşağıdaki resmi üretecektir: © Mustafa Başer – 2007 16
  • 17.
    ImageDraw Metotları Yayın kutu içerisine yerleşmesi (yay.png) Burada görüldüğü gibi, çizilen yay eğer tam çember ise kutu ile belirtilen alan içerisine tam sığacak şekilde yay çizilmektedir. 0o saat 3 konumundan başlayıp, saat yönünde derece cinsinden ölçülmektedir. Şimdi bu öğrendiğimizi kullanarak bir hilal çizelim. Hilalimiz kırmızı zemin üzerine beyaz renkli olsun. Aşağıdaki program kodunu inceleyin: import Image, ImageDraw res = Image.new("RGB",(120,120), "#ff0000") ciz = ImageDraw.Draw(res) ciz.arc((10,10,110,110), 0,180, fill="#ffffff") ciz.arc((10,20,110,100), 0,180, fill="#ffffff") del ciz res.save("hilal.png") Bu program kodu aşağıda görünen hilali çizecektir. İki yayın kesişmesi ile ortaya çıkan hilal (hilal.png) chord ciz.chord(kutu, baslamaAcisi, bitmeAcisi, secenekler) arc (yay) ile aynıdır, ancak yayın başlama ve bitişi arasında bir çizgi çizer. Aşağıdaki örnekte, kutu içerisinde kirişin nasıl yerleştiğini görüyorsunuz: >>> import Image, ImageDraw >>> res = Image.new("RGB",(120,120), "#ff0000") >>> ciz = ImageDraw.Draw(res) >>> kutu = (10,10,110,110) >>> ciz.rectangle(kutu, outline="#0000ff") © Mustafa Başer – 2007 17
  • 18.
    ImageDraw Metotları >>> ciz.chord(kutu, 0,180, outline="#0000ff", fill="#ffffff") >>> del ciz >>> res.save("kiris.png") Yukarıdaki programın ürettiği resim aşağıdaki şekilde görülmektedir: Kutu içerisine kirişin yerleşmesi (kiris.png) Yukarıdaki hilal örneğimizde, hilalin içi beyaz olsun istiyorsak, ilkinin içi beyaz kiriş ikincisinin için kırmızı kiriş yapmamız gerekecektir: import Image, ImageDraw res = Image.new("RGB",(95,120), "#ff0000") ciz = ImageDraw.Draw(res) ciz.chord((10,10,85,110), 0,180, fill="#ffffff") ciz.chord((10,20,85,100), 0,180, fill="#ff0000") del ciz res.save("hilal.png") Bu program aşağıda görünen kırmızı zemin üzerinde beyaz hilalli oluşturacaktır: İçi beyaz hilal (hilal.png) Merkezine bir de yıldız kondurmamız gerekecek! ellipse ciz.ellipse(kutu, secenekler) Verilen kutu içerisine elips çizer. © Mustafa Başer – 2007 18
  • 19.
    ImageDraw Metotları pieslice ciz.pieslice(kutu, baslamaAcisi, bitmeAcisi, secenekler) acr (yay) ile aynıdır ancak yayın uçları ile merkez arasında bir çizgi çizer. Aşağıda basit bir örnek görünüyor: import Image, ImageDraw res = Image.new("RGB",(120,120), "#ff0000") ciz = ImageDraw.Draw(res) ciz.pieslice((10,10,110,110), 0,75, fill="#ffffff") del ciz res.save("dilim.png") Bu program aşağıdaki resmi üretecektir: İçi beyaz bir karpuz dilimi (dilim.png) Web üzerinden verileri pasta grafik olarak yansıtmak için sıkça kullanacağınız metot olacaktır. Örneğin 4 seçenekten oluşan bir anket hazırladık ve bu anketin sonuçları şu şekilde bulundu Seçenek Oy Sayısı A 80 B 49 C 32 D 76 Bu seçenekleri secenek listesinde aşağıdaki gibi tuttuğumuzu varlayalım: >>> secenek = [80, 49, 32, 76] Burada her bir seçeneği farklı bir renkteki karpuz dilimi olarak göstermemiz gerekir. Bir daire 360o'den oluştuğuna göre her oy sayısına karşılık gelen açıyı hesaplamalıyız. Bunun için: >>> secenek = [80, 49, 32, 76] >>> toplamOy=0 >>> for i in secenek: ... toplamOy += i ... >>> print toplamOy 237 © Mustafa Başer – 2007 19
  • 20.
    ImageDraw Metotları O halde toplam oy sayımız 237 dir. Şimdi oy oranlarına göre her bir dilim için açıyı bulalım: >>> secenekBasinaAci=[] >>> for i in secenek: ... secenekBasinaAci.append(int(round(360*(i/float(toplamOy))))) ... >>> print secenekBasinaAci [122, 74, 49, 115] Şimdi rastgele renk üreten bir fonksiyon yazalım: >>> import random >>> def rastgeleRenk(): >>> renk='#' >>> for i in range(6): >>> renk=renk+random.choice('0123456789abcdfe') >>> return renk Son olarak açılara denk gelen dilimleri resim üzerine çizmek gerekecek: >>> import Image, ImageDraw >>> res = Image.new("RGB",(120,120), "#cccccc") >>> ciz = ImageDraw.Draw(res) baslangic=0 bitis=0 for i in secenekBasinaAci: bitis=baslangic+i ciz.pieslice((10,10,110,110), baslangic,bitis, fill=rastgeleRenk()) baslangic=bitis del ciz res.save("pasta.png") Bunların hepsini bir program olarak yazarsak: #!/usr/bin/python import Image, ImageDraw, random secenek = [80, 49, 32, 76] toplamOy=0 for i in secenek: toplamOy += i secenekBasinaAci=[] for i in secenek: secenekBasinaAci.append(int(round(360*(i/float(toplamOy))))) def rastgeleRenk(): renk='#' for i in range(6): renk=renk+random.choice('0123456789abcdfe') return renk res = Image.new("RGB",(120,120), "#cccccc") ciz = ImageDraw.Draw(res) baslangic=0 bitis=0 for i in secenekBasinaAci: bitis=baslangic+i ciz.pieslice((10,10,110,110), baslangic,bitis, fill=rastgeleRenk()) baslangic=bitis del ciz res.save("pasta.png") © Mustafa Başer – 2007 20
  • 21.
    ImageDraw Metotları Bu programın ürettiği resim aşağıdaki gibi olacaktır (sizde pasta dilimleri farklı renkler olacaktır) Verileri pasta grafik olarak sunmak (pasta.png) © Mustafa Başer – 2007 21
  • 22.
    4 PIL veCGI Python'un web programcıları için içerdiği birçok araç, onun web programlamada vazgeçilmez bir dil olmasını sağlamaktadır. Şimdi PIL ile oluşturulan bir resmin web sayfasında nasıl Devam Edecek.... 22 © Mustafa Başer – 2007