Come posso ritagliare / immagini dell'utente scala in modo da poter visualizzare le miniature di dimensioni fisse, senza inclinazione e stretching?

StackOverflow https://stackoverflow.com/questions/991587

Domanda

su cui sto lavorando che permette agli utenti di caricare le immagini del profilo per il mio sito. Il classico esempio di quello che sto cercando di evitare è plentyoffish.com dove l'immagine ogni utenti è inclinata e sembra molto brutto:

alt text

Quindi, come posso progmatically coltura / creare versioni di dimensioni standard di un'immagine senza l'inclinazione dimostrato sopra?

È stato utile?

Soluzione

Bene, è necessario disporre di un massimo altezza e larghezza, consente di assumere la dimensione dell'immagine che avete a disposizione è quadrata, dicono 100x100.

Quando un utente carica un'immagine ottenere le dimensioni, poi risolvono che è maggiore, l'altezza o la larghezza.

Poi prendere il più grande misura e ottenere il rapporto di questa misura per la vostra misura di destinazione, quindi utilizzare tale rapporto per scalare sia l'altezza e la larghezza.

Quindi, se l'utente carica una foto di 500 di altezza e 450 di larghezza, l'altezza è il più grande che ci si divide 100 per 500, la dimensione delle miniature. Questo ci dà 0,2 come il rapporto. il che significa che la larghezza diventerà 90, quindi si dovrebbe ridursi a 100x90, e si verificherebbe alcuna distorsione.

Altri suggerimenti

Ecco un po 'di codice (C #) ho usato per fare un ridimensionamento, simile al metodo suggerito da blowdart. Basta sostituire i "300" s con la dimensione massima di un lato nel tuo caso:

 private Bitmap ScaleImage(Image oldImage)
    {
        double resizeFactor = 1;

        if (oldImage.Width > 300 || oldImage.Height > 300)
        {
            double widthFactor = Convert.ToDouble(oldImage.Width) / 300;
            double heightFactor = Convert.ToDouble(oldImage.Height) / 300;
            resizeFactor = Math.Max(widthFactor, heightFactor);

        }
        int width = Convert.ToInt32(oldImage.Width / resizeFactor);
        int height = Convert.ToInt32(oldImage.Height / resizeFactor);
        Bitmap newImage = new Bitmap(width, height);
        Graphics g = Graphics.FromImage(newImage);
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        g.DrawImage(oldImage, 0, 0, newImage.Width, newImage.Height);
        return newImage;
    }

O: Se desideri comunque dimensioni fisse, è seguire le istruzioni del blowdart ma calcolare il più grande rapporto di posto: 100px / 450px = .22 ..

  • width: 100px
  • Altezza: 111.11..px -> raccolto dal pavimento ((111,11-100) / 2) in alto e in basso 100px
  • .

Modifica :. O lasciare all'utente di selezionare come ritagliare la dimensione massima

ImageMagick . In caso di utilizzo della riga di comando:

convert -thumbnail geometry

Ho fatto questa funzione per PHP qualche tempo fa che funziona alla grande per questo e alcuni altri scenari:

<?php

function Image($source, $crop = null, $resize = null)
{
    $source = ImageCreateFromString(file_get_contents($source));

    if (is_resource($source) === true)
    {
        $width = imagesx($source);
        $height = imagesy($source);

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

            if (count($crop) == 2)
            {
                if (($width / $height) > ($crop[0] / $crop[1]))
                {
                    $width = $height * ($crop[0] / $crop[1]);
                    $crop = array((imagesx($source) - $width) / 2, 0);
                }

                else if (($width / $height) < ($crop[0] / $crop[1]))
                {
                    $height = $width / ($crop[0] / $crop[1]);
                    $crop = array(0, (imagesy($source) - $height) / 2);
                }
            }

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

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

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

            if (count($resize) >= 1)
            {
                if (empty($resize[0]) === true)
                {
                    $resize[0] = round($resize[1] * $width / $height);
                }

                else if (empty($resize[1]) === true)
                {
                    $resize[1] = round($resize[0] * $height / $width);
                }
            }

            else
            {
                $resize = array($width, $height);
            }
        }

        else
        {
            $resize = array($width, $height);
        }

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

        if (is_resource($result) === true)
        {
            ImageCopyResampled($result, $source, 0, 0, $crop[0], $crop[1], $resize[0], $resize[1], $width, $height);
            ImageDestroy($source);

            header('Content-Type: image/jpeg');

            ImageJPEG($result, null, 90);
            ImageDestroy($result);
        }
    }

    return false;
}

Image('/path/to/your/image.jpg', '1/1', '100*');
Image('/path/to/your/image.jpg', '1/1', '100*100');
Image('/path/to/your/image.jpg', '1/1', '100*500');

?>

Ecco un comando bash ho buttato insieme per raggiungere questo obiettivo utilizzando lo strumento convert di ImageMagick. Per una serie di immagini che si siedono nella directory genitore, qualche ritratto, qualche paesaggio, per creare immagini nella directory corrente scalata a 600x400, ritaglio immagini ritratto dal centro e semplicemente scalando le immagini del paesaggio:

for f in ../*jpg; do
    echo $f; 
    size=`identify $f|cut -d' ' -f 3`; 
    w=`echo $size|cut -dx -f 1`; 
    h=`echo $size|cut -dx -f 2`; 
    if [ $w -gt $h ]; then 
        convert $f -thumbnail 600x400 `basename $f`; 
    else 
        convert $f -scale 600x -crop 600x400+0+`echo "((600*($h/$w))/2)" | bc | sed 's/\..*//'` `basename $f`; 
    fi;
done;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top