سؤال

ما هي الطريقة الأكثر فعالية لتغيير حجم الصور الكبيرة في PHP?

أنا حاليا باستخدام GD وظيفة imagecopyresampled أن تأخذ الصور عالية الدقة و نظيفة حجمها إلى حجم عرض الويب (تقريبا 700 بكسل واسعة من قبل 700 بكسل طويل القامة).

هذا يعمل كبيرة على الصغيرة (أقل من 2 MB) الصور كامل حجم العملية تستغرق أقل من ثانية على الملقم.ومع ذلك ، فإن الموقع سيكون في نهاية المطاف خدمة المصورين الذين قد يكون تحميل الصور تصل إلى 10 ميغابايت في حجم (أو الصور تصل إلى 5000x4000 بكسل في الحجم).

تفعل هذا النوع من تغيير حجم العملية مع الصور الكبيرة يميل إلى زيادة استخدام الذاكرة بواسطة وبهامش كبير جدا (أكبر من الصور يمكن أن ارتفاع استخدام الذاكرة في النص الماضي 80 ميجا بايت).هل هناك أي طريقة لجعل هذا تغيير حجم العملية أكثر كفاءة ؟ يجب أن يكون باستخدام بديل مكتبة الصور مثل يماغيماغيك?

الآن تغيير التعليمات البرمجية تبدو شيئا مثل هذا

function makeThumbnail($sourcefile, $endfile, $thumbwidth, $thumbheight, $quality) {
    // Takes the sourcefile (path/to/image.jpg) and makes a thumbnail from it
    // and places it at endfile (path/to/thumb.jpg).

    // Load image and get image size.
    $img = imagecreatefromjpeg($sourcefile);
    $width = imagesx( $img );
    $height = imagesy( $img );

    if ($width > $height) {
        $newwidth = $thumbwidth;
        $divisor = $width / $thumbwidth;
        $newheight = floor( $height / $divisor);
    } else {
        $newheight = $thumbheight;
        $divisor = $height / $thumbheight;
        $newwidth = floor( $width / $divisor );
    }

    // Create a new temporary image.
    $tmpimg = imagecreatetruecolor( $newwidth, $newheight );

    // Copy and resize old image into new image.
    imagecopyresampled( $tmpimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height );

    // Save thumbnail into a file.
    imagejpeg( $tmpimg, $endfile, $quality);

    // release the memory
    imagedestroy($tmpimg);
    imagedestroy($img);
هل كانت مفيدة؟

المحلول

الناس يقولون أن يماغيماغيك هو أسرع بكثير.في أفضل الأحوال مجرد مقارنة كل المكتبات و تدبير.

  1. إعداد 1000 الصور النمطية.
  2. كتابة البرامج النصية اثنين -- واحد GD, واحد بالنسبة ImageMagick.
  3. تشغيل كل منهم عدة مرات.
  4. مقارنة النتائج (مجموع التنفيذ الوقت وحدة المعالجة المركزية و I/O الاستخدام ، نتيجة جودة الصورة).

وهو أفضل من أي شخص آخر, لا يمكن أن يكون أفضل بالنسبة لك.

أيضا ، في رأيي ، يماغيماغيك أفضل بكثير واجهة API.

نصائح أخرى

هنا مقتطف من php.net المستندات التي استخدمتها في المشروع يعمل بشكل جيد:

<?
function fastimagecopyresampled (&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 3) {
    // Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
    // Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
    // Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
    // Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain.
    //
    // Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero.
    // Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect.
    // 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized.
    // 2 = Up to 95 times faster.  Images appear a little sharp, some prefer this over a quality of 3.
    // 3 = Up to 60 times faster.  Will give high quality smooth results very close to imagecopyresampled, just faster.
    // 4 = Up to 25 times faster.  Almost identical to imagecopyresampled for most images.
    // 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled.

    if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; }
    if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
        $temp = imagecreatetruecolor ($dst_w * $quality + 1, $dst_h * $quality + 1);
        imagecopyresized ($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h);
        imagecopyresampled ($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality);
        imagedestroy ($temp);
    } else imagecopyresampled ($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
    return true;
}
?>

http://us.php.net/manual/en/function.imagecopyresampled.php#77679

phpThumb يستخدم يماغيماغيك كلما أمكن السرعة (يتراجع إلى GD إذا لزم الأمر) و يبدو أن ذاكرة التخزين المؤقت بشكل جيد لتقليل الحمل على الخادم.انها خفيفة الوزن جدا لمحاولة الخروج (لتغيير حجم الصورة فقط اتصل phpThumb.php مع الحصول على استعلام يتضمن الرسم اسم الملف و إخراج الأبعاد) ، لذلك قد تعطيه فرصة لمعرفة ما إذا كان يلبي احتياجاتك.

أكبر الصور استخدام libjpeg إلى تغيير في صورة الحمل في يماغيماغيك وبالتالي الحد بشكل كبير من استخدام الذاكرة وتحسين الأداء ، فإنه ليس من الممكن مع GD.

$im = new Imagick();
try {
  $im->pingImage($file_name);
} catch (ImagickException $e) {
  throw new Exception(_('Invalid or corrupted image file, please try uploading another image.'));
}

$width  = $im->getImageWidth();
$height = $im->getImageHeight();
if ($width > $config['width_threshold'] || $height > $config['height_threshold'])
{
  try {
/* send thumbnail parameters to Imagick so that libjpeg can resize images
 * as they are loaded instead of consuming additional resources to pass back
 * to PHP.
 */
    $fitbyWidth = ($config['width_threshold'] / $width) > ($config['height_threshold'] / $height);
    $aspectRatio = $height / $width;
    if ($fitbyWidth) {
      $im->setSize($config['width_threshold'], abs($width * $aspectRatio));
    } else {
      $im->setSize(abs($height / $aspectRatio), $config['height_threshold']);
    }
    $im->readImage($file_name);

/* Imagick::thumbnailImage(fit = true) has a bug that it does fit both dimensions
 */
//  $im->thumbnailImage($config['width_threshold'], $config['height_threshold'], true);

// workaround:
    if ($fitbyWidth) {
      $im->thumbnailImage($config['width_threshold'], 0, false);
    } else {
      $im->thumbnailImage(0, $config['height_threshold'], false);
    }

    $im->setImageFileName($thumbnail_name);
    $im->writeImage();
  }
  catch (ImagickException $e)
  {
    header('HTTP/1.1 500 Internal Server Error');
    throw new Exception(_('An error occured reszing the image.'));
  }
}

/* cleanup Imagick
 */
$im->destroy();

من quesion, يبدو أنك جديدة نوعا ما إلى GD, سوف أشارك بعض اكسبيرينسي من الألغام ، ربما هذا هو قليلا خارج الموضوع ولكن أعتقد أنه سوف يكون من المفيد شخص جديد GD مثلك:

الخطوة 1 من صحة الملف. استخدام الدالة التالية للتحقق مما إذا $_FILES['image']['tmp_name'] الملف هو ملف صالح:

   function getContentsFromImage($image) {
      if (@is_file($image) == true) {
         return file_get_contents($image);
      } else {
         throw new \Exception('Invalid image');
      }
   }
   $contents = getContentsFromImage($_FILES['image']['tmp_name']);

الخطوة 2 على شكل ملف محاولة الدالة التالية مع finfo امتداد للتحقق من ملف تنسيق الملف(المحتويات).كنت أقول لماذا لا يمكنك فقط استخدام $_FILES["image"]["type"] للتحقق من تنسيق الملف ؟ لأنه فقط تحقق امتداد الملف لم محتويات الملف, اذا كان شخص ما تسمية ملف يسمى في الأصل العالم.png إلى world.jpg, $_FILES["image"]["type"] عودة الحياة السياسية في فرنسا لا بابوا نيو غينيا, حتى $_FILES["image"]["type"] قد يعود نتيجة خاطئة.

   function getFormatFromContents($contents) {
      $finfo = new \finfo();
      $mimetype = $finfo->buffer($contents, FILEINFO_MIME_TYPE);
      switch ($mimetype) {
         case 'image/jpeg':
            return 'jpeg';
            break;
         case 'image/png':
            return 'png';
            break;
         case 'image/gif':
            return 'gif';
            break;
         default:
            throw new \Exception('Unknown or unsupported image format');
      }
   }
   $format = getFormatFromContents($contents);

الخطوة.3, الحصول على الموارد GD الحصول على GD الموارد من محتويات لدينا من قبل:

   function getGDResourceFromContents($contents) {
      $resource = @imagecreatefromstring($contents);
      if ($resource == false) {
         throw new \Exception('Cannot process image');
      }
      return $resource;
   }
   $resource = getGDResourceFromContents($contents);

الخطوة 4 الحصول على صورة البعد الآن يمكنك الحصول على صورة البعد التالية رمز بسيط:

  $width = imagesx($resource);
  $height = imagesy($resource);

الآن ، دعونا نرى ما هو متغير علينا من الصورة الأصلية ثم:

       $contents, $format, $resource, $width, $height
       OK, lets move on

الخطوة 5 ، وحساب حجم الصورة الحجج هذه الخطوة هي ذات الصلة إلى سؤالك ، والغرض من الدالة التالية للحصول على حجم الحجج GD وظيفة imagecopyresampled(), مدونة نوعا ما طويلة ، ولكن يعمل كبيرة ، حتى أنه لديه ثلاثة خيارات:تمتد, انكماش, وملء.

تمتد:إخراج الصورة البعد هو نفس البعد الجديد تعيين.لن تبقى الطول/العرض نسبة.

يتقلص:إخراج الصورة البعد لن تتجاوز البعد الجديد كنت تعطي ، والحفاظ على صورة الطول/العرض نسبة.

ملء:إخراج الصورة البعد سوف يكون نفس البعد الجديد ، وسوف المحاصيل & تغيير حجم صورة إذا لزم الأمر ، والحفاظ على صورة الطول/العرض نسبة. هذا الخيار هو ما تحتاج إليه في سؤالك.

   function getResizeArgs($width, $height, $newwidth, $newheight, $option) {
      if ($option === 'stretch') {
         if ($width === $newwidth && $height === $newheight) {
            return false;
         }
         $dst_w = $newwidth;
         $dst_h = $newheight;
         $src_w = $width;
         $src_h = $height;
         $src_x = 0;
         $src_y = 0;
      } else if ($option === 'shrink') {
         if ($width <= $newwidth && $height <= $newheight) {
            return false;
         } else if ($width / $height >= $newwidth / $newheight) {
            $dst_w = $newwidth;
            $dst_h = (int) round(($newwidth * $height) / $width);
         } else {
            $dst_w = (int) round(($newheight * $width) / $height);
            $dst_h = $newheight;
         }
         $src_x = 0;
         $src_y = 0;
         $src_w = $width;
         $src_h = $height;
      } else if ($option === 'fill') {
         if ($width === $newwidth && $height === $newheight) {
            return false;
         }
         if ($width / $height >= $newwidth / $newheight) {
            $src_w = (int) round(($newwidth * $height) / $newheight);
            $src_h = $height;
            $src_x = (int) round(($width - $src_w) / 2);
            $src_y = 0;
         } else {
            $src_w = $width;
            $src_h = (int) round(($width * $newheight) / $newwidth);
            $src_x = 0;
            $src_y = (int) round(($height - $src_h) / 2);
         }
         $dst_w = $newwidth;
         $dst_h = $newheight;
      }
      if ($src_w < 1 || $src_h < 1) {
         throw new \Exception('Image width or height is too small');
      }
      return array(
          'dst_x' => 0,
          'dst_y' => 0,
          'src_x' => $src_x,
          'src_y' => $src_y,
          'dst_w' => $dst_w,
          'dst_h' => $dst_h,
          'src_w' => $src_w,
          'src_h' => $src_h
      );
   }
   $args = getResizeArgs($width, $height, 150, 170, 'fill');

الخطوة 6, تغيير حجم الصورة استخدام $args, $width, $height, $format و $الموارد لدينا من أعلاه إلى الدالة التالية والحصول على مورد جديد من تغيير حجم الصورة:

   function runResize($width, $height, $format, $resource, $args) {
      if ($args === false) {
         return; //if $args equal to false, this means no resize occurs;
      }
      $newimage = imagecreatetruecolor($args['dst_w'], $args['dst_h']);
      if ($format === 'png') {
         imagealphablending($newimage, false);
         imagesavealpha($newimage, true);
         $transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
         imagefill($newimage, 0, 0, $transparentindex);
      } else if ($format === 'gif') {
         $transparentindex = imagecolorallocatealpha($newimage, 255, 255, 255, 127);
         imagefill($newimage, 0, 0, $transparentindex);
         imagecolortransparent($newimage, $transparentindex);
      }
      imagecopyresampled($newimage, $resource, $args['dst_x'], $args['dst_y'], $args['src_x'], $args['src_y'], $args['dst_w'], $args['dst_h'], $args['src_w'], $args['src_h']);
      imagedestroy($resource);
      return $newimage;
   }
   $newresource = runResize($width, $height, $format, $resource, $args);

الخطوة 7 ، الحصول على المحتويات الجديدة, استخدم الدالة التالية للحصول على محتويات من جديد GD الموارد:

   function getContentsFromGDResource($resource, $format) {
      ob_start();
      switch ($format) {
         case 'gif':
            imagegif($resource);
            break;
         case 'jpeg':
            imagejpeg($resource, NULL, 100);
            break;
         case 'png':
            imagepng($resource, NULL, 9);
      }
      $contents = ob_get_contents();
      ob_end_clean();
      return $contents;
   }
   $newcontents = getContentsFromGDResource($newresource, $format);

الخطوة 8 على امتداد, استخدم الدالة التالية إلى الحصول على تمديد من شكل صورة(ملاحظة شكل صورة لا تساوي صورة ملحق):

   function getExtensionFromFormat($format) {
      switch ($format) {
         case 'gif':
            return 'gif';
            break;
         case 'jpeg':
            return 'jpg';
            break;
         case 'png':
            return 'png';
      }
   }
   $extension = getExtensionFromFormat($format);

الخطوة 9 حفظ الصورة إذا كان لدينا مستخدم يدعى مايك ، يمكنك القيام بما يلي ، سيتم حفظ إلى نفس المجلد مثل هذا البرنامج النصي php:

$user_name = 'mike';
$filename = $user_name . '.' . $extension;
file_put_contents($filename, $newcontents);

الخطوة 10 تدمير الموارد لا ننسى تدمير GD الموارد!

imagedestroy($newresource);

أو يمكنك كتابة كل ما تبذلونه من التعليمات البرمجية في فئة ببساطة استخدام ما يلي:

   public function __destruct() {
      @imagedestroy($this->resource);
   }

نصائح

أنصح بعدم تحويل تنسيق الملف المستخدم تحميل, سوف يجتمع العديد من المشاكل.

أقترح عليك أن تعمل شيء على طول هذه الخطوط:

  1. إجراء getimagesize( ) على الملف الذي تم تحميله إلى التحقق من نوع الصورة و الحجم
  2. حفظ أي حملت صورة JPEG أصغر من 700x700px في المجلد الوجهة "كما هو"
  3. استخدام GD مكتبة متوسطة الحجم الصور (انظر هذه المقالة على نموذج التعليمات البرمجية: تغيير حجم الصور باستخدام PHP GD مكتبة)
  4. استخدام ImageMagick على الصور الكبيرة.يمكنك استخدام يماغيماغيك في الخلفية إذا كنت تفضل ذلك.

استخدام يماغيماغيك في الخلفية ، نقل الملفات التي تم تحميلها إلى المجلد المؤقت والجدول الزمني وظيفة كرون أن "تحويل"s جميع ملفات jpeg و تغيير حجم وفقا لذلك.انظر جملة الأمر في: يماغيماغيك-قيادة خط المعالجة

يمكنك مطالبة المستخدم الذي يتم تحميل الملف و من المقرر أن تتم معالجتها.كرون الوظيفة يمكن أن يكون المقرر تشغيل يوميا في فترة زمنية محددة.مصدر الصورة يمكن حذفها بعد المعالجة للتأكد من أن الصورة لم تتم معالجة مرتين.

لقد سمعت أشياء كبيرة حول Imagick مكتبة للأسف لم أستطع تثبيته في جهاز الكمبيوتر الخاص بك في العمل ولا في البيت (و ثق بي, لقد قضيت ساعات وساعات على جميع أنواع المنتديات).

تعمل قررت أن تحاول هذه الطبقة PHP:

http://www.verot.net/php_class_upload.htm

إنه بارد جدا و لا يمكن تغيير حجم جميع أنواع الصور (يمكن تحويلها الى JPG أيضا).

يماغيماغيك هو مؤشرات, لذلك يبدو أن تكون أسرع, ولكن في الواقع يستخدم الكثير من الموارد أكثر مما GD.إذا قمت بتشغيل العديد من البرامج النصية PHP في موازاة كل ذلك باستخدام GD ثم أنهم فاز يماغيماغيك في سرعة عمليات بسيطة.ExactImage هو أقل قوة من يماغيماغيك ولكن الكثير أسرع, وإن لم تكن متاحة من خلال PHP, يجب عليك تثبيته على الخادم وتشغيله من خلال exec.

أكبر الصور الاستخدام phpThumb().هنا هو كيفية استخدامه: http://abcoder.com/php/problem-with-resizing-corrupted-images-using-php-image-functions/.كما يعمل كبيرة تلف الصور.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top