2008-09-22 4 views
31

У меня немного проблема с масштабированием моих изображений до надлежащего предопределенного размера. Мне было интересно - поскольку это чисто математика, если есть какой-то общий логический алгоритм, который работает на каждом языке (PHP, ActionScript, Javascript и т. Д.) Для пропорционального масштабирования изображений.Пропорциональное изменение размера изображения

Я использую это на данный момент:

var maxHeight = 300; 
var maxWidth = 300; 

var ratio:Number = height/width; 

if (height > maxHeight) { 
    height = maxHeight; 
    width = Math.round(height/ratio); 
} 

else if(width > maxWidth) { 
    width = maxWidth; 
    height = Math.round(width * ratio); 
} 

Но это не работает должным образом. Изображения масштабируются пропорционально, конечно, но размер не установлен равным 300 (по ширине или по высоте). Это имеет смысл, но мне было интересно, есть ли простой и простой способ масштабирования изображений пропорционально.

ответ

64
ratio = MIN(maxWidth/width, maxHeight/ height); 
width = ratio * width; 
height = ratio * height; 

Убедитесь, что все деления являются плавающей точкой.

2

Я бы рекомендовал не писать этот код самостоятельно; есть мириады деталей уровня пикселя, которые занимают серьезное время, чтобы получить право. Используйте ImageMagick, это лучшая графическая библиотека.

4

У Темного Шикари есть это. Ваше решение, указанное в вопросе, терпит неудачу, потому что вы не сначала, устанавливая, какое отношение размера от размера к maxsize больше, и , затем, уменьшая оба размера за это большее отношение.

Ваше текущее решение использует последовательный, условный анализ одного потенциального нарушения размера, а затем другого не будет работать.

Обратите внимание, что если вы хотите высококлассные изображения, ваше текущее решение не будет летать, а Dark Shikari снова будет.

0

Вот функция, которую я разработал для своего сайта, вы можете использовать. Это основано на вашем ответе выше.

Он делает другие вещи не только для обработки изображений - удалите все, что не нужно.

<?php 

$thumb_width = 500; 
$thumb_height = 500; 

if ($handle = opendir('to-do')) { 
    echo "Directory handle: $handle<br />"; 
    echo "Files:<br /><br />"; 

    /* This is the correct way to loop over the directory. */ 
    while (false !== ($file = readdir($handle))) { 

     if (($file != ".") && ($file != "..")){ 
      echo "$file"; 

      $original_path = "to-do/" . $file; 

      $source_image = ImageCreateFromJPEG($original_path); 
      $thumb_width = $thumb_width; 
      $thumb_height = $thumb_height; 

      // Create the image, of the required size 
      $thumbnail = imagecreatetruecolor($thumb_width, $thumb_height); 
      if($thumbnail === false) { 
       //creation failed -- probably not enough memory 
       return null; 
      } 

      // Fill the image with a white color (this will be visible in the padding around the image, 
      // if the aspect ratios of the image and the thumbnail do not match) 
      // Replace this with any color you want, or comment it out for black. 
      // I used grey for testing =) 
      $fill = imagecolorallocate($thumbnail, 255, 255, 255); 
      imagefill($thumbnail, 0, 0, $fill); 

      // Compute resize ratio 
      $hratio = $thumb_height/imagesy($source_image); 
      $wratio = $thumb_width/imagesx($source_image); 
      $ratio = min($hratio, $wratio); 

      // If the source is smaller than the thumbnail size, 
      // Don't resize -- add a margin instead 
      // (that is, dont magnify images) 
      if ($ratio > 1.0) 
       $ratio = 1.0; 

      // Compute sizes 
      $sy = floor(imagesy($source_image) * $ratio); 
      $sx = floor(imagesx($source_image) * $ratio); 

      // Compute margins 
      // Using these margins centers the image in the thumbnail. 
      // If you always want the image to the top left, set both of these to 0 
      $m_y = floor(($thumb_height - $sy)/2); 
      $m_x = floor(($thumb_width - $sx)/2); 

      // Copy the image data, and resample 
      // If you want a fast and ugly thumbnail, replace imagecopyresampled with imagecopyresized 
      if (!imagecopyresampled($thumbnail, $source_image, 
       $m_x, $m_y, //dest x, y (margins) 
       0, 0, //src x, y (0,0 means top left) 
       $sx, $sy,//dest w, h (resample to this size (computed above) 
       imagesx($source_image), imagesy($source_image)) //src w, h (the full size of the original) 
      ) { 
       //copy failed 
       imagedestroy($thumbnail); 
       return null; 
      } 

      /* Set the new file name */ 
      $thumbnail_file_name = $file; 

      /* Apply changes on the original image and write the result on the disk */ 
      ImageJPEG($thumbnail, $complete_path . "done/" . $thumbnail_file_name); 
      unset($source_image); 
      unset($thumbnail); 
      unset($original_path); 
      unset($targeted_image_size); 

      echo " done<br />"; 

     } 

    } 

    closedir($handle); 
} 

?> 
+0

Так что, пожалуйста, помните, что его нужно очистить, есть множество съемной секции. – 2011-10-12 20:49:47

0

хорошо я сделал эту функцию в масштабе пропорционально, она использует заданную ширину, высоту, и, возможно, максимальную ширину/высоту у хотят (зависит от заданной ширины и высоты)

function scaleProportional($img_w,$img_h,$max=50) 
    { 
     $w = 0; 
     $h = 0; 

     $img_w > $img_h ? $w = $img_w/$img_h : $w = 1; 
     $img_h > $img_w ? $h = $img_h/$img_w : $h = 1; 

     $ws = $w > $h ? $ws = ($w/$w) * $max : $ws = (1/$h) * $max; 
     $hs = $h > $w ? $hs = ($h/$h) * $max : $hs = (1/$w) * $max; 

     return array(
      'width'=>$ws, 
      'height'=>$hs 
     ); 
    } 

использования :

  $getScale = scaleProportional(600,200,500); 
      $targ_w = $getScale['width']; //returns 500 
      $targ_h = $getScale['height']; //returns 16,6666667 
1

Вот как я это делаю:

+ (NSSize) scaleHeight:(NSSize)origSize 
      newHeight:(CGFloat)height { 

    NSSize newSize = NSZeroSize; 
    if (origSize.height == 0) return newSize; 

    newSize.height = height; 
    CGFloat factor = (height/origSize.height); 
    newSize.width = (origSize.width * factor); 

    return newSize; 
} 

+ (NSSize) scaleWidth:(NSSize)origSize 
      newWidth:(CGFloat)width { 

    NSSize newSize = NSZeroSize; 
    if (origSize.width == 0) return newSize; 

    newSize.width = width; 
    CGFloat factor = (width/origSize.width); 
    newSize.height = (origSize.height * factor); 

    return newSize; 
}