Advertisement
  1. Code
  2. PHP

تغییر ساده ابعاد عکس با استفاده از PHP

Scroll to top
Read Time: 13 min

() translation by (you can also view the original English article)

همیشه به یک روشِ همه منظوره که بتوانید به راحتی عکس هایتان را در PHP تغییر سایز دهید، نیاز داشته اید ؟ بسیار خب، کلاس های PHP برای استفاده مجدد از کدهایی که کار های اصلی را برای ما انجام می دهند، به وجود آمده اند. در این مقاله میخواهیم یاد بگیریم که چطور کلاسِ php خودمان را با ساختاری مناسب و قابل ارتقا بسازیم. تغییر سایز عکس کار آسانی است. اما چقدر آسان؟ در سه گام !


مقدمه

برای آشنایی شما با ویژگی های کلاسی که قصد ساختن آن را داریم، نگاهی مختصر به ویژگی های آن می اندازیم :

  • آسان برای استفاده
  • مستقل از فرمت. I.E., open, resize ، و داری توانایی ذخیره با فرمت های مختلفِ عکس.
  • اندازه گیری هوشمند - بدون تحریف تصویری !

توجه داشته باشید که این مقاله آموزش چگونگیه ساخت کلاس ها و شی ها نیست، البته داشتن آن مهارت ها به شما کمک خواهد کرد ولی برای دنبال کردنِ این آموزش داشتن آن مهارت ها ضروری نیست.

بیاید شروع کنیم.


گام اول : آماده سازی

کارمان را آسان شروع میکنیم. دو فایل در پوشه کاریتان بسازید: یکی به نامِ index.php، و دیگری به نامِ resize-class.php .


گام دوم : صدا زدن شی

برای این که به شما نشان دهیم که به چه چیزی قرار است برسیم، ما ابتدا صدا زننده ها را برای تغییر ابعاد عکس کد نویسی میکنیم. فایل index.php را باز کنید و کد زیر را اضافه کنید.

همانطور که می بینید، منطق خوبی برای آنچه که ما انجام می دهیم وجود دارد. ما فایل تصویر را باز می کنیم، ابعادی را که می خواهیم  تصویر را به آن تغییر اندازه دهیم، تعیین میکنیم و نوع تغییر اندازه را تنظیم کنیم.
سپس تصویر را ذخیره می کنیم،  فرمت تصویری که می خواهیم و کیفیت تصویر را انتخاب می کنیم. فایل index.php خود را ذخیره و سپس میبندیم.

1
2
  	// *** Include the class

3
		include("resize-class.php");
4
5
		// *** 1) Initialize / load image

6
		$resizeObj = new resize('sample.jpg');
7
8
		// *** 2) Resize image (options: exact, portrait, landscape, auto, crop)

9
		$resizeObj -> resizeImage(150, 100, 'crop');
10
11
		// *** 3) Save image

12
		$resizeObj -> saveImage('sample-resized.gif', 100);

از کد بالا می توانید ببینید که ما یک فایل JPG را باز کرده ایم اما یک GIF را ذخیره کردیم. به خاطر داشته باشید، این همان انعطاف پذیری است.


گام سوم : کلاسِ Skeleton

این برنامه نویسیِ شیء گرا (OOP) است که باعث می شود احساس راحتی امکان کنید. مانند یک الگوی به کلاس فکر کنید شما می توانید داده ها را محصور ( encapsulate  ) کنید - اصطلاح دیگر، اصطلاحی که واقعا فقط به معنی پنهان کردن داده ها است. سپس می توانیم  بدون نیاز به بازنویسی، این کلاس را در هر جایی که نیاز به تغییر اندازه داریم، دوباره استفاده کنیم. فقط نیاز به متد مناسب برای صدا زدن داریم. هنگامی که الگوی مان را ساختیم، نمونه هایی از این الگو را، به نام اشیاء ( objects ) ایجاد می کنیم.

"تابع construct ، که به عنوان یک سازنده شناخته می شود، و زمانی که یک شی از کلاس ساخته میشود، این تابع صدا زده میشود."

بیایید با ساختن کلاس resize شروع کنیم. فایل resize-class.php را باز کنید. در زیر یک کلاسِ structure skeleton داریم که من اونو "resize" نامگذاری کرده ام. به قسمتِ کامنت شده توجه داشته باشید؛ این قسمت جایی است که ما بعدا میخواهیم class variable هایمان را اضافه کنیم.

تابع construct، به عنوان یک سازنده شناخته می شود، یک متد خاص از کلاس  است (اصطلاح "method" همان function است، با این حال، هنگام صحبت کردن در مورد کلاس ها و اشیاء، اغلب method استفاده می شود) که زمانی که یک شی از کلاس ساخته میشود، این method صدا زده میشود. این کار برای مقدار دهیه اولیه که ما قصد داریم در مرحله بعد انجام دهیم، مناسب است.

1
2
		Class resize
3
		{
4
			// *** Class variables

5
6
			public function __construct()
7
			{
8
9
			}
10
		}

توجه داشته باشید که برای ساخت تابع سازنده از دو __  ( underscore )  پشت سرهم استفاده میشود


گام چهارم سازنده

ما قصد داریم متدِ سازنده بالا را تغییر دهیم. در ابتدا، نام فایل (و مسیر) تصویر مان را تغییر می دهیم. ما این متغیر را fileName$ می نامیم.

ما باید فایل PHP GD Library را باز کنیم تا PHP بتواند تصویر را بخواند. ما این کار را با متدِ شخصیِ 'openImage' انجام می دهیم. I'll get to how this method
به زودی قرار است کار کند، اما در حال حاضر ما باید نتیجه را به عنوان یک class variable ذخیره کنیم. یک class variable فقط یک متغیر است - اما برای آن کلاس خاص است. class variable که قبلا ذکر کردم را به یاد می آورید؟ با نوشتن 'private $image' متغییر image را به صورت private تعریف میکنیم. با تنظیم متغیر به صورت «private»، دامنه آن متغیر را تنظیم می کنید تا فقط توسط کلاس قابل دسترسی باشد. از حالا به بعد می توانیم به تصویر باز شده ای که به عنوان یک منبع شناخته می شود، را صدا بزنیم.

بیاید ارتفاع و عرض تصویر را ذخیره کنیم. من احساس می کنم بعدا مفید خواهد بود.

اکنون باید موارد زیر را داشته باشید.

1
2
		Class resize
3
		{
4
			// *** Class variables

5
			private $image;
6
			private $width;
7
			private $height;
8
9
			function __construct($fileName)
10
			{
11
			    // *** Open up the file

12
			    $this->image = $this->openImage($fileName);
13
14
			    // *** Get width and height

15
			    $this->width  = imagesx($this->image);
16
			    $this->height = imagesy($this->image);
17
			}
18
		}

متدهای imagesx و imagesy در توابعی که بخشی از کتابخانه GD هستند ساخته شده است. آنها به ترتیب عرض و ارتفاع تصویر شما را بازیابی می کنند.


مرحله پنجم باز کردن تصویر

در مرحله قبل ما متد سفارشیِ openImage را فراخوانی کردیم. در این مرحله ما این متد را ایجاد می کنیم. ما میخواهیم اسکریپت این کار را برای ما انجام دهد، بنابراین بسته به اینکه کدام نوع فایل در حال انتقال است، اسکریپت باید تعیین کند که کدام کتابخانه GD خواستار باز کردن تصویر است. این کار به راحتی با مقایسه فرمت فایل ها با دستور switch به دست می آید.

ما می خواهیم آن فایل را تغییر اندازه داده و بازگردانیم.

1
2
		private function openImage($file)
3
		{
4
		    // *** Get extension

5
		    $extension = strtolower(strrchr($file, '.'));
6
7
		    switch($extension)
8
		    {
9
		        case '.jpg':
10
		        case '.jpeg':
11
		            $img = @imagecreatefromjpeg($file);
12
		            break;
13
		        case '.gif':
14
		            $img = @imagecreatefromgif($file);
15
		            break;
16
		        case '.png':
17
		            $img = @imagecreatefrompng($file);
18
		            break;
19
		        default:
20
		            $img = false;
21
		            break;
22
		    }
23
		    return $img;
24
		}

مرحله ششم نحوه تغییر اندازه

این جایی است که عشق اتفاق می افتد. این مرحله واقعا فقط توضیحی است که ما میخواهیم انجام دهیم - بنابراین هیچ مشکلی در اینجا وجود ندارد. در مرحله بعد، ما قصد داریم یک متدِ عمومی ایجاد کنیم که برای انجام تغییرات مان آن را به کار خواهیم گرفت؛ بنابراین این امر در مورد عرض و ارتفاع، و نیز اطلاعاتی درباره اینکه چگونه می خواهیم تغییر اندازه تصویر را انجام دهیم، منطقی است. بگذارید یک لحظه در مورد این صحبت کنیم. زمانی وجود خواهد داشت که در آن شما می خواهید تصویرتان را به اندازه دقیقی تغییر سایز دهید. عالی است، بگذارید این مورد را در نظر بگیریم. اما زمان هایی نیز وجود دارد که شما مجبور به تغییر اندازه صدها تصویر که هر یک از آن تصاویر دارای نسبت و ابعاد مختلف است، هستید - مانند تصاویر پرتره. تغییر اندازه آنها به اندازه دقیق باعث تحریفِ شدید خواهد شد. اگر ما گزینه های مان را برای جلوگیری از تحریف در نظر بگیریم، می توانیم:

  1. تغییر اندازه تصویر تا نزدیکترین حالت به ابعاد تصویر واقعی، در حالی که نسبت ابعاد حفظ شود.
  2. تغییر اندازه تصویر به همان اندازه که می توانیم به ابعاد تصویر جدیدمان برسیم و باقیمانده را از تصویر جدا کنیم.

هر دو گزینه، با توجه به نیازهای شما قابل اجرا هستند.

Yep. ما قصد داریم به همه موارد فوق رسیدگی کنیم. به طور خلاصه : 

  1. تغییر اندازه با عرض / ارتفاع دقیق . (دقیق)
  2. تغییر اندازه با عرض - عرض دقیق تنظیم خواهد شد، ارتفاع با توجه به نسبت ابعاد تنظیم می شود. (landscape)
  3. تغییر اندازه در ارتفاع - مانند روش Resize by Width، اما ارتفاع آن را تنظیم  میکنیم و عرض به صورت پویا تنظیم می شود. (portrait)
  4. تعیین خودکارِ گزینه 2 و 3. اگر پوشه ای با عکس های مختلف دارید، اجازه دهید اسکریپت به صورت خودکار نحوه اداره کردن این موضوع را تعیین کند. (خودکار)
  5. تغییر اندازه دهید، سپس crop کنید. این مورد علاقه من است. اندازه دقیق، بدون تحریف عکس. (crop)

مرحله هفتم : تغییر اندازه. بیایید این کار را انجام دهیم!

دو بخش برای متدِ resize وجود دارد. برای شروع، با ایجاد برخی از متدهای سفارشی، عرض و ارتفاع مطلوب برای تصویر جدید مان را میگیریم و همانطور که در بالا توضیح داده شد option مان را بهش پاس میدهیم . عرض و ارتفاع به صورت آرایه بازمی گردند و به متغیرهای مربوطه تنظیم می شوند. احساس خوبی برای "'pass as reference" کردن، منتقل می شود، اما من طرفدار آن نیستم.

بخش دوم این است که تغییر اندازه واقعی را انجام می دهد. به منظور حفظ اندازه این آموزش، به شما اجازه می دهم تا در مورد توابع GD در لینک های زیر اطلاعات کسب کنید:

ما همچنین خروجی متد imagecreatetruecolor (یک تصویر رنگی واقعی) را به عنوان یک class variable ذخیره می کنیم.  متغییر 'private $ imageResized؛' را به متغیرهای کلاس دیگرتان اضافه کنید.

تغییر اندازه توسط یک ماژول PHP شناخته شده به عنوان کتابخانه GD انجام می شود. بسیاری از متد های استفاده شده توسط این کتابخانه ارائه شده است.

1
2
		// *** Add to class variables

3
		private $imageResized;
1
2
		public function resizeImage($newWidth, $newHeight, $option="auto")
3
		{
4
5
			// *** Get optimal width and height - based on $option

6
			$optionArray = $this->getDimensions($newWidth, $newHeight, strtolower($option));
7
8
			$optimalWidth  = $optionArray['optimalWidth'];
9
			$optimalHeight = $optionArray['optimalHeight'];
10
11
			// *** Resample - create image canvas of x, y size

12
			$this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
13
			imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
14
15
			// *** if option is 'crop', then crop too

16
			if ($option == 'crop') {
17
				$this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight);
18
			}
19
		}

گام هشتم : درخت تصمیم گیری

کار بیشتر شما در حال حاضر، باعث کار کمتر شما در زمان تغییر اندازه میشود. این متد مسیر را انتخاب می کند، با هدف به دست آوردن عرض و ارتفاع تغییر اندازه بهینه. این متد مناسب ما است که ما در مرحله بعدی آن را ایجاد خواهیم کرد.

1
2
		private function getDimensions($newWidth, $newHeight, $option)
3
		{
4
5
		   switch ($option)
6
		    {
7
		        case 'exact':
8
		            $optimalWidth = $newWidth;
9
		            $optimalHeight= $newHeight;
10
		            break;
11
		        case 'portrait':
12
		            $optimalWidth = $this->getSizeByFixedHeight($newHeight);
13
		            $optimalHeight= $newHeight;
14
		            break;
15
		        case 'landscape':
16
		            $optimalWidth = $newWidth;
17
		            $optimalHeight= $this->getSizeByFixedWidth($newWidth);
18
		            break;
19
		        case 'auto':
20
		            $optionArray = $this->getSizeByAuto($newWidth, $newHeight);
21
					$optimalWidth = $optionArray['optimalWidth'];
22
					$optimalHeight = $optionArray['optimalHeight'];
23
		            break;
24
				case 'crop':
25
		            $optionArray = $this->getOptimalCrop($newWidth, $newHeight);
26
					$optimalWidth = $optionArray['optimalWidth'];
27
					$optimalHeight = $optionArray['optimalHeight'];
28
		            break;
29
		    }
30
			return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
31
		}

گام نهم : Optimal Dimensions

ما قبلا در مورد کاری که این چهار متد انجام میدهند، بحث کرده ایم. آنها فقط ریاضی پایه هستند.

1
2
		private function getSizeByFixedHeight($newHeight)
3
		{
4
		    $ratio = $this->width / $this->height;
5
		    $newWidth = $newHeight * $ratio;
6
		    return $newWidth;
7
		}
8
9
		private function getSizeByFixedWidth($newWidth)
10
		{
11
		    $ratio = $this->height / $this->width;
12
		    $newHeight = $newWidth * $ratio;
13
		    return $newHeight;
14
		}
15
16
		private function getSizeByAuto($newWidth, $newHeight)
17
		{
18
		    if ($this->height < $this->width)
19
		    // *** Image to be resized is wider (landscape)

20
		    {
21
		        $optimalWidth = $newWidth;
22
		        $optimalHeight= $this->getSizeByFixedWidth($newWidth);
23
		    }
24
		    elseif ($this->height > $this->width)
25
		    // *** Image to be resized is taller (portrait)

26
		    {
27
		        $optimalWidth = $this->getSizeByFixedHeight($newHeight);
28
		        $optimalHeight= $newHeight;
29
		    }
30
			else
31
		    // *** Image to be resizerd is a square

32
		    {
33
				if ($newHeight < $newWidth) {
34
					$optimalWidth = $newWidth;
35
					$optimalHeight= $this->getSizeByFixedWidth($newWidth);
36
				} else if ($newHeight > $newWidth) {
37
					$optimalWidth = $this->getSizeByFixedHeight($newHeight);
38
				    $optimalHeight= $newHeight;
39
				} else {
40
					// *** Sqaure being resized to a square

41
					$optimalWidth = $newWidth;
42
					$optimalHeight= $newHeight;
43
				}
44
		    }
45
46
			return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
47
		}
48
49
		private function getOptimalCrop($newWidth, $newHeight)
50
		{
51
52
			$heightRatio = $this->height / $newHeight;
53
			$widthRatio  = $this->width /  $newWidth;
54
55
			if ($heightRatio < $widthRatio) {
56
				$optimalRatio = $heightRatio;
57
			} else {
58
				$optimalRatio = $widthRatio;
59
			}
60
61
			$optimalHeight = $this->height / $optimalRatio;
62
			$optimalWidth  = $this->width  / $optimalRatio;
63
64
			return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
65
		}

مرحله دهم : بُرش

اگر crop را انتخاب کردید، سپس یک گام کوچکتر دارید. ما قصد داریم تصویر را از
وسط برش دهیم. Cropping یک فرایند بسیار مشابه برای تغییر اندازه عکس است، اما با چند پارامتر بزرگتر.

1
2
		private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
3
		{
4
			// *** Find center - this will be used for the crop

5
			$cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
6
			$cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
7
8
			$crop = $this->imageResized;
9
			//imagedestroy($this->imageResized);

10
11
			// *** Now crop from center to exact requested size

12
			$this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
13
			imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
14
		}

Step 11 Save the Image

کار ما تقریبا تمام شده است. اکنون زمان ذخیره تصویر است. اگر کیفیت تصویر را از 0-100 در نظر بگیریم، ​​100 بهترین کیفت است. چندین مورد قابل توجه درباره کیفیت تصویر: JPG از مقیاس 0-100 استفاده می کند، 100 بهترین را داراست. تصاویر با فرمت GIF قسمت تنظیمات کیفیت تصویر ندارند. PNG هم دارد، اما از مقیاس 0 تا 9 استفاده می کنند، و 0 بهترین کیفیت است. این خوب نیست زیرا ما نمی توانیم انتظار داشته باشیم هربار که بخواهیم یک تصویر را ذخیره کنیم، این مورد را به یاد داشته باشیم. ما کمی جادو می کنیم تا همه چیز را استاندارد کنیم.

1
2
		public function saveImage($savePath, $imageQuality="100")
3
		{
4
			// *** Get extension

5
        	$extension = strrchr($savePath, '.');
6
        	$extension = strtolower($extension);
7
8
			switch($extension)
9
			{
10
				case '.jpg':
11
				case '.jpeg':
12
					if (imagetypes() & IMG_JPG) {
13
						imagejpeg($this->imageResized, $savePath, $imageQuality);
14
					}
15
		            break;
16
17
				case '.gif':
18
					if (imagetypes() & IMG_GIF) {
19
						imagegif($this->imageResized, $savePath);
20
					}
21
					break;
22
23
				case '.png':
24
					// *** Scale quality from 0-100 to 0-9

25
					$scaleQuality = round(($imageQuality/100) * 9);
26
27
					// *** Invert quality setting as 0 is best, not 9

28
					$invertScaleQuality = 9 - $scaleQuality;
29
30
					if (imagetypes() & IMG_PNG) {
31
						imagepng($this->imageResized, $savePath, $invertScaleQuality);
32
					}
33
					break;
34
35
				// ... etc

36
37
				default:
38
					// *** No extension - No save.

39
					break;
40
			}
41
42
			imagedestroy($this->imageResized);
43
		}

اکنون زمان خوبی برای از بین بردن منابع تصویرمان، برای آزاد کردن حافظه است. اگر شما از این آموزش در زمان تولید استفاده می کنید، گرفتن و برگرداندن عکس ذخیره شده، میتواند ایده جالبی باشد.


نتیجه گیری

Well that's it, folks. با تشکر از شما برای دنبال کردن این آموزش، امیدوارم مفید واقع شود. از فیدبک های شما که میتوانید با استفاده از قسمت نظرات زیر برایم بفرستید، سپاسگزارم.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.