2009-12-30 10 views
6

Tengo una aplicación que permite a los usuarios subir imágenes. El caso de prueba que uso es un jpeg de 1.6MB con dimensiones 3872 x 2592px. El script de carga en el back-end va a cambiar el tamaño de la imagen cargada en 6 formatos adicionales:¿Cómo acelerar el cambio de tamaño de la imagen en una aplicación PHP CodeIgniter?

  • cuadrada (pequeño 75 x 75)
  • pulgar pequeño (50 x 38)
  • Pulgar (100 x 76)
  • Pequeño (240 x 161)
  • Medio (500 x 378)
  • grande (1024 x 774)

sé que Es mucho, pero créeme, lo necesito. Hago el cambio de tamaño usando la clase de Manipulación de Imagen de Code Igniter, que usa GD, GD2 o ImageMagick para hacer el cambio de tamaño. Primero lo configuré para usar GD2 y noté que el proceso de redimensionamiento total toma 11 segundos.

Como el usuario tiene que esperar este proceso, no es aceptable. Después de un montón de lectura supe que ImageMagick es una biblioteca mucho más rápido y eficiente manipulación, por lo que me pasa a lo siguiente:

$sourceimage = $data['filedata']['file_path'] . $data['imagedata']['user_id'] . "/" . $imageid . $data['filedata']['file_ext']; 
$resize_settings['image_library'] = 'imagemagick'; 
$resize_settings['library_path'] = '/usr/bin'; 
$resize_settings['source_image'] = $sourceimage; 
$resize_settings['maintain_ratio'] = false; 
$resize_settings['quality'] = "100%"; 
$this->load->library('image_lib', $resize_settings); 

Para mi sorpresa, el proceso de cambio de tamaño ahora toma más tiempo: 15 segundos para ser específico.

Al echar un vistazo a mi registro, veo que cada acción de redimensionamiento lleva 2 segundos, sin importar el formato de archivo al que se está redimensionando. Supongo que esto se debe a que siempre cambio el tamaño del original, que es muy grande.

No me gustaría descargar el proceso de redimensionamiento a un proceso programado, porque eso disminuiría la usabilidad del sitio. Significaría que los usuarios tienen que esperar unos minutos antes de poder comenzar a ver/trabajar con la imagen.

Entonces, ¿hay alguna manera inteligente de acelerar drásticamente este proceso de cambio de tamaño para que pueda mantenerlo en tiempo real? Solo aclare: permitir resoluciones más pequeñas no es una opción, este es un sitio de fotografía que estoy construyendo. Además, realmente necesito los seis formatos mencionados.

+0

alguna posibilidad de que nos pudiera proporcionar una imagen JPEG original 1.6MB? –

Respuesta

7

Como una idea, puede cambiar el tamaño del tamaño cargado a un tamaño intermedio más sensible y luego utilizar esto como base para otras operaciones.

Como alternativa, podría ejecutar la versión de línea de comandos de ImageMagick y realizar (al menos la mayor parte de) las transformaciones de imagen en segundo plano utilizando el proceso descrito en Asynchronous shell exec in PHP.

Por último, mientras que está un poco fuera de tema, ¿vas a permitir la orientación vertical, o no es probable que esto sea un factor?

+3

Muchas gracias. Ahora cambio el tamaño usando un efecto de goteo, lo que significa que empiezo desde grande para cambiar el tamaño a medio, luego uso la imagen mediana (en lugar de la imagen grande) para cambiar el tamaño a pequeño, etc. Ahora se necesitan menos de 3 segundos para hacer el crujido . Arranqué un formato (cuadrado) y cambié a GD2, en lugar de imagemagick. Por lo que puedo decir, no hay problemas de calidad visibles con este cambio de tamaño. ¡Gracias una vez más! – Ferdy

7

Parece que ya has aceptado una respuesta pero aún así voy a publicar la mía.

En primer lugar, que realmente no es necesario utilizar 100% en calidad, una 90% o 85% valor no tendrán ningún problema, mientras que la disminución de su tiempo de procesamiento y tamaño de la imagen (si no no me creo que haga algunas pruebas).

También he hecho algunos puntos de referencia con this image y una función personalizada JPEG(), primer caso de prueba:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg'); 
JPEG('./original.jpg', null, '500*378', './output/medium.jpg'); 
JPEG('./original.jpg', null, '240*161', './output/small.jpg'); 
JPEG('./original.jpg', null, '100*76', './output/thumb.jpg'); 
JPEG('./original.jpg', null, '50*38', './output/small_thumb.jpg'); 
JPEG('./original.jpg', null, '75*75', './output/square.jpg'); 

Esto toma un promedio de 60 segundos en mi lenta lenta ordenador.


caso de prueba Segunda:

JPEG('./original.jpg', null, '1024*774', './output/large.jpg'); 
JPEG('./output/large.jpg', null, '500*378', './output/medium.jpg'); 
JPEG('./output/medium.jpg', null, '240*161', './output/small.jpg'); 
JPEG('./output/medium.jpg', null, '100*76', './output/thumb.jpg'); 
JPEG('./output/medium.jpg', null, '50*38', './output/small_thumb.jpg'); 
JPEG('./output/medium.jpg', null, '75*75', './output/square.jpg'); 

Ésta toma "sólo" 16 segundos (mi equipo es muy lento ATM : P), casi 4 veces más rápido.


Aquí está la función JPEG() en caso de que quiera hacer sus propios puntos de referencia:

function JPEG($source, $crop = null, $scale = null, $destination = null) 
{ 
    $source = ImageCreateFromJPEG($source); 

    if (is_resource($source) === true) 
    { 
     $size = array(ImageSX($source), ImageSY($source)); 

     if (isset($crop) === true) 
     { 
      $crop = array_filter(explode('/', $crop), 'is_numeric'); 

      if (count($crop) == 2) 
      { 
       $crop = array($size[0]/$size[1], $crop[0]/$crop[1]); 

       if ($crop[0] > $crop[1]) 
       { 
        $size[0] = $size[1] * $crop[1]; 
       } 

       else if ($crop[0] < $crop[1]) 
       { 
        $size[1] = $size[0]/$crop[1]; 
       } 

       $crop = array(ImageSX($source) - $size[0], ImageSY($source) - $size[1]); 
      } 

      else 
      { 
       $crop = array(0, 0); 
      } 
     } 

     else 
     { 
      $crop = array(0, 0); 
     } 

     if (isset($scale) === true) 
     { 
      $scale = array_filter(explode('*', $scale), 'is_numeric'); 

      if (count($scale) >= 1) 
      { 
       if (empty($scale[0]) === true) 
       { 
        $scale[0] = $scale[1] * $size[0]/$size[1]; 
       } 

       else if (empty($scale[1]) === true) 
       { 
        $scale[1] = $scale[0] * $size[1]/$size[0]; 
       } 
      } 

      else 
      { 
       $scale = array($size[0], $size[1]); 
      } 
     } 

     else 
     { 
      $scale = array($size[0], $size[1]); 
     } 

     $result = ImageCreateTrueColor($scale[0], $scale[1]); 

     if (is_resource($result) === true) 
     { 
      if (ImageCopyResampled($result, $source, 0, 0, $crop[0]/2, $crop[1]/2, $scale[0], $scale[1], $size[0], $size[1]) === true) 
      { 
       return ImageJPEG($result, $destination, 90); 
      } 
     } 
    } 

    return false; 
} 
+0

Gracias, tu respuesta definitivamente enriquece el hilo. En realidad, intenté cambiar la calidad, como caso de prueba extrema utilicé el 10%. El resultado fue que el procedimiento de cambio de tamaño total aún tomó exactamente el mismo tiempo que antes. Esto me llevó a creer que la resolución era el problema, no la calidad. Acabo de probar esa misma calidad del 10% de nuevo en mi lógica de cambio de tamaño mejorada y nuevamente toma exactamente el mismo tiempo con una calidad del 100%. Sin embargo, no estoy seguro de por qué. – Ferdy

+0

Una observación más, si es posible, me gustaría quedarme con la clase de imagen CodeIgniter, ya que puede manejar casi todos los tipos de archivos de imagen y oculta la complejidad de tratar con rutinas de tamaño de imagen de menor nivel. Solo si todo lo demás falla y si hay una clara ventaja, cambiaría. – Ferdy

+3

@Ferdy: Sí, no debería importar mucho en términos de velocidad, pero igual debería usar una calidad inferior, el 90% reduce el tamaño de la imagen a la mitad y mantiene toda la calidad. –

Cuestiones relacionadas