تغییر اندازه عکس در PHP یا لاراول

?>

اگر یک سرچی در گوگل زده باشید انواع روش های تغییر ابعاد عکس با php یا لاراول وجود دارد.اما من اینجا میخوام یک روش کامل و مستقل برای تغییر اندازه عکس در PHP را آموزش بدهم.

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

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

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

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

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

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

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

// *** Include the class
    include("resize-class.php");
 
    // *** 1) Initialize / load image
    $resizeObj = new resize('sample.jpg');
 
    // *** 2) Resize image (options: exact, portrait, landscape, auto, crop)
    $resizeObj -> resizeImage(150, 100, 'crop');
 
    // *** 3) Save image
    $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 صدا زده میشود. این کار برای مقدار دهیه اولیه که ما قصد داریم در مرحله بعد انجام دهیم، مناسب است.

Class resize
{
    // *** Class variables
 
    public function __construct()
    {
 
    }
}

توجه داشته باشید که برای ساخت تابع سازنده از دو __  ( 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»، دامنه آن متغیر را تنظیم می کنید تا فقط توسط کلاس قابل دسترسی باشد. از حالا به بعد می توانیم به تصویر باز شده ای که به عنوان یک منبع شناخته می شود، را صدا بزنیم.

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

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

Class resize
{
    // *** Class variables
    private $image;
    private $width;
    private $height;
 
    function __construct($fileName)
    {
        // *** Open up the file
        $this->image = $this->openImage($fileName);
 
        // *** Get width and height
        $this->width  = imagesx($this->image);
        $this->height = imagesy($this->image);
    }
}

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

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

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

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

private function openImage($file)
{
    // *** Get extension
    $extension = strtolower(strrchr($file, '.'));
 
    switch($extension)
    {
        case '.jpg':
        case '.jpeg':
            $img = @imagecreatefromjpeg($file);
            break;
        case '.gif':
            $img = @imagecreatefromgif($file);
            break;
        case '.png':
            $img = @imagecreatefrompng($file);
            break;
        default:
            $img = false;
            break;
    }
    return $img;
}

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

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

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

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

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

  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 انجام می شود. بسیاری از متد های استفاده شده توسط این کتابخانه ارائه شده است.

// *** Add to class variables
private $imageResized;
public function resizeImage($newWidth, $newHeight, $option="auto")
{
 
    // *** Get optimal width and height - based on $option
    $optionArray = $this->getDimensions($newWidth, $newHeight, strtolower($option));
 
    $optimalWidth  = $optionArray['optimalWidth'];
    $optimalHeight = $optionArray['optimalHeight'];
 
    // *** Resample - create image canvas of x, y size
    $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
    imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
 
    // *** if option is 'crop', then crop too
    if ($option == 'crop') {
        $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight);
    }
}

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

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

private function getDimensions($newWidth, $newHeight, $option)
{
 
   switch ($option)
    {
        case 'exact':
            $optimalWidth = $newWidth;
            $optimalHeight= $newHeight;
            break;
        case 'portrait':
            $optimalWidth = $this->getSizeByFixedHeight($newHeight);
            $optimalHeight= $newHeight;
            break;
        case 'landscape':
            $optimalWidth = $newWidth;
            $optimalHeight= $this->getSizeByFixedWidth($newWidth);
            break;
        case 'auto':
            $optionArray = $this->getSizeByAuto($newWidth, $newHeight);
            $optimalWidth = $optionArray['optimalWidth'];
            $optimalHeight = $optionArray['optimalHeight'];
            break;
        case 'crop':
            $optionArray = $this->getOptimalCrop($newWidth, $newHeight);
            $optimalWidth = $optionArray['optimalWidth'];
            $optimalHeight = $optionArray['optimalHeight'];
            break;
    }
    return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
}

گام نهم : Optimal Dimensions

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

private function getSizeByFixedHeight($newHeight)
{
    $ratio = $this->width / $this->height;
    $newWidth = $newHeight * $ratio;
    return $newWidth;
}
 
private function getSizeByFixedWidth($newWidth)
{
    $ratio = $this->height / $this->width;
    $newHeight = $newWidth * $ratio;
    return $newHeight;
}
 
private function getSizeByAuto($newWidth, $newHeight)
{
    if ($this->height < $this->width)
    // *** Image to be resized is wider (landscape)
    {
        $optimalWidth = $newWidth;
        $optimalHeight= $this->getSizeByFixedWidth($newWidth);
    }
    elseif ($this->height > $this->width)
    // *** Image to be resized is taller (portrait)
    {
        $optimalWidth = $this->getSizeByFixedHeight($newHeight);
        $optimalHeight= $newHeight;
    }
    else
    // *** Image to be resizerd is a square
    {
        if ($newHeight < $newWidth) {
            $optimalWidth = $newWidth;
            $optimalHeight= $this->getSizeByFixedWidth($newWidth);
        } else if ($newHeight > $newWidth) {
            $optimalWidth = $this->getSizeByFixedHeight($newHeight);
            $optimalHeight= $newHeight;
        } else {
            // *** Sqaure being resized to a square
            $optimalWidth = $newWidth;
            $optimalHeight= $newHeight;
        }
    }
 
    return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
}
 
private function getOptimalCrop($newWidth, $newHeight)
{
 
    $heightRatio = $this->height / $newHeight;
    $widthRatio  = $this->width /  $newWidth;
 
    if ($heightRatio < $widthRatio) {
        $optimalRatio = $heightRatio;
    } else {
        $optimalRatio = $widthRatio;
    }
 
    $optimalHeight = $this->height / $optimalRatio;
    $optimalWidth  = $this->width  / $optimalRatio;
 
    return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
}

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

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

private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
{
    // *** Find center - this will be used for the crop
    $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
    $cropStartY = ( $optimalHeight/ 2) - ( $newHeight/2 );
 
    $crop = $this->imageResized;
    //imagedestroy($this->imageResized);
 
    // *** Now crop from center to exact requested size
    $this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
    imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
}

مرحله یازدهم: ذخیره عکس

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

public function saveImage($savePath, $imageQuality="100")
{
    // *** Get extension
    $extension = strrchr($savePath, '.');
    $extension = strtolower($extension);
 
    switch($extension)
    {
        case '.jpg':
        case '.jpeg':
            if (imagetypes() & IMG_JPG) {
                imagejpeg($this->imageResized, $savePath, $imageQuality);
            }
            break;
 
        case '.gif':
            if (imagetypes() & IMG_GIF) {
                imagegif($this->imageResized, $savePath);
            }
            break;
 
        case '.png':
            // *** Scale quality from 0-100 to 0-9
            $scaleQuality = round(($imageQuality/100) * 9);
 
            // *** Invert quality setting as 0 is best, not 9
            $invertScaleQuality = 9 - $scaleQuality;
 
            if (imagetypes() & IMG_PNG) {
                imagepng($this->imageResized, $savePath, $invertScaleQuality);
            }
            break;
 
        // ... etc
 
        default:
            // *** No extension - No save.
            break;
    }
 
    imagedestroy($this->imageResized);
}

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

امیدوارم از این آموزش لذت برده باشید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *