Criando miniaturas proporcionais

Walter Amorim (e-mail) é programador em ASP.net e VB.net desde 2003. Atualmente trabalha como Programador Web na agência AM4, em Barra Mansa/RJ. É cursando de Engenharia da Computação do Centro Universitário de Barra Mansa, unidade Cicuta (UBM-Cicuta).

Olá pessoal! Após algum tempo afastado do iMasters, estou voltando com um novo artigo, o qual espero que seja de ajuda à toda comunidade.

Pois bem. Veja a imagem abaixo, e imagine que ela tem 740px de altura e 1120px de altura:

image001.jpg

Agora, imagine o quanto tempo essa imagem irá demorar a carregar, principalmente se o usuário estiver usando linha discada.

Como desenvolvedores, devemos estar atentos à este fato, principalmente quando damos ao nosso cliente a opção de ele fazer o upload das fotos. O que devemos fazer é mostrar ao visitante uma imagem menor, que carregue mais rapidamente, e dar ao visitante a opção de ver a imagem em seu tamanho original.

Isso é importante, pois você não quer ter que tratar cada imagem que seu cliente fizer upload no site, e o visitante do site também não quer esperar uma imagem gigantesca carregar.

Muita gente já escreveu sobre como criar miniaturas (thumbnails) de imagens, principalmente em ASP.net. Mas o que também trago para vocês é uma forma de redimensionar a imagem de forma proporcional, isto é, mantendo a proporção entre altura e largura da imagem, evitando que ela fique distorcida.

Um código normal, sem esse ajuste, iria criar a miniatura assim:

image002.jpg

Iremos fazer com que a imagem fique assim:

image003.jpg

Para entender melhor o que estou dizendo, acesse o exemplo on-line. Ou faça o download completo aqui.

Então, vamos programar. O código completo está abaixo.

<script language="VB" runat="server">

'Se desejar, pode alterar o caminho onde a imagem é salva, e o tamanho mínimo e máximo da imagem.

    Private PastaOriginal As String = "imagens"               'Pasta onde está a imagem a ser redimensionada

    Private PastaMiniatura As String = "imagens\miniaturas"   'Pasta onde ficará a miniatura

    Private MaxLargura As Long = 50                          'Largura MÁXIMA da miniatura (em pixels)

    Private MaxAltura As Long = 50                           'Altura MÁXIMA da miniatura (em pixels)

Private Function GerarMiniatura(ByVal NomeArquivo As String) As Boolean

        'Gera a miniatura da imagem

        Try

            Response.Write("Detalhes da imagem")

            Dim CaminhoInicial As String = PastaOriginal & "\" & NomeArquivo

            Dim CaminhoFinal As String = PastaMiniatura & "\" & NomeArquivo

            'Objetos usados para criar a imagem

            Dim ImgOriginal As Drawing.Image = Drawing.Image.FromFile(Server.MapPath(CaminhoInicial))

            Dim ImgFinal As Drawing.Image

            Dim Graf As Graphics

            'Define o novo tamanho da imagem

            Dim dimensaoFinal As Size = NovoTamanho(ImgOriginal.Size, New Size(MaxLargura, MaxAltura))

            'Define o novo formato da imagem    

            Dim Formato As Drawing.Imaging.ImageFormat = ImgOriginal.RawFormat

            'Cria a nova imagem

            ImgFinal = New Bitmap(dimensaoFinal.Width, dimensaoFinal.Height)

            Graf = Graphics.FromImage(ImgFinal)

            'Opções relativas à qualidade da nova imagem

            Graf.CompositingQuality = Drawing2D.CompositingQuality.HighQuality

            Graf.SmoothingMode = Drawing2D.SmoothingMode.HighQuality

            Graf.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

            'Desenha a imagem no objeto gráfico oGraf

            Graf.DrawImage(ImgOriginal, New Rectangle(0, 0, dimensaoFinal.Width, dimensaoFinal.Height))

            'Fecha a imagem original e salva a imagem final           

            ImgOriginal.Dispose()

            ImgFinal.Save(Server.MapPath(CaminhoFinal), Formato)

            ImgFinal.Dispose()

            'Mostra a imagem original e a miniatura

            Response.Write("
Imagem '"
& CaminhoFinal.ToLower & "' salva com sucesso!

"
)

            panResultado.Visible = True

            img1.Src = CaminhoInicial

            img2.Src = CaminhoFinal

        Catch ex As Exception

            Response.Write("Não foi possível salvar a imagem!
Erro completo: "
& ex.ToString & "
"
)

            Return False

        End Try

    End Function

    Private Function NovoTamanho(ByVal Original As Size, ByVal Nova As Size) As Size

        'Define o melhor tamanho para a nova imagem, de acordo com a

        'proporção entre largura e altura da imagem original

        Dim ProporcaoOriginal As Decimal = ((Original.Height * 100) / Original.Width) / 100

        If ProporcaoOriginal > 1 Then

            ProporcaoOriginal = ((Original.Width * 100) / Original.Height) / 100

            NovoTamanho.Height = Nova.Height

            NovoTamanho.Width = Nova.Height * ProporcaoOriginal

        Else

            NovoTamanho.Width = Nova.Width

            NovoTamanho.Height = Nova.Width * ProporcaoOriginal

        End If                   

        Response.Write("

Tamanho original:  "
& Original.Width & "x" & Original.Height & "
"
)

        Response.Write("Novo Tamanho: " & NovoTamanho.Width & "x" & NovoTamanho.Height & "
"
)

    End Function

    Protected Sub cmdEnviar_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        'Faz o upload da foto               

        'Pega o nome do arquivo

        Dim NomeArquivo = arquivo.PostedFile.FileName.Substring(arquivo.PostedFile.FileName.LastIndexOf("\") + 1, arquivo.PostedFile.FileName.Length - arquivo.PostedFile.FileName.LastIndexOf("\") - 1)       

        arquivo.PostedFile.SaveAs(Server.MapPath("imagens/") & NomeArquivo)      

        'Gera a miniatura da foto

        GerarMiniatura(NomeArquivo)

    End Sub

SCRIPT>

<html><head><title>Walter Amorim - Upload e Redimensionamento de Imagens - iMasters.com.brtitle>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">head>

<body>

   <form runat="server">                 

        <asp:Panel id="panResultado" runat="server" Visible="False">

            <hr />Imagem Original: <br />

            <img id="img1" runat="server" /> <br /><br />Miniatura: <br />

            <img id="img2" runat="server" /><br /><br /><hr />

        asp:Panel>                       

        Escolha a imagem para criar a miniatura:<br />       

        <input id="arquivo" type="file" runat="server" />

        <asp:Button ID="cmdEnviar" runat="server" Text="Enviar" OnClick="cmdEnviar_Click" />

    form>

body>html>

As linhas que você provavelmente irá querer alterar estão em negrito, e irei explicá-las a seguir.

01. Tamanho da imagem

Logo no começo, declaramos 2 variáveis importantes:

Private MaxLargura As Long = 50                         
Private MaxAltura As Long = 50                          

Estas duas variáveis definem a largura e a altura da miniatura, em pixels.
Este é o tamanho máximo da imagem. Ou seja, isto não significa que a imagem realmente fique com este tamanho.

Por exemplo:

Se a imagem original tiver 100x200px, a proporção será de 2 (200÷100 = 0.5).
Ou seja, a altura será de 2 vezes a largura da imagem. Portanto, a imagem será de 50x25px.

Se a imagem original tiver 200x100px, a proporção será de 0.5 (100÷200 = 0.5). A imagem terá 25x50px.

Se a imagem original tiver 800x600, a proporção será de 0.75 (600÷800 = 0.75). A imagem terá 50x38px.

02. Formato da imagem

Também podemos definir o formato de saída da imagem. Procure a linha:
Dim Formato As Drawing.Imaging.ImageFormat = ImgOriginal.RawFormat

Nela, nós informamos o formato de imagem que irá ser criado. Neste caso, será o mesmo formato da imagem original (imgOriginal.RawFormat|). Mas você pode definir outros formatos.

É isso. Por hoje é só. Espero que o código possa ajudar a todos. Caso você tenha alguma dúvida, não hesite em escrever para meu e-mail. Abraço.