اذهب إلى المحتوى

معالجة الصور مع مكتبة GD ومكتبة Imagick في PHP


سارة محمد2

خرج الصورة

يمكن إنشاء صورة باستخدام دوال image*‎ حيث * هي صيغة الملف، وهذه الدوال لها الصيغة المشتركة التالية:

bool image___(resource $im [, mixed $to [ other parameters]] )

الحفظ إلى ملف

يمكنك تمرير اسم الملف أو مجرى ملف مفتوح للمتغير ‎$to إذا كنت تريد حفظ الصورة إلى ملف، إذا مررت مجرى فلا تحتاج لإغلاقه لأنّ مكتبة GD تغلقه تلقائيًا، مثلًا لحفظ ملف PNG:

imagepng($image, "/path/to/target/file.png"); 

$stream = fopen("phar://path/to/target.phar/file.png", "wb"); 
imagepng($image2, $stream);
// لا حاجة لإغلاق المجرى

تأكد عند استخدام fopen من أنك تستخدم الراية b وليس الراية t لأن الملف هو خرج ثنائي، ولا تحاول أن تمرر fopen("php://temp", $f)‎ أو fopen("php://memory", $f)‎ لأنّ الدالة تُغلق المجرى بعد الاستدعاء ولن تبقى قادرًا على استدعائه أو استخدامه لاسترداد محتوياته مثلًا.

الخرج كرد HTTP

لا تحتاج إلى تمرير شيء (أو مرر null) كوسيط ثانٍ إذا كنت تريد أن ترجع هذه الصورة مباشرةً كرد للصورة (لإنشاء بطاقات ديناميكية مثلًا)، لكنك تحتاج إلى تحديد نوع المحتوى في رد HTTP:

header("Content-Type: $mimeType");

‎$mimeType هو نوع الصياغة المُرجعة في الترويسة MIME مثل image/png وimage/gif وimage/jpeg.

الكتابة إلى متغير

يوجد طريقتين للكتابة إلى متغير:

  • استخدام المخزن المؤقت للخرج (OB):
ob_start(); 
// ‫تمرير null للكتابة افتراضيًا في مجرى الخرج القياسي
imagepng($image, null, $quality); 
$binary = ob_get_clean();
  • استخدام مغلِّف المجرى:

قد يكون لديك سبب ما لعدم استخدام المخزن المؤقت للخرج كأن يكون لديك بالفعل مخزن مؤقت قيد التشغيل لذا تحتاج إلى بديل، يمكنك تسجيل مغلَّف مجرى جديد باستخدام الدالة stream_wrapper_register لذا يمكنك تمرير مجرى إلى دالة إظهار الصورة واستعادته لاحقًا.

<?php
class GlobalStream{
    private $var;

    public function stream_open(string $path){
        this->var =& $GLOBALS[parse_url($path)["host"]];
        return true;
    }

    public function stream_write(string $data){
        $this->var .= $data;
        return strlen($data);
    }
}

stream_wrapper_register("global", GlobalStream::class);

$image = imagecreatetruecolor(100, 100);
imagefill($image, 0, 0, imagecolorallocate($image, 0, 0, 0));

$stream = fopen("global://myImage", "");
imagepng($image, $stream);
echo base64_encode($myImage);

في هذا المثال يكتب الصنف GlobalStream أي دخل إلى المتغير المرجعي (أي الكتابة بشكل غير مباشر إلى المتغير العام للاسم المعطى)، يمكن استرجاع المتغير العام لاحقًا بشكلٍ مباشر.

يجب الانتباه إلى عدة أمور:

  • صنف مغلِّف المجرى المنفَّذ بشكلٍ كامل يجب أن يشبه هذا الصنف لكن وفقًا للاختبارات باستخدام تابع ‎__call السحري فإنّه من الممكن استدعاء stream_open وstream_write وstream_close فقط من الدوال الداخلية.
  • لا توجد رايات مطلوبة في استدعاء fopen لكن يجب أن تمرر سلسلة فارغة على الأقل، لأنّ الدالة fopen تتوقع مثل هذا المعامل، حتى لو لم تستخدمها في تنفيذ stream_open يبقى هذا المعامل مطلوبًا.
  • تستدعى الدالة stream_write عدة مرات وفقًا للاختبارات، تذكر أن تستخدم إسناد الدمج ‎.=‎ وليس إسناد المتغير المباشر =.

مثال: في وسم <img> في HTML، يمكن توفير صورة بشكلٍ مباشر بدلًا من استخدام رابط خارجي:

echo '<img src="data:image/png;base64,' . base64_encode($binary) . '">';

إنشاء صورة

نستخدم الدالة imagecreatetruecolor لإنشاء صورة فارغة:

$img = imagecreatetruecolor($width, $height);

المتغير ‎$img‎ هو متغير مورد الآن بعرض ‎$width وطول ‎$height بكسل، لاحظ أنّ العرض يُحسب من اليسار إلى اليمين والطول من الأعلى إلى الأسفل.

يمكن أن يُنشأ أيضًا مورد الصورة من دوال إنشاء الصورة مثل imagecreatefrompng وimagecreatefromjpeg ودوال imagecreatefrom*‎ أخرى.

قد تُحرَّر موارد الصورة لاحقًا عندما لا توجد مراجع إليها، لكن لتحرير الذاكرة بشكلٍ مباشر (قد يكون هذا مهمًا عند معالجة عدة صور كبيرة) يمكننا استخدام imagedestroy()‎ على الصورة عندما لا تبقى حاجة لاستخدامها وتكون هذه ممارسة جيدة.

imagedestroy($image);

تحويل صورة

إنّ الصور التي تُنشأ من تحويل الصور لا تعدّل الصورة حتى تُخرجها، لذا يمكن أن يكون محوِّل الصورة ببساطة عبارة عن ثلاثة أسطر من الشيفرة:

function convertJpegToPng(string $filename, string $outputFile) {
    $im = imagecreatefromjpeg($filename);
    imagepng($im, $outputFile);
    imagedestroy($im);
}

اقتصاص الصورة وتغيير حجمها

يمكنك استخدام الدالة imagecopyresampled إذا كان لديك صورة وتريد إنشاء صورة جديدة بأبعاد جديدة، أنشئ أولًا صورة جديدة بالأبعاد المرغوبة:

// صورة جديدة
$dst_img = imagecreatetruecolor($width, $height);

خزّن الصورة الأصلية في متغير، يمكنك القيام بذلك باستخدام إحدى دوال createimagefrom*‎ حيث يمكن أن تكون * هي jpeg أو gif أوpng أوstring، مثال:

// الصورة الأصلية
$src_img=imagecreatefromstring(file_get_contents($original_image_path));

ثم استخدم الدالة imagecopyresampled لنسخ كل الصورة الأصلية (أو جزء منها) (src_img) إلى الصورة الجديدة (dst_img):

imagecopyresampled($dst_img, $src_img,
    $dst_x ,$dst_y, $src_x, $src_y,
    $dst_width, $dst_height, $src_width, $src_height);

لضبط أبعاد src_*‎ و‎dst_*‎، استخدم الصورة التالية:

01.jpg

إذا كنت تريد الآن نسخ كامل الصورة المصدر (الأصلية) إلى كامل منطقة الهدف (بدون اقتصاص):

$src_x = $src_y = $dst_x = $dst_y = 0;

// عرض الصورة الجديدة
$dst_width = $width;

// طول الصورة الجديدة
$dst_height = $height;

// عرض الصورة الأصلية
$src_width = imagesx($src_img);

// طول الصورة الأصلية
$src_height = imagesy($src_img);

مكتبة Imagick

التثبيت

  • باستخدام apt في الأنظمة المعتمدة على Debian:
sudo apt-get install php5-imagick
  • باستخدام Homebrew في أنظمة OSX/macOs:
brew install imagemagick
  • باستخدام الإصدارات الثنائية: التعليمات في موقع imagemagick.

الاستخدام

<?php
$imagen = new Imagick('imagen.jpg');
// ‫إذا وضعت قيمة المعامل 0 ستتم المحافظة على نسبة العرض
$imagen->thumbnailImage(100, 0);

echo $imagen;
?>

تحويل صورة إلى سلسلة نصية بالأساس 64

يُظهر هذا المثال كيفية تحويل صورة إلى سلسلة نصية بالأساس 64 (أي سلسلة نصية يمكنك استخدامها مباشرةً في السمة src لوسم img)، يستخدم هذا المثال مكتبة Imagick لكن يمكن استخدام مكتبات أخرى مثل GD.

<?php
// (1)
$img = new Imagick('image.jpg');

// (2)
$img->resizeImage(320, 240);

// (3)
$imgBuff = $img->getimageblob();

// (4)
$img->clear();

// (5)
$img = base64_encode($imgBuff);
echo "<img alt='Embedded Image' src='data:image/jpeg;base64,$img' />";

في الموضع (1) يُحمَّل الملف image.jpg للمعالجة، مسار الملف نسبي إلى ملف ‎.php‎ المتضمن هذه الشيفرة لذا في هذا المثال يجب أن يكون ملف image.jpg في نفس مجلد السكربت.

في الموضع (2) يتغير حجم الصورة للحجم المُعطى كطول وعرض وإذا أردت تغيير دقة الصورة أيضًا مع تغيير الحجم يمكنك استخدام الدالة ‎$img->resampleimage(320, 240)‎، لاحظ أنّه يمكنك ضبط المعامل الثاني إلى 0 للمحافظة على نسبة عرض الصورة.

في الموضع (3) تُرجع الدالة تمثيل الصورة على شكل سلسلة نصية غير مشفرة.

في الموضع (4) يُزال المورد image.jpg من الكائن ‎$img‎ ويُدمَّر الكائن مما يحرر موارد النظام المحجوزة لمعالجة الصورة.

في الموضع (5) تُنشأ نسخة بتشفير الأساس 64 من السلسلة النصية السابقة غير المشفرة ثم تُعرَض كصورة في الصفحة، لاحظ أنّه قد يتغير الجزء image/jpeg في السمة src وذلك بالاعتماد على نوع الصورة التي تستخدمها (png أوjpeg مثلًا).

ترجمة -وبتصرف- للفصول [Image Processing with GD - Imagick] من كتاب PHP Notes for Professionals book

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...