Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

DrawImage e le Thumbnails quadrate

Una soluzione efficace per l'aspetto delle Thumbnails
Una soluzione efficace per l'aspetto delle Thumbnails
Link copiato negli appunti

Nelle gallerie fotografiche e ovunque sia necessario utilizzare delle thumbnails per ottenere in un colpo d'occhio, molte piccole anteprime delle immagini, possiamo incontrare problemi di aspetto.

I casi sono diversi: possiamo trovarci a gestire collezioni di immagini che non hanno tutte le stesse proporzioni, o più tipicamente, insiemi di foto orientate sia in orizzontale, sia in verticale.

Se ci limitiamo a produrre thumbnails tutte uguali, possiamo ottenere un effetto sgradevole dovuto alla perdita dell'aspect ratio. Possiamo pensare allora di rimpicciolire le immagini mantenendo le proporzioni iniziali ma l'effetto d'insieme potrebbe risultare troppo disomogeneo.

Figura 1. Effetti indesiderati
Effetti indesiderati

Le soluzioni sono diverse e spesso si ricorre a cornici omogenee, spesso quadrate, che rendono tutto più gradevole.

Con questo articolo utilizziamo una soluzione alternativa, che ben si applica alle foto, e che prevede di creare thumbnails quadrate ritagliate dalle figure originali. L'idea è quella di cercare il lato minore dell'immagine e di tagliarla utilizzando il quadrato costruito su quel lato.

Alle immagini orizzontali saranno tolte le parti laterali, e alle verticali saranno scorciate le parti superiore e inferiore.

Figura 2. Effetto desiderato
Effetto desiderato

Cerchiamo di risolvere questo problema e lo usiamo come spunto per approfondire la conoscenza con le librerie grafiche di ASP.NET.

Anzitutto pensiamo la soluzione concettualmente. La classe Graphics del namespace System.Drawing ci permette di generare una sorta di "tela" sulla quale posizionare elementi grafici tra cui forme (linee, rettangoli o ellissi), testi e immagini raster (o bitmap). Possiamo definire quindi una superficie grafica sulla quale applicare gli elementi fornendone le coordinate.

Figura 3. Sistema di coordinate
Sistema di coordinate

Un'istanza della classe Graphics si può ottenere a partire da una finestra Windows Form, ma è possibile generarla anche a partire da un oggetto Bitmap utilizzando il metodo statico FromImage().

In questo modo la tela assume le stesse dimensioni della bitmap e tutte le modifiche applicate alla tela saranno riportate sull'immagine.

Possiamo pensare quindi di iniziare creando la nostra thumbnail vuota come oggetto Bitmap con dimensioni quadrate. Fatto ciò generiamo l'oggetto Graphics (la "tela") e vi posizioniamo l'immagine.

Prima di piazzare l'immagine sulla tela dobbiamo averla già talgiata e ridimensionata. Vediamo come compiere tutte queste operazioni in un sol colpo.

Uno dei molti metodi DrawImage() della classe Graphics ci consente proprio di tagliare l'immagine e di ridimensionarla nello stesso passaggio. È importante però capire bene quali parametri sono necessari.

  • L'immagine iniziale. È semplicemente l'immagine di cui vogliamo ottenere la thumbnail.
  • Un rettangolo che serve per definire le dimensioni finali dell'immagine
  • Le coordinate in cui posizionare un rettangolo di ritaglio sull'immagine per ottenere che sia centrata. Si intendono le coordinate dell'angolo superiore-sinistro del rettangolo.
  • Le dimensioni del rettangolo di ritaglio (in questo caso un quadrato)
  • L'unità di misura delle dimensioni inserite (in questo caso il pixel)
Figura 4. Schema visuale dei parametri di DrawImage()
Schema visuale dei parametri di DrawImage()

Il motore grafico GDI+ adatta alle nuove dimensioni solo ciò che è contenuto nel rettangolo di ritaglio. Nel nostro caso utilizziamo un quadrato con lato pari al lato minore dell'immagine in input.

Per migliorare la qualità dell'adattamento possiamo indicare all'oggetto Graphics un algoritmo di interpolazione, impostando la proprietà InterpolationMode.

Come abbiamo visto in un articolo precedente possiamo aggiungere alla thumbnail un'immagine o una scritta come watermark, continuando a scrivere sulla tela con i metodi della classe Graphics.

Una volta elaborata l'immagine la inviamo sullo stream di output e il gioco è fatto.

Possiamo finalmente esaminare un esempio di codifica che realizza quanto abbiamo descritto. Il codice che mostriamo può essere ottimizzato, ma per l'esempio abbiamo preferito lasciarlo più leggibile.

<%@ Page Language="C#" %>
<%@ import Namespace="System.Drawing" %>

<script runat="server">

// contenitore dell'immagine in ingresso
System.Drawing.Image immagineIN;

void Page_Load(Object sender, EventArgs e) {

  // prende i dati dalla querystring
  int dimLato = Convert.ToInt32(Request.QueryString["lato"]);
  string strNomeFile = Request.QueryString["nomefile"];
  string strPercorsoImmagine = Server.MapPath(".") + "/https://static.html.it/app/uploads/documenti/articoli/2308/" + strNomeFile;

  try {
    // carica l'immagine di partenza
    immagineIN = System.Drawing.Image.FromFile(strPercorsoImmagine);

    // determina l'orientamento dell'immagine
    bool orizzontale = (immagineIN.Width > immagineIN.Height);

    // misura lato minore e maggiore
    int latoMinore = (orizzontale) ? immagineIN.Height : immagineIN.Width;
    int latoMaggiore = (orizzontale) ? immagineIN.Width : immagineIN.Height;

    // calcola le coordinate per centrare l'immagine nel rettangolo di taglio
    int posizione_centrale = latoMaggiore / 2 - latoMinore / 2;

    int posX = (orizzontale) ? posizione_centrale: 0;
    int posY = (orizzontale) ? 0: posizione_centrale;


    // crea un nuovo oggetto bitmap delle dimensioni della thumbnail
    // che useremo per ottenere la superficie grafica

    using (Bitmap bmThumb = new Bitmap(dimLato, dimLato, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
    {
      using (Graphics grTela = Graphics.FromImage(bmThumb))
      {
        // rettangolo per il ridimensionamento
        Rectangle rectDimensioniFinali = new Rectangle(0, 0, dimLato, dimLato);

        // Imposta un'interpolazione molto accurata (più lenta)
        grTela.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;

        // disegna l'immagine nella thumbnail
        grTela.DrawImage(immagineIN, rectDimensioniFinali, posX, posY, latoMinore, latoMinore, GraphicsUnit.Pixel);

        // indica al client che sta per ricevere un'immagine Jpeg
        Response.ContentType = "image/jpeg";
        bmThumb.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
      }
    }
    immagineIN.Dispose();
    immagineIN = null;
  }
  catch (Exception ex) {
    Response.Write(ex.Message);
  }
}
</script>

Le modalità di utilizzo possono essere diverse: possiamo richiamare il file così com'è, o realizzare un HttpHandler che gestisca tutte le chiamate ad un certo insieme di indirizzi.

Ti consigliamo anche