IRCForumları - IRC ve mIRC Kullanıcılarının Buluşma Noktası
  sohbet

 Kayıt ol  Topluluk
Yeni Konu aç Cevapla
 
LinkBack Seçenekler Stil
Alt 13 Temmuz 2013, 22:00   #1
Çevrimdışı
Kullanıcıların profil bilgileri misafirlere kapatılmıştır.
IF Ticaret Sayısı: (0)
IF Ticaret Yüzdesi:(%)
Java Image Manipulation




Java Image Manipulation

İçerik
x Temel “Image” Bilgileri
-- Java’da Image
-- Loading Image
-- Graphics2D Kullanarak Image objesini çizdirme
-- Kendi Image objemizi oluşturmak ve kullanmak
-- Resim/Image Kaydetmek
Işe Yarar Image Işlemleri
x Şeffaflaştırma
-- Belirli bir rengi şeffaflaştırma
-- Resmi çevirmek
-- Resmi döndürmek
-- Resmi yeniden boyutlandırmak

Başlamadan önce, şunu söyleyeyim... Yazıyı bir yabancı siteden çeviri yapacaktım fakat, sitenin yetersiz olduğunu gördüm ve bazı kısımları hariç kendim değiştirip anlattım. Bu yüzden benzer kod parçalarını internette kolayca bulabilirsiniz.


Resimler grafik arayüzlü birçok programda kullanılıyor olmaları sebebiyle önemlidir. Bu resimleri kontrol etme ve işleme becerisi çok önemli bir beceridir ve herhangi bir grafik tasarımcı veya oyun tasarımcısı için olmazsa olmazlardandır. Bu yazı, hobisiyle uğraşan bir amatör de olsanız, profesyonel bir tasarımcı da olsanız, Java’da resimlerle uğraşmanız için gerekli temelleri vermeyi amaçlamaktadır. Yazının sonuna kadar uyguladığınızda, “küçük ama çok etkili”, resimlerle ilgili en yaygın birkaç işlemi yapabilen bir sınıfa sahip olacaksınız. jpg, .png, .gif, and bmp resim dosyaları üzerinde işlem yapabileceksiniz. Bu yazı sadece, Java’da temel bilgilere sahip olduğunuz düşünülerek yazılmıştır. (Tabii birazcık da resimlerle uğraşma tecrübeniz varsa yardımı olacaktır.) Bu yazıda tabii ki olabildiğince sizi matematiksel detaylarla uğraştırmayacağım. Yani, hadi başlayalım kodlamaya...

Java’da Image

Java’da Image sınıfı java.awt.image.Image adresindedir. Bu sınıf, temel resim kontrollerini sağlar. Yani iskelet diyebiliriz. Fakat asıl sistem, kan ve etler, java.awt.image.BufferedImage sınıfındadır. BufferedImage dediğimiz şey, bir resim verisinin erişilebilir ara belleğidir. (Aslına bakarsanız, piksellerin ve RGB renklerinin demek daha doğru olur.) Bu sınıf, resimler üzerinde çalışma adına çok güçlü bir yöntem sağlar. Bir BufferedImage, ColorModel ve Raster’dan oluşmuştur. Çok derinlemesine bilmek gerekmese de,
ColorModel objesi, resmin piksel verilerini renk parçalarına dönüştürecek metodları sağlar.
Raster ise, piksellerin dikdörtgenler dizilimini gösterir. Raster, resmin ham verisini tutan DataBuffer ve bu buffer’daki verinin nasıl organize edileceğini açıklayan SampleModel sınıflarından oluşur.

Temel bilgi olarak bunlar yeterli..

Image Yükleme(Loading Image)


Muhtemelen resimlerle ilgili en çok kullanılan işlem budur. Programa resim açma/yükleme (load kelimesinin tam karşılığı olarak ne kullanacağımı bilemedim :/ ) aslına bakarsanız yeterincebasit bir işlemdir ve bunu yapmanın birçok yöntemi vardır. Ben en basit olarak gördüğüm bir yöntemi sizinle paylaşacağım. bunun için, javax.imageio.ImageIO sınıfını kullanacağız.
Temel olarak, yapmak istediğimiz şey, bir resim dosyasındaki tüm veriyi load ederek, (Kusura bakmayın Türkçe’de buna karşılık kullanabileceğim bir kelime gelmiyor aklıma) , bunu bir BufferedImage objesine aktarmaktır ki bir daha sonra bunu gösterebilelim. Bunu ImageIO kullanarak şu şekilde yapabiliriz:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Burada, ilk olarak bir BufferedImage referansı oluşturuyoruz. Ardından bunu bir kaynak dosyadan okumayı deniyoruz. (Hata vermezse, ) elde ettiğimiz resmi return ediyoruz.
Ve tabii ki, siz bir resmi, en azından görüntülemiyorsanız, bir objeye yüklemek tam anlamıyla faydasızdır. Bu yüzden, şimdi size bu resmi nasıl çizdirebileceğimizi anlatmak lazım bir de...


Graphics2D Kullanarak Image Objesini Çizdirme



İşte tam olarak burası, eğlencenin yavaş yavaş başladığı yer. Bir resmi çizdirmek için, ilk önce onu çizebileceğimiz bir yüzeye ihtiyacımız vardır. Bunun için de AWT ve Swing kaynakları kullanmamız gerekiyor. Bununla alakalı daha geniş bilgi için, “Grafik Dersleri 1” konusuna bakınız. Daha da geniş bilgi için Java Documentation sayfalarını inceleyin. Swing içindeki her üst düzey container -JPanel, JFrame Canvas gibi- kendi Graphics objesine sahiptir. Bu Graphics objesi bize, kendi ata yüzeyine çizim yapmamıza izin verir. Örneğin page.drawLine(int x1,inty1,int x2,int y2); veya page.drawImage(Image img,int x,int y,ImageObserver ob); gibi...
Graphics2D objesi ise, Graphics objesinin güçlü bir alt sınıfıdır anlayacağınız üzere... BufferedImage çizimlerine izin veren daha fazla metod sağlar.
BufferedImage load edip ekrana çizdiren bir örnek inceleyelim:
Öncelikle şunu belirtmeliyim. Ben Eclipse kullanıyorum ve buradaki örnekleri denemeniz sırasında kullanmak üzere ŞU RESiMLERi indirip oluşturduğunuz projenin içine kaydetmenizi öneriyorum.



Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Not
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.
u şekilde normalde çalışıyor ama bazı durumlarda çalışmayabiliyor... Graphics nesnesine ulaşmaya çalıştığı anda o null olabiliyor.


Bu yöntemle çizdiğinizde, ekran boyutuyla oynadığınızda resmin yok olduğunu göreceksiniz.
Bunun önüne geçmek için, JPanel’in subclass’ı olan bir başka class yapıp; bunu,resmi ne durumda olursa olsun ekrana çizdirecek bir hale getirmemiz lazım. Bunun için de [RED}paintComponent(Graphics g); metodunu override etmemiz lazım. Bu class için aşağıya doğru devam edin.
Bir parça kod daha ekliyorum. Ben böyle kullanmayı tercih ediyorum genellikle.


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu Main birkaç şeyi açıklamakta fayda var... Bu class’taki loadImage metodunu çağırmadım. O, ImageApp class’ındaki yöntem için orada duruyordu. Bu class’ın sadece main metoduna baksanız yeterli bu yöntem için...


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Burada da şunu söylemekte fayda var. size ayarlarken +20 dedim, çizdirirken de (10,10) koordinatından başlattım ki pencerenin tam ortasına yerleştireyim resmi...


Not: bu metod için Graphics2D kullanmamıza gerek yoktu.. Onun yerine direkt olarak “g” üzerine çizim de yapabilirdik.
Fakat bu sefer metodumuz:
g.drawImage(image,10,10,null);
şeklinde olacaktı. (Evet bu iki class’ta drawImage parametre sistemi farklı...
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.



Bu değişiklik sonuç olarak bize bir dünya farklılık oluşturuyor. Yeniden boyutlandırma,buffering, vs. gibi arkaplan işlemlerinde olay kendi içinde halledilecek. Biz de ilerlemeye devam edelim bu sırada...


Kendi Image objemizi oluşturmak ve kullanmak


Bunu yapmanın da yeterince kolay birkaç yöntemi var. En bariz yöntem haliyle,
BufferedImage bi=new BufferedImage(320, 240,BufferedImage.TYPE_3BYTE_BGR);
şeklinde oluştururuz.
Fakat bunun üzerinde bir çizim yapabilmek için bunun Graphics objesini oluşturmamız gerekir.
BufferedImage bi=new BufferedImage(320, 240,BufferedImage.TYPE_3BYTE_BGR);
bi.createGraphics();

Şimdi üzerine çizim yapabileceğimiz nur topu gibi bir yüzeyimiz oldu. Hayırlı olsun.
Not:createGraphics metodu Graphics2D objesi return eder ve sizin bunu bir şeye eşitlemeniz gerekir. sadece bunu yapıp bırakamazsınız.


Şimdi sizinle basit bir çizim yapalım.


Ya da bir dakika... Once şu ImagePanel class’ını biraz daha genişkapsamlı/genelgeçer hale getirelim.


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Kısaca söylemek gerekirse, bu class, BufferedImage objesi, 2 tane de sayı alır. ve bunu (x,y) itibariyle çizdirir.


Şimdi basit çizimimizi yapabiliriz.
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.



Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu örnek basit olarak Graphics2D üzerine nasıl çizim yapabileceğimizi gösteriyor. İsterseniz g.drawString, drawOval vs. metodları kullanarak farklı şeyler tecrübe edebilirsiniz.


Resim/Image Kaydetmek


Bu da daha önce bahsettiğimiz çoğu şey gibi yeterince basit bir metod... Temel olarak, yapılacak tek şey, RAM’deki resim verisinin dosyaya yazılması.. Aşağıdaki kodda bunun JPG ve PNG için yapılışı var. Java henüz Sun’a aitken eklenen ImageIO, bize büyük kolaylık sağlıyor.
ImageIO.write(RenderedImage ri,String format,File output);


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu metodu da Main class’ımıza ekledim.


Resmi Şeffaflaştırma

Bazen bir resmi veya onun bir kısmını geçirgen/şeffaf yapmamız gerekebilir. Photoshop, Gimp veya bunlara benzer bir resim düzenleme programı kullandıysanız, resmin “alpha” değerini değiştirme veya resme alpha katmanı uygulamanın bu işi yaptığını tahmin edebilirsiniz. Burada da tam olarak bunun nasl yapıldığını göreceğiz.


Her resmin bir parçası olan Graphics2D objesi ve JFrame gibi container’lar bizim, bunların nasıl çizileceğine karışmamıza izin verir. Temel olarak, setComposite(Composite comp), setStroke(Stroke stroke) and setPaint(Paint paint) vs. hepsi bizim Graphics2D objemizin çizimini etkiler. Composite bizim bu başlıkta yapmak istediğimiz işlem olan şeffaflık ayarlama gibi şeyleri etkilemeye yarar. Genellikle sadece resmin AlphaComposite’i ile ilgilenilir onu çizdirdiğimiz panele bulaşmamıza gerek yok. Main class’ımıza bu metodu da ekleyelim (tabii ki resim üzerinde uygulayıp ekleyelim, tüm container’ı etkilemeye gerek yok). Örnek kod parçası:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu kod parçası, once resmi alır, sonra resmi şeffaflaştırma işlemi için hazır hale getirilmiş yeni BufferedImage objesini oluşturur ve bunun Graphics2D objesini alarak belirlenen şeffaflık değerini AlphaComposite ile uygular. Ardından resmi çizer. Son olarak, kullanılan kaynakları serbest bırakır ve bitirir. AlphaComposite içinde kullanılan değer, 0.0 ile 1.0 arasında herhangi bir şey olabilir. (Not: Hatırlayınız, yazdığınız bir ondalık sayının float olarak alınmasını istiyorsanız, sayının sonuna “f” harfi eklemelisiniz.)
Main metodumuzun içindeki her şeyi silip yerine bunları yazabilirsiniz:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Outputumuz:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Belirli Bir Rengi Şeffaflaştırma

Birçok resim düzenleme programında olan işe yarar bir özellik de, belirli bir rengi şeffaf hale getirebilme özelliğidir. Buna maske (mask) uygulamak deniliyor. Bunu GIMP programı, tüm pikselleri teker teker test edip, belirli renkteki piksellerin RGB değerini sıfırlayıp alpha değerini de 0.0’a eşitleyerek yaptığını biliyorum. Bunu Java’da yapmak için:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu kısım, resmi aldıktan sonra, yeni bir renk tipinde (ARGB/ RGBA) bir hedef obje oluşturur. Sonraki kısım da asıl işi yapacak olan kısım.


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu, hedefin Graphics2D objesini alır, Composite değerini Alpha’ya çevirir. Resmi çizer ve Graphics2D objesini sistemden temizler. Sonra, resimdeki tüm pikselleri gezerek, rengi kontrol eder. Eğer renkler aynıysa, bunu alpha RGB değeriyle değiştiriyoruz. Son olarak, maske uygulanmış hedef resmi return ediyoruz.


Bunu uygulayıp ImagePanel ile gösterdiğimizde çıkan output:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Fark ettiğiniz üzere burada gayet güzel çalışıyor programımız. Bir de şunda deneyelim:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Eveeeeet... Gördüğünüz üzere, beyazın bir kısmını silemedi.. Siyahın daha büyük bir kısmını silemedi... Bunun sebebi, seçtiğimiz rengi biz siyah olarak görsek de, saygıdeğer programımız kendilerini farklı görüyor.
Bunun için de, işin içine threshold denilen bir kavram giriyor. Yani, manuel olarak, belirli miktardaki farkı yok saymasını sağlayacağız.


Bu kısım biraz karmaşık görünüyor fakat temel olarak yaptığım şey, rengi R, Gve B olarak ayırıp, hepsini bir threshold ile kontrol ediyorum. buna Photoshop’ta “tolerance” diyor hatırlayanlar olur...
kod parçasını paylaşıyorum:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.



Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bu kısmı biraz aceleye geldi.. Bunu çoğu kişi zaten okumayacağı için birisi hakkında soru sorana kadar açıklama ihtiyacı duymuyorum. Açıklanması gereken yerler, gelen soruya göre daha anlaşılır olacak...
Bir de sonuç paylaşayım:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bununla alakalı çok konuştum.. Diğer kısımlara geçeyim.


Resmi Çevirmek/Ters Yüz Etmek


Bir resmi ters yüz etmek, bir eksene göre ayna görüntüsünü almak demektir.
bunu yapmak için Graphics2D’nin daha çok parametre alan bir metodunu kullanacağız.
drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer);
parametreleri sırasıyla, çizim yapılacak hedef dikdörtgenin sol üst köşe, sağ alt köşe koordinatları ve kaynağın sol-üst ve sağ-alt köşeleri... Biz kaynağın köşelerinde sağ-üst ve sol-alt verirsek, bunu tersyüz etmiş oluruz. Aynı şekilde diğer ikisini de değiştirerek farklı bir eksene göre ters yüz etmiş oluruz:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.



Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Resmi Döndürmek

Normalde resmi döndürme işlemi, trigonometrik hesaplar ve image processing bilgisi gerektiren karmaşık sayılabilecek bir olaydır. Java’da sağlanan bir metod sayesinde biz bunu kolaylıkla yapıyoruz. Kod parçası:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


burada verdiğimiz w/2 ve h/2 değerleri referans noktası oluyor. yani 0,0 derseniz, bir kağıdın sol üst köşesini bir parmağınızla tutup bir köşesinden tutup çevirdiğinizde elde edeceğiniz şekil oluyor.
Örnek resimler vereyim. 45 derece çevrilmiş hal. Tabii ki renklerde bir miktar bozulmalar oldu. Resmin formatına bağlı olarak bunları yaşamazsınız. “kirby.jpg” ile deneyin.


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Resmi Yeniden Boyutlandırmak


Bunu yapmak için değişik yöntemler var. Ben bunu kullanmıyorum genelde fakat siz bunu bilin.
Olayın bütün matematiksel kısmını yine Graphics2D hallediyor. Fakat yine de işin içine çoğumuzun daha önce duymamış olduğu bir sınıf giriyor. “RenderingHints”. Bununla alakalı açıklama yapamayacağım çünkü ben de bilmiyorum
Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.



Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Output diyelim:


Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.

Bu forumdaki linkleri ve resimleri görebilmek için en az 25 mesajınız olması gerekir.


Bunu kullanmanızı önerme sebebim hızlı ve sistemli oluşu..
Bir de şöyle bir şey varmış:
Image.getScaledInstance(int newWidth, int newHeight, int renderHints)


fakat bunun yavaş olduğunu söylüyorlar.. [Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]

Unutmadan ekleyeyim:
[Üye Olmadan Linkleri Göremezsiniz. Üye Olmak için TIKLAYIN...]

Alıntı

 
Alıntı ile Cevapla

IRCForumlari.NET Reklamlar
sohbet odaları reklam ver Benimmekan Mobil Sohbet
Cevapla

Etiketler
image, java, manipulation


Konuyu Toplam 1 Üye okuyor. (0 Kayıtlı üye ve 1 Misafir)
 

Yetkileriniz
Konu Acma Yetkiniz Yok
Cevap Yazma Yetkiniz Yok
Eklenti Yükleme Yetkiniz Yok
Mesajınızı Değiştirme Yetkiniz Yok

BB code is Açık
Smileler Açık
[IMG] Kodları Açık
HTML-Kodu Kapalı
Trackbacks are Kapalı
Pingbacks are Açık
Refbacks are Açık


Benzer Konular
Konu Konuyu Başlatan Forum Cevaplar Son Mesaj
JRE (Java Runtime Engine - Java Çalışma Zamanı Motoru) toXic Java 2 18 Aralık 2011 13:40
Sorun söyleyeyim (Java,JSP,ASP.NET(C#),PL/SQL,jQuery,Java Script,Ajax) J2EE123 Java 2 03 Kasım 2011 12:57
JRE (Java Runtime Engine - Java Çalışma Zamanı Motoru) Stealth Java 1 29 Eylül 2010 22:19