PHP ile otomatik thumbnail oluşturun

Sniper tarafından 27 Ağustos 2009 tarihinde yazıldı.

Bugüne kadar hazırladığım web siteleri çoğunlukla katalog tarzı ürün tanıtım siteleriydi. Bu sitelerde bir ürünün farklı ebatlarda resimlerini sitenin çeşitli yerlerinde kullanmam gerekiyordu. Zamanında buna çare olarak bir script hazırlamıştım. Script, kendisine parametre olarak gönderilen resmin istenilen boyutlarda bir küçük kopyasını çalışma anında oluşturuyor ve tarayıcıya gönderiyordu. Böylelikle hem disk alanından kâr ediyor, hem de her boyut için manuel olarak tüm resimlerin thumbnailini oluşturma zahmetinden kurtuluyordum.

Bu scripti, ASP yazdığım zamanlarda ASPJpeg bileşeni kullanarak geliştirmiştim. PHP’ye geçince aynı işi yapan PHP kodlarını da hazırladım ama bu kodlar ASP’deki kadar hızlı çalışmıyordu. Resimlerin görüntülenmesinde gözle görülür bir yavaşlama söz konusuydu ama gerek zamansızlık, gerekse PHP alanında tecrübesiz olmamdan dolayı bu konunun üstünde fazla durmamıştım. Son birkaç gündür bu scriptle ilgilenme fırsatım oldu ve nasıl daha az kaynak tüketerek scripti daha verimli hale getirebilirim diye düşündüm. Madem her resmin thumbnail’i oluşturulup tarayıcıya gönderiliyor, neden bunları bir dosyaya kaydetmeyeyim? Hem bir sonraki çağırılışlarında direkt oluşturduğum dosyayı çağırırım ve işlemciyi yormam, hem de her resmin istediğim ebatlardaki thumbnaillerini elimi sürmeden oluşturmuş olurum.

Scriptin adı thumb.php, dışarıdan 3 parametre alıyor:

  • p: Üzerinde işlem yapılacak olan resmin dosya sistemi üzerindeki tam yolu. Scriptin esprisini kaybetmemesi açısından yeniden boyutlandırılacak resmin bulunduğu klasörün yazma izinleri ayarlanmış olmalıdır.
  • w: Resmin dönüştürüleceği maximum genişlik. (Kötü amaçlı kullanımlardan korunmak amacıyla 1024px ile sınırlandırılmıştır.)
  • h: Resmin dönüştürüleceği maximum yükseklik. (Kötü amaçlı kullanımlardan korunmak amacıyla 768px ile sınırlandırılmıştır.)

w ve h parametreleri opsiyonel olup istenirse her ikisinin de kullanılacağı gibi sadece biri de kullanılabilir. Hiçbirini kullanmamak resmi doğrudan çağırmakla eşdeğer olacağından bir anlam ifade etmez. Scriptin çalışma mantığı özetle şöyle:

  • Resmin genişlik ve yükseklik parametreleri alınır, yukarıda bahsedilen sınırlandırma uygulanır.
  • p parametresinde belirtilen resim dosyasının varlığı doğrulanır.
  • Resim için bir thumbnail dosya adı oluşturulur. Bu dosya adı; orjinal resmin adı[_w[genişlik değeri_hyükseklik değeri]].uzantı formatındadır. (Örneğin: “thumb.php?p=sniper.jpg&w=100&h=75″ olarak çağırılan dosyanın thumbnail adı “sniper_w100_h75.jpg” olacaktır.)
  • Ortaya çıkan thumbnail dosya adı kullanılarak daha önce bu isimde bir dosya oluşturulmuşsa script o dosyaya yönlenir ve çalışmayı durdurur.
  • Resim dosyası belirtilen özelliklerle ilk defa çağırılıyorsa istenilen genişlik ve yükseklik değerleri işlenip orantılı bir şekilde küçük resim oluşturulur.
  • Resmin bulunduğu klasörün yazma izinleri ayarlanmışsa oluşturulan küçük resim klasöre kaydedilir, script kaydedilen dosyaya yönlendirilir ve çalışmayı durdurur.
  • Eğer klasörün yazma izni yoksa oluşturulan thumbnail direkt olarak tarayıcıya gönderilir ve dosyanın sonraki çağırılışlarında tüm bu işlemler tekrar eder.

Son olarak birkaç örnek kullanım ve bu kullanımlar sonucunda oluşacak dosya bilgilerini verdikten sonra kodları alabilirsiniz. Örnek kodlar 1280×960 px boyutlarında bir resim üzerinde çalıştırılmıştır.

<img src="thumb.php?p=urunler/wall1.jpg&h=200" />

Dosya Adı: wall1_h200.jpg
Genişlik: 267px
Yükseklik: 200px
Kodun çalışan halini görmek için tıklayın


<img src="thumb.php?p=urunler/wall1.jpg&w=200" />

Dosya Adı: wall1_w200.jpg
Genişlik: 200px
Yükseklik: 150px
Kodun çalışan halini görmek için tıklayın


<img src="thumb.php?p=urunler/wall1.jpg&w=200&h=200" />

Dosya Adı: wall1_w200_h200.jpg
Genişlik: 200px
Yükseklik: 200px
Kodun çalışan halini görmek için tıklayın


thumb.php

< ?php
/**
 * 	Dosya			= thumb.php
 *	Yazan			= Tuncay KINALI (a.k.a. Sniper)
 *	Görevi			= Parametre olarak verilen resmi istenilen boyutlarda küçültme, büyütme ve
 *			  		  orantılı olarak resmin içinden bir bölümü gösterme. Oluşturulan son resim
 *					  dosyasını yeniden isimlendirerek kaydetme. Sonraki çağırılışında bu isimde
 *					  dosya bulunduğu takdirde direkt olarak o dosyayı gösterme.
 *	Parametreler	= "p": Üzerinde oynanacak resmin yolu
 *					  "w": Resmin maximum genişliği (opsiyonel)
 *					  "h": Resmin maximum yüksekliği (opsiyonel)
 *	Tarih			= 11.08.2007
 * 	Son Güncelleme 	= 27.08.2009 - 21:11
 */
 
error_reporting(0);
 
// Gösterilecek resmin yolu.
$p = $_GET['p'];
 
// Resmin istenilen genişliği.
// Olası kötü amaçlı kullanımlara karşı maximum genişliği 1024px olarak ayarlıyoruz.
$w = intval($_GET['w']) > 1024 ? 1024 : intval($_GET['w']);
 
// Resmin istenilen yüksekliği
// Olası kötü amaçlı kullanımlara karşı maximum yüksekliği 768px olarak ayarlıyoruz
$h = intval($_GET['h']) > 768 ? 768 : intval($_GET['h']);
 
// Belirtilen resim dosya sisteminde varsa...
if(file_exists($p)) {
	// Dosya adını ve uzantısını ayrı ayrı al.
	$dosyaAdi 	= substr($p, 0, strrpos($p, '.'));
	$uzanti 	= substr($p, strrpos($p, '.'));
 
	// Thumbnail dosya adını öğren
	/**
	 * Thumbnail dosya adı, scriptin sonraki çalışmasında kontrol edeceği
	 * içinde istenilen genişliğin ve yüksekliğin belirtildiği isimdir.
	 * Örneğin thumb.php?p=resim.jpg&w=100&h=75 şeklinde çalıştırılan script
	 * için thumbnail dosya adı "resim_100_75.jpg" olarak belirlenecektir.
	 */
	$thumbFileName = $dosyaAdi;
	$thumbFileName .= $w>0 ? '_w'.$w : '';
	$thumbFileName .= $h>0 ? '_h'.$h : '';
	$thumbFileName .= $uzanti;
 
	// İstenilen ölçülerde thumbnail daha önce talep edilmiş ve dosya sistemine kaydedilmişse...
	if(file_exists($thumbFileName)) { // ... thumbnail dosyasına yönlen ve çalışmayı durdur.
		header("Location: {$thumbFileName}");
		exit;
	} else { // ... ilk defa talep edilen thumbnail dosyası için çalışmaya başla
 
		// Resmin bilgilerini al
		$resim = getimagesize($p);
 
		if($w && !$h) { // Max. Genişlik manuel olarak belirtilmiş ve yükseklik belirtilmemişse...
			// ... genişliği istenilen ölçüye getir ...
			$genislik = $w;
			// ... yüksekliği genişliğe orantılı bir şekilde hesapla.
			$yukseklik = round(($genislik*$resim[1])/$resim[0]);
		} elseif(!$w && $h) { // Max. Yükseklik manuel olarak belirtilmişse ve genişlik belirtilmemişse
			// ... yüksekliği istenilen ölçüye getir ...
			$yukseklik = $h;
			// ... genişliği yüksekliğe orantılı bir şekilde hesapla.
			$genislik = round(($yukseklik*$resim[0])/$resim[1]);
		} elseif($w && $h) { // Her iki özellikte manuel olarak belirtilmişse ...
			// ... özellikleri istenilen ölçüye getir.
			$yukseklik = $h;
			$genislik = $w;
		} else { // Her iki ölçü de girilmemişse ana resme git ve çalışmayı durdur.
			header('Location: '. $p);
			exit;
		}
 
		// Resmin türüne göre ana resmi belleğe kopyala
		switch($resim[2]) {
			case 1: // GIF
				$kopya_resim = imagecreatefromgif($p);
				$resim_mime_type = 'image/gif';
				break;
			case 2: // JPG
				$kopya_resim = imagecreatefromjpeg($p);
				$resim_mime_type = 'image/jpeg';
				break;
			case 3: // PNG
				$kopya_resim = imagecreatefrompng($p);
				$resim_mime_type = 'image/png';
				break;
		}
 
		// Belirlenen ölçülerde boş bir resim oluştur
		$thumb = imagecreatetruecolor($genislik, $yukseklik);
		// Belleğe kopyalanan ana resmi istenilen ölçülere göre küçülterek oluşturulan resmi
		// az önce oluşturduğumuz boş resmin içine yazdır.
		imagecopyresampled($thumb, $kopya_resim, 0, 0, 0, 0, $genislik, $yukseklik, $resim[0], $resim[1]);
 
		if($h) {
			/**
			 * Eğer maximum yükseklik değeri manuel olarak girilmişse ve bu değer
			 * scriptin oluşturduğu değerden farklıysa scriptin otomatik değeri yoksayılıp
			 * elle girilen değer dikkate alınarak thumbnail yeniden boyutlandırılır
			 */
 
			if($yukseklik>$h) $yukseklik = $h;
 
			$thumb2 = imagecreatetruecolor($genislik, $yukseklik);
 
			imagecopy($thumb2, $thumb, 0, 0, 0, (($h-$yukseklik)/2), $genislik, $yukseklik);
			$sonuc = $thumb2;
		} else {
			$sonuc = $thumb;
		}
 
		/** İstenilen boyuttaki thumbnail artık hazır
		 * Resmin türüne göre oluşturulan thumbnaili dosya sistemine yazdırmayı deneyeceğiz.
		 * Resmin bulunduğu klasörün yazma izinleri verilmişse thumbnail dosyası yukarıda
		 * ayarlanan isimle klasöre kaydedilir ve script kaydedilen bu dosyaya yönlendikten sonra
		 * çalışmayı durdurur. Yazma izinlerinde sorun varsa -ki bu scriptin esprisini yok eder-
		 * oluşturulan thumbnail'i direkt olarak browser'a yollar ve her seferinde yukarıdaki işlemleri yapar
		 */
 
		switch($resim[2]) {
			case 1: // GIF
				if(@imagegif($sonuc,$thumbFileName)) {
					header('Location: '.$thumbFileName);
					exit;
				} else {
					header("Content-Type: {$resim_mime_type}");
					imagegif($sonuc);
				}
				break;
			case 2: // JPG
				if(@imagejpeg($sonuc,$thumbFileName,80)) {
					header('Location: '.$thumbFileName);
					exit;
				} else {
					header("Content-Type: {$resim_mime_type}");
					imagejpeg($sonuc,NULL,80);
				}
				break;
			case 3: // PNG
				if(@imagepng($sonuc,$thumbFileName)) {
					header('Location: '.$thumbFileName);
					exit;
				} else {
					header("Content-Type: {$resim_mime_type}");
					imagepng($sonuc);
				}
				break;
		}
 
		// Tüm işlemler bittikten sonra bellek boşaltılıp bir nebze olsun sunucu rahatlatılır
		imagedestroy($sonuc);
	}
}
?>

31 kişi bunu beğendi.

Etiketler:

“PHP ile otomatik thumbnail oluşturun” yazısına 12 yorum yapılmış

  1. Ali ÇAM

    Merhaba, otomatik thumbnail kodunuzu denedim fakat bir sorunum var. ben klasör içerisindeki resimlerimi sıralıyorum. sıralarken de sizin kodunuzu kullanarak otomatik thumbnail dosyasını yaratayım dedim fakat her seferinde bir kopyasını oluşturdu. bu sorunu çözemedim. yardım ederseniz sevinirim.

  2. Kodun özelliği zaten thumbnail olarak farklı bir dosya oluşturması, amaç bu yani. Sizin tam olarak yapmak istediğinizi ben anlayamadım.

  3. Ali ÇAM

    Aslında ben anlatamadım.

    < ?php
     
    $imgdir = 'uploads/resimler/';
    $allowed_types = array('png','jpg','jpeg','gif');
    $dimg = opendir($imgdir);
    while($imgfile = readdir($dimg))
    {
    if(in_array(strtolower(substr($imgfile,-3)),$allowed_types))
    {
    $a_img[] = $imgfile;
    sort($a_img);
    reset ($a_img);
    }
    }
     
    $totimg = count($a_img);
     
    for($x=0; $x
    <a href="uploads/dekorlar/? rel=?example1? style=?text-decoration:none;? rel="nofollow"><img src="thumb.php?p=uploads/dekorlar/&w=120&h=90? border=?0? width=?120? height=?90? />

    kodlar yukarıdaki gibi. sayfayı her çalıştırdığımda bir küçük resim daha oluşuyor döngüden dolayı. bunu nasıl halledebiliriz. yardım ederseniz sevinirim.

  4. Ali ÇAM

    Aslında ben anlatamadım. Ben bir klasörün içerisindeki resimleri döngüyle ekrana getiriyorum. sayfaya çağırırken thumb.php dosyanızı kullanıyorum. fakat döngüden dolayı sayfayı her çalıştırdığımda yeni bir küçük resim daha oluşuyor. bunu nasıl halledebiliriz acaba. yardım ederseniz sevinirim. isterseniz mail adresinize kodları gönderebilirim.

  5. Dosya oluşmasını engellemek için ya o dizinin yazma iznini kaldırmalısın ya da kodda küçük bir değişikliğe gitmelisin. Değiştirmen gereken yer en alttaki “swicth($resim[2])” ile başlayan bölüm. Burayı kodlarla değiştirirsen yeni dosya oluşturmadan direkt olarak çıktıyı browser’a gönderir:

    switch($resim[2]) {
    case 1: // GIF
    	header("Content-Type: {$resim_mime_type}");
    	imagegif($sonuc);				
    	break;
    case 2: // JPG
    	header("Content-Type: {$resim_mime_type}");
    	imagejpeg($sonuc,NULL,80);
    	break;
    case 3: // PNG
    	header("Content-Type: {$resim_mime_type}");
    	imagepng($sonuc);
    	break;
    }
  6. Teşekkürler Tuncay, çok güzel bir çalışma.. Herkesin kullanabileceği bir dille anlattığından dolayı çok sağol.

  7. tam aradığım gibi bişey fakat ttp://localhost/thumb.php?p=sniper.jpg&w=132&h=74 olarak kullanınca normak olarak 132×74 olarak küçültüyor, burası tamam.

    fakat şöyle kullanınca resmi alıp küçültmüyor, curl falan mı gerekiyor acaba (phpden anlamam valla) ?
    tam olarak istediğim verdiğim resim adresini çeksin belirlediğim klasöre kaydetsin, olmaz mı :$
    ttp://localhost/thumb.php?p=http://siteismi.com/sniper.jpg&w=132&h=74

    yine de teşekkür ederim.

  8. Script bu haliyle istediğinizi gerçekleştiremez. İstediğiniz şey bu scriptin dışında birşey.

  9. [...] [...]

  10. Peki ya bunu bi upload uygulamasında kullanmak istersek nasıl yapmamız lazım? resmi upload ederken aynı zamanda thumb’ını alsın? get ile verileri veririz de önemli olan bu dosyayı tarayıcıda belli etmeden çalıştırmak?

  11. Upload işlemi bittikten sonra sayfaya echo ile bir <img /> etiketi bastırıp bunun src özelliğinde de thumb.php’yi çağırabilirsin. Resmin görünmesini istemiyorsan boyutlarını küçültebilir ya da display:none ile gizleyebilirsin.

    Bunlar olmaz diyorsan geriye tek bir seçenek kalıyor. Thumb.php dosyasının içeriğini bir fonksiyona atayıp gerekli yerleri değiştirerek istediğin resmin thumbnail’ını alabilirsin.

  12. Hocam çok işime yaradı. Heleki tekrar üretmeyip var olanı kullanması…

    Çalışmalarında başarılar.

    Not : Hakkında sayfasını zevkle okudum.

Yorum Ekle