it-swarm.com.de

Berechnen des Bildgrößenverhältnisses für die Größenänderung

Ich habe eine feste Breite und Höhe, um die Größe eines Bildes zu ändern. Ich habe jedoch ein Problem damit, da das Bild ein beliebiges Größenverhältnis haben kann (es kann vertikal oder das horizontal sein). In diesem Fall verursachen feste Breite und Höhe ein Problem. Ich möchte Breite und Höhe intelligenter berechnen.

Zum Beispiel sagen wir, ich habe Breite 1024px und Höhe 768px definiert. Und ich möchte ein Bild vergrößern, das vertikal (Höhe 1100px und Breite 200px) ist. In meinem Fall wird die Größe daher auf festes size (1024x768) geändert, sodass die Breite von 100px auf 768px erhöht wird und sehr hässlich wird. Wenn das Bild eine Höhe von weniger als 768px hat, erhöht sich die Höhe ebenfalls gewaltsam auf 768px .

Daher möchte ich die neue Bildgröße basierend auf dem ursprünglichen Bildgrößenverhältnis berechnen. Sagen wir, wenn das obige Beispielbild auf die maximale Höhe von 768px skaliert werden soll, aber was ist dann mit der Breite? es ist schon weniger als meine "maximale Breite", die 200px ist, sollte die Breite also unverändert bleiben? oder sollte es weiter verringert werden?

Ebenso, wenn das Bild die Höhe 200px und die Breite 1100px hat. Die Breite sollte also auf 1024px verringert werden, aber wie steht es mit der Höhe?

Das dritte Problem ist, nehmen wir an, wenn sowohl Höhe als auch Breite mehr als die maximale Höhe und maximale Breite sind, sagen wir width: 1100px und height: 4000px . Da Breite und Höhe beide größer als die maximale Breite und maximale Höhe sind, das Bild jedoch vertikal ist, wird es horizontal ausgerichtet. Wie kann ich also überprüfen, ob in diesem Fall das Bild entsprechend der maximalen Höhe oder der maximalen Breite angepasst werden soll?

Ich bin dankbar für jede Hilfe.

42
sunjie

Hier ist der Code aus meiner persönlichen Sammlung von Code zum Ändern der Bildgröße. Zuerst benötigen Sie Daten:

list($originalWidth, $originalHeight) = getimagesize($imageFile);
$ratio = $originalWidth / $originalHeight;

Dann passt dieser Algorithmus das Bild so gut wie möglich in die Zielgröße ein, wobei das ursprüngliche Seitenverhältnis beibehalten und das Bild nicht größer als das Original gedehnt wird:

$targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight));

if ($ratio < 1) {
    $targetWidth = $targetHeight * $ratio;
} else {
    $targetHeight = $targetWidth / $ratio;
}

$srcWidth = $originalWidth;
$srcHeight = $originalHeight;
$srcX = $srcY = 0;

Dadurch wird das Bild so beschnitten, dass es die Zielgröße vollständig ausfüllt und nicht dehnt:

$targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size);

if ($ratio < 1) {
    $srcX = 0;
    $srcY = ($originalHeight / 2) - ($originalWidth / 2);
    $srcWidth = $srcHeight = $originalWidth;
} else {
    $srcY = 0;
    $srcX = ($originalWidth / 2) - ($originalHeight / 2);
    $srcWidth = $srcHeight = $originalHeight;
}

Und das macht die eigentliche Größenänderung:

$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight);

In diesem Fall ist der $size nur eine Zahl für Breite und Höhe (quadratische Zielgröße). Ich bin sicher, dass Sie es ändern können, um nicht quadratische Ziele zu verwenden. Es sollte auch eine Inspiration für die anderen Algorithmen zur Größenänderung geben, die Sie verwenden können.

69
deceze
$ratio = $originalWidth / $originalHeight

wenn Sie die Höhe ändern möchten:

$targetWidth = $targetHeight * $ratio

wenn Sie die Breite ändern möchten:

$targetHeight = $targetWidth / $ratio
47

Sie möchten das Seitenverhältnis Ihres Originalbildes beibehalten. Dies ist das Verhältnis zwischen der Breite und der Höhe des Bildes. Sie berechnen also den Faktor, um den Sie die Größe des Bildes in vertikaler und horizontaler Richtung ändern müssen, und halten dann den höheren Wert ein. Im Pseudocode:

target_height = 768
target_width = 1024
# v_fact and h_fact are the factor by which the original vertical / horizontal
# image sizes should be multiplied to get the image to your target size.
v_fact = target_height / im_height 
h_fact = target_width / im_width
# you want to resize the image by the same factor in both vertical 
# and horizontal direction, so you need to pick the correct factor from
# v_fact / h_fact so that the largest (relative to target) of the new height/width
# equals the target height/width and the smallest is lower than the target.
# this is the lowest of the two factors
im_fact = min(v_fact, h_fact)
new_height = im_height * im_fact
new_width = im_width * im_fact
image.resize(new_width, new_height)
12
jilles de wit

das funktioniert.

function calculateDimensions($width,$height,$maxwidth,$maxheight)
{

        if($width != $height)
        {
            if($width > $height)
            {
                $t_width = $maxwidth;
                $t_height = (($t_width * $height)/$width);
                //fix height
                if($t_height > $maxheight)
                {
                    $t_height = $maxheight;
                    $t_width = (($width * $t_height)/$height);
                }
            }
            else
            {
                $t_height = $maxheight;
                $t_width = (($width * $t_height)/$height);
                //fix width
                if($t_width > $maxwidth)
                {
                    $t_width = $maxwidth;
                    $t_height = (($t_width * $height)/$width);
                }
            }
        }
        else
            $t_width = $t_height = min($maxheight,$maxwidth);

        return array('height'=>(int)$t_height,'width'=>(int)$t_width);
    }
7
kestas

Überprüfen Sie den PHP-Code unten:

$new_width  = 1024;
$new_height = 768;
$this_image = "images/my_image";

list($width, $height, $type, $attr) = getimagesize("$this_image");

if ($width > $height) {
  $image_height = floor(($height/$width)*$new_width);
  $image_width  = $new_width;
} else {
  $image_width  = floor(($width/$height)*$new_height);
  $image_height = $new_height;
}
echo "<img src='$this_image' height='$image_height' width='$image_width'>";
1
Wayne

Sie müssen das Breiten-/Höhenverhältnis "beibehalten". Ursprünglich haben Sie ein Bild der Größe (B x H) 500x1000, dieses Verhältnis von Breite zu Höhe ist 0.5. Angenommen, Sie ändern 1000 in 768 in der Höhe, wäre Ihre Ergebnisbreite 0.5 * 768 = 384

Ein anderes Beispiel, 1800 x 1200 und Ihre neue Höhe ist 200, dann ist Ihre neue Breite 300, da 300/2001.5 und 1800/1200 ebenfalls 1.5 ist.

Viel Glück.

1
Gary Tsui

Wie wäre es damit:

double ratio = imageWidth/imageHeight;
int newHeight = Math.min(displayHeight, displayWidth / ratio); 
int newWidth =  Math.min(displayWidth, displayHeight * ratio); 
0
Yaza

Wenn die maximale Höhe oder Breite gegeben ist oder nicht, verwenden Sie @ (jilles de wit)

Überlegungen: Diese sollten bereits definiert sein!

$mh = given height limit; //optional
$mw = given width limit; //optional

$height = $nh =[your original height];
$width = $nw =[your original width];

Der Code

if($mh || $mw){
if(is_numeric($mh)){$h_fact = $mh / $nh;}
if(is_numeric($mw)){$v_fact = $mw / $nw;}

if(is_numeric($v_fact) && is_numeric($h_fact)  ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;}
$nw = $nw * $im_fact;
$nh = $nh * $im_fact;
}

Resampling

$dst_img = imagecreatetruecolor($nw,$nh);
imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height);
0
Miguel

Sie sollten die Größe ändern, je nachdem, welche Eigenschaft vom maximalen Wert entfernt ist. Berechnen Sie dann das Verhältnis.

if(($w - $w_max) > ($h - $h_max)) {
    $w_new = $w_max;
    $h_new = (int) ($h * ($w_max / $w));
}
else {
    $h_new = $h_max;
    $w_new = (int) ($w * ($h_max / $h));
}
0
Sascha Galley
class Image_Aspect_Ratio_Resize {
var $image_to_resize;
var $new_width;
var $new_height;
var $ratio;
var $new_image_name;
var $save_folder;

function resize() {
    if (!file_exists($this->image_to_resize)) {
        exit("File " . $this->image_to_resize . " does not exist.");
    }

    $info = GetImageSize($this->image_to_resize);

    if (empty($info)) {
        exit("The file " . $this->image_to_resize . " doesn't seem to be an image.");
    }

    $width = $info[0];
    $height = $info[1];
    $mime = $info['mime'];

    /* Keep Aspect Ratio? */

    if ($this->ratio) {
        $thumb = ($this->new_width < $width && $this->new_height < $height) ? true : false; // Thumbnail
        $bigger_image = ($this->new_width > $width || $this->new_height > $height) ? true : false; // Bigger Image

        if ($thumb) {
            if ($this->new_width >= $this->new_height) {
                $x = ($width / $this->new_width);

                $this->new_height = ($height / $x);
            } else if ($this->new_height >= $this->new_width) {
                $x = ($height / $this->new_height);

                $this->new_width = ($width / $x);
            }
        } else if ($bigger_image) {
            if ($this->new_width >= $width) {
                $x = ($this->new_width / $width);

                $this->new_height = ($height * $x);
            } else if ($this->new_height >= $height) {
                $x = ($this->new_height / $height);

                $this->new_width = ($width * $x);
            }
        }
    }


    $type = substr(strrchr($mime, '/'), 1);

    switch ($type) {
        case 'jpeg':
            $image_create_func = 'ImageCreateFromJPEG';
            $image_save_func = 'ImageJPEG';
            $new_image_ext = 'jpg';
            break;

        case 'png':
            $image_create_func = 'ImageCreateFromPNG';
            $image_save_func = 'ImagePNG';
            $new_image_ext = 'png';
            break;

        case 'bmp':
            $image_create_func = 'ImageCreateFromBMP';
            $image_save_func = 'ImageBMP';
            $new_image_ext = 'bmp';
            break;

        case 'gif':
            $image_create_func = 'ImageCreateFromGIF';
            $image_save_func = 'ImageGIF';
            $new_image_ext = 'gif';
            break;

        case 'vnd.wap.wbmp':
            $image_create_func = 'ImageCreateFromWBMP';
            $image_save_func = 'ImageWBMP';
            $new_image_ext = 'bmp';
            break;

        case 'xbm':
            $image_create_func = 'ImageCreateFromXBM';
            $image_save_func = 'ImageXBM';
            $new_image_ext = 'xbm';
            break;

        default:
            $image_create_func = 'ImageCreateFromJPEG';
            $image_save_func = 'ImageJPEG';
            $new_image_ext = 'jpg';
    }

    // New Image
    $image_c = ImageCreateTrueColor($this->new_width, $this->new_height);

    $new_image = $image_create_func($this->image_to_resize);

    ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height);

    if ($this->save_folder) {
        if ($this->new_image_name) {
            $new_name = $this->new_image_name . '.' . $new_image_ext;
        } else {
            $new_name = $this->new_thumb_name(basename($this->image_to_resize)) . '_resized.' . $new_image_ext;
        }

        $save_path = $this->save_folder . $new_name;
    } else {
        /* Show the image without saving it to a folder */
        header("Content-Type: " . $mime);

        $image_save_func($image_c);

        $save_path = '';
    }

    $process = $image_save_func($image_c, $save_path);

    return array('result' => $process, 'new_file_path' => $save_path);
}}

/ * Funktionsaufruf * / 

$resize_image = new Image_Aspect_Ratio_Resize;
$new_width = (int) $_POST['new_width'];
$new_height = (int) $_POST['new_height'];
$resize_image->new_width = $new_width;
$resize_image->new_height = $new_height;
$resize_image->image_to_resize = $image; // Full Path to the file
$resize_image->ratio = true; // Keep aspect ratio
// Name of the new image (optional) - If it's not set a new will be added automatically
$resize_image->new_image_name = 'water_lilies_thumbnail';
/* Path where the new image should be saved. If it's not set the script will output the image without saving it */
$resize_image->save_folder = 'thumbs/';
$process = $resize_image->resize(); // Output image
0
Jah Yusuff

Ich bin zu dieser Frage gekommen und habe keine passende Antwort gefunden, also machte ich mich alleine auf, um die Frage zu beantworten.

ich begann mit einer grundlegenden Logik und nachdem ich einen Freund von mir befragt hatte, der in Mathe ein bisschen besser ist, haben wir uns das ausgedacht.

function calculate_dimensions($width,$height,$max){
    if($width != $height){
        if($width > $height){
            $t_height = $max;
            $t_width = min(($width * $t_height)/$height);
        }
        if($height > $width){
            $t_width = $max;
            $t_height = min(($t_width * $height)/$width)
        }
    }else{
        if($width > $max){
            $t_width = $t_height = $max;
        }
    }
    $res = ['height'=>$t_height,'width'=>$t_width]
    return $res;
}

Dieses Codefragment ist wiederverwendbar. Übergeben Sie einfach die maximal zulässige kleinste Bemaßung, und es wird die Bemaßung der größten Seite berechnet, so dass Sie eine korrekt skalierte Bemaßung erhalten, in der Sie den Ausschnitt zentrieren können, was zu einem korrekt verkleinerten und zugeschnittenen quadratischen Bild führt. Dies ist nützlich für Dinge wie Profilbilder und Thumbnails.

dank an meinen Freund Justin Gillett für seinen brillanten Vorschlag der Kreuzvervielfachung. 

0
r3wt

In diesem Beispiel wird ein Bild verkleinert, um es an ein definiertes Pixel-Seitenverhältnis (16: 9) anzupassen, wodurch ein Bild erstellt wird, das den angegebenen Grenzwert (1200 x 675) nicht überschreitet.

Stellen Sie Ihr Bildverhältnis und eine beliebige Obergrenze ein:

const RATIO_W                       = 16;
const RATIO_H                       = 9;
const RATIO_MULIPLIER_UPPER_LIMIT   = 75;

Berechnen Sie die neue Bildbreite und -höhe

list($imageWidth, $imageHeight) = getimagesize($path_to_image);    

if( ($imageWidth / $imageHeight) === (self::RATIO_W / self::RATIO_H) ){
    return;

// Find closest ratio multiple to image size
if($imageWidth > $imageHeight){
    // landscape
    $ratioMultiple  = round($imageHeight / self::RATIO_H, 0, PHP_ROUND_HALF_DOWN);
}else{
    // portrait
    $ratioMultiple  = round($imageWidth / self::RATIO_W, 0, PHP_ROUND_HALF_DOWN);
}    

$newWidth   = $ratioMultiple * self::RATIO_W;
$newHeight = $ratioMultiple * self::RATIO_H;    

if($newWidth > self::RATIO_W * self::RATIO_MULIPLIER_UPPER_LIMIT|| $newHeight > self::RATIO_H * self::RATIO_MULIPLIER_UPPER_LIMIT){
    // File is larger than upper limit
    $ratioMultiple = self::RATIO_MULIPLIER_UPPER_LIMIT;
}    

$this->tweakMultiplier($ratioMultiple, $imageWidth, $imageHeight);    

$newWidth   = $ratioMultiple * self::RATIO_W;
$newHeight = $ratioMultiple * self::RATIO_H;    

Bildgröße anpassen

$originalImage  = imagecreatefromjpeg( $tempImagePath );
$newImage       = imagecreatetruecolor($newWidth, $newHeight);
imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, imagecolorallocate($newImage, 255, 255, 255));
imagecopyresampled($newImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $imageWidth, $imageHeight);
imagejpeg($newImage, $tempImagePath, 100);

Durchlaufen Sie die Faktoren, bis beide Dimensionen die ursprüngliche Bildgröße unterschreiten

protected function tweakMultiplier( &$ratioMultiple, $fitInsideWidth, $fitInsideHeight ){
    $newWidth   = $ratioMultiple * self::RATIO_W;
    $newHeight  = $ratioMultiple * self::RATIO_H;    

    if($newWidth > $fitInsideWidth || $newHeight > $fitInsideHeight){
        echo " Tweak ";
        $ratioMultiple--;
        $this->tweakMultiplier($ratioMultiple, $fitInsideWidth, $fitInsideHeight);
    }else{
        return;
    }    
}
0
JPickup