2008-09-22 27 views
31

Mam mały problem z przeskalowaniem obrazów do prawidłowo zdefiniowanego rozmiaru. Zastanawiam się - skoro jest to czysto matematyczne, jeśli istnieje jakiś typowy algorytm logiczny, który działa w każdym języku (PHP, ActionScript, JavaScript itp.) W celu proporcjonalnego skalowania obrazów.Proportional image resize

używam tego w tej chwili:

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); 
} 

Ale to nie działa prawidłowo. Obrazy skalują się proporcjonalnie, ale rozmiar nie jest ustawiony na 300 (szerokość lub wysokość). To ma sens, ale zastanawiałem się, czy istnieje niepoprawny i łatwy sposób skalowania obrazów proporcjonalnie.

Odpowiedz

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

Upewnij się, że wszystkie podziały są zmiennoprzecinkowe.

2

Nie polecam samodzielnego pisania tego kodu; są miriady szczegółów na poziomie pikseli, które wymagają poważnego wysiłku, aby uzyskać właściwą. Użyj ImageMagick, to najlepsza biblioteka graficzna.

4

Dark Shikari go ma. Twoje rozwiązanie, o którym mowa w pytaniu, nie działa, ponieważ nie jesteś najpierw ustalając, który stosunek wymiaru dimensona do wielkości jest większy i , a następnie, zmniejszając oba wymiary o ten większy stosunek.

Obecne rozwiązanie wykorzystania seryjnej, warunkowej analizy jednego potencjalnego naruszenia wymiarów, a następnie drugiego, nie będzie działać.

Należy również pamiętać, że jeśli chcesz uzyskać wysokiej jakości obrazy, twoje obecne rozwiązanie nie będzie działać, a Dark Shikari ponownie.

0

Oto funkcja, którą opracowałem dla mojej witryny, możesz chcieć jej użyć. Jest to oparte na twojej odpowiedzi powyżej.

Wykonuje inne czynności, nie tylko przetwarzanie obrazu - proszę usunąć wszystko, co jest niepotrzebne..

<?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

Więc proszę pamiętać, to musi być wyczyszczone, jest mnóstwo wymiennych sekcji. –

0

dobrze, że wykonane z tej funkcji skalowania proporcjonalne wykorzystuje określoną szerokość, wysokość, oraz ewentualnie maksymalną szerokość/wysokość U ma (w zależności od zadanej szerokości i wysokości)

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 
     ); 
    } 

użytkowania :

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

Oto jak to zrobić:

+ (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; 
}