2010-12-14 31 views
4

Quelqu'un connaît une version ASP.Net de la célèbre classe PHP "timthumb"? Juste besoin d'un script qui fonctionnera dans la même ligne de «timthumb» et produira des vignettes carrées ou basées sur le ratio avec une bonne qualité pour toutes les images de taille.asp.net version de timthumb php class

Voici le lien vers la classe php: http://www.darrenhoyt.com/2008/04/02/timthumb-php-script-released/

+0

Si ma réponse gagnante de bounty ne répond pas à vos besoins en quelque sorte faites le moi savoir et je peux probablement l'ajuster pour vos besoins. – Peter

+0

http://imageresizing.net a une syntaxe presque identique:? Width = x & height = y & quality = 0-100 –

Répondre

5

Je l'ai écrit juste pour vous :) ... Je l'ai testé en essayant tous les cas dans http://www.binarymoon.co.uk/demo/timthumb-basic/ et en le comparant visuellement côte à côte avec mon code. Autant que je sache, c'est fondamentalement identique. Cela dit, il ne supporte pas le drapeau 'zc'. Je l'ai écrit en tant que gestionnaire générique (fichier ashx) afin qu'il fonctionne plus rapidement. La mise en cache de l'imagerie est prise en charge, mais je l'ai commentée car elle rend les tests très difficiles. N'hésitez pas à le décommenter pour améliorer les performances à long terme (un bloc au début et un près de la fin lorsqu'il l'écrit dans le flux mémoire).

--- Code ---

<%@ WebHandler Language="VB" Class="Thumb" %> 

    Imports System 
    Imports System.Web 
    Imports System.Drawing 
    Imports System.IO 

    Public Class Thumb : Implements IHttpHandler 
     Private Shared _DefaultWidth As Integer = 100 
     Private Shared _DefaultHeight As Integer = 100 
     Private Shared _DefaultQuality As Integer = 90 

     Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest 
      ''check the cache for the image first 
      'Dim cacheObj As Object = context.Cache("Thumb-" + context.Request.Url.ToString().ToLower()) 
      'If cacheObj IsNot Nothing Then 
      ' Dim msCache As MemoryStream = DirectCast(cacheObj, MemoryStream) 

      ' WriteImage(msCache, context) 

      ' Exit Sub 
      'End If 

      'process request (since it wasn't in the cache) 
      Dim imgPath As String = context.Request.QueryString("src") 

      If String.IsNullOrEmpty(imgPath) Then 
       context.Response.End() 
      End If 

      'get image path on server 
      Dim serverPath As String = context.Server.MapPath(imgPath) 
      If Not File.Exists(serverPath) Then 
       context.Response.End() 
      End If 

      'load image from file path 
      Dim img As Image = Bitmap.FromFile(serverPath) 
      Dim origRatio As Double = (Math.Min(img.Width, img.Height)/Math.Max(img.Width, img.Height)) 

      '---Calculate thumbnail sizes--- 
      Dim destWidth As Integer = 0 
      Dim destHeight As Integer = 0 
      Dim destRatio As Double = 0 

      Dim qW As String = context.Request.QueryString("w") 
      Dim qH As String = context.Request.QueryString("h") 

      If Not String.IsNullOrEmpty(qW) Then 
       Int32.TryParse(qW, destWidth) 
       If destWidth < 0 Then 
        destWidth = 0 
       End If 
      End If 

      If Not String.IsNullOrEmpty(qH) Then 
       Int32.TryParse(qH, destHeight) 
       If destHeight < 0 Then 
        destHeight = 0 
       End If 
      End If 

      'if both width and height are 0 then use defaults (100x100) 
      If destWidth = 0 And destHeight = 0 Then 
       destWidth = _DefaultWidth 
       destHeight = _DefaultHeight 

       'else, if the width is specified, calculate an appropriate height 
      ElseIf destWidth > 0 And destHeight > 0 Then 
       'do nothing, we have both sizes already 
      ElseIf destWidth > 0 Then 
       destHeight = Math.Floor(img.Height * (destWidth/img.Width)) 
      ElseIf destHeight > 0 Then 
       destWidth = Math.Floor(img.Width * (destHeight/img.Height)) 
      End If 

      destRatio = (Math.Min(destWidth, destHeight)/Math.Max(destWidth, destHeight)) 

      'calculate source image sizes (rectangle) to get pixel data from   
      Dim sourceWidth As Integer = img.Width 
      Dim sourceHeight As Integer = img.Height 

      Dim sourceX As Integer = 0 
      Dim sourceY As Integer = 0 

      Dim cmpx As Integer = img.Width/destWidth 
      Dim cmpy As Integer = img.Height/destHeight 

      'selection is based on the smallest dimension 
      If cmpx > cmpy Then 
       sourceWidth = img.Width/cmpx * cmpy 
       sourceX = ((img.Width - (img.Width/cmpx * cmpy))/2) 
      ElseIf cmpy > cmpx Then 
       sourceHeight = img.Height/cmpy * cmpx 
       sourceY = ((img.Height - (img.Height/cmpy * cmpx))/2) 
      End If 

      '---create the new thumbnail image--- 
      Dim bmpThumb As New Bitmap(destWidth, destHeight) 
      Dim g = Graphics.FromImage(bmpThumb) 
      g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic 
      g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality 
      g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias 

      g.DrawImage(img, _ 
         New Rectangle(0, 0, destWidth, destHeight), _ 
         New Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel) 

      '-----write out Thumbnail to the output stream------   
      'get jpeg image coded info so we can use it when saving 
      Dim ici As Imaging.ImageCodecInfo = Imaging.ImageCodecInfo.GetImageEncoders().Where(Function(c) c.MimeType = "image/jpeg").First() 

      'save image to memory stream 
      Dim ms As New MemoryStream() 
      bmpThumb.Save(ms, ici, BuildQualityParams(context)) 

      ''save image to cache for future use 
      'context.Cache("Thumb-" + context.Request.Url.ToString().ToLower()) = ms 

      'write the image out 
      WriteImage(ms, context) 
     End Sub 

     Private Sub WriteImage(ByVal ms As MemoryStream, ByVal context As HttpContext) 
      'clear the response stream 
      context.Response.Clear() 

      'set output content type to jpeg 
      context.Response.ContentType = "image/jpeg" 

      'write memory stream out 
      ms.WriteTo(context.Response.OutputStream) 

      'flush the stream and end the response 
      context.Response.Flush() 
      context.Response.End() 
     End Sub 

     'for adjusting quality setting if needed, otherwise 90 will be used 
     Private Function BuildQualityParams(ByVal context As HttpContext) As Imaging.EncoderParameters 
      Dim epParams As New Imaging.EncoderParameters(1) 

      Dim q As Integer = _DefaultQuality 

      Dim strQ As String = context.Request.QueryString("q") 
      If Not String.IsNullOrEmpty(strQ) Then 
       Int32.TryParse(strQ, q) 
      End If 

      epParams.Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, q) 

      Return epParams 
     End Function 

     Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable 
      Get 
       Return False 
      End Get 
     End Property 
    End Class 

--- Test Cases ---

<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&q=100" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&q=10" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&w=200" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&h=150" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&h=180&w=120" /> 
<br /> 
<img alt="" src="Thumb.ashx?src=~/images/castle1.jpg&h=80&w=210" /> 
<br /> 
+0

grands merci, prime attribuée, bien que je n'ai pas encore eu le temps de tester moi-même ce code. – Blowsie

+0

Merci pour la confiance et la générosité :) – Peter

+1

Il y a quelques fuites de mémoire dans ce code ... Revue [l'image redimensionnant les pièges] (http://nathanaeljones.com/163/20-image-resizing-pitfalls/) et assurez-vous que vous les avez tous évités .. –

1

La bibliothèque http://imageresizing.net fait tout le script TimThumb fait et plus encore. C'est très facile à installer et entièrement pris en charge.

TimThumb: image.jpg w = 100 & h = 100 & q = 90

ImageResizing.Net: image.jpg width = 100 height = 100 & & qualité = 100

Si vous besoin d'imiter la syntaxe exacte de timthumb, faites le moi savoir et je peux vous donner quelques lignes de code qui vont le faire fonctionner.

4

@Peter je vous remercie pour votre code ci-dessus, il fonctionne parfaitement dans mon fichier ashx. Je suis un développeur asp.net C# donc j'ai converti votre code vb en C# et j'ai résolu certains problèmes que j'ai rencontrés.

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Data; 
using System.Diagnostics; 
using System.Web; 
using System.Drawing; 
using System.Drawing.Drawing2D; 
using System.Drawing.Imaging; 
using System.IO; 

namespace myProject.Handlers 
{ 
    public class Thumb : IHttpHandler 
    { 
     private static int _DefaultWidth = 100; 
     private static int _DefaultHeight = 100; 
     private static int _DefaultQuality = 90; 

     public void ProcessRequest(HttpContext context) 
     { 
      string imgPath = context.Request.QueryString["src"]; 

      if (string.IsNullOrEmpty(imgPath)) 
      { 
       context.Response.End(); 
      } 

      string serverPath = context.Server.MapPath(imgPath); 
      if (!File.Exists(serverPath)) 
      { 
       context.Response.End(); 
      } 

      Image img = Bitmap.FromFile(serverPath); 
      double origRatio = (Math.Min(img.Width, img.Height)/Math.Max(img.Width, img.Height)); 

      int destWidth = 0; 
      int destHeight = 0; 
      double destRatio = 0; 
      double dHeight = 0; 
      double dWidth = 0; 

      string qW = context.Request.QueryString["w"]; 
      string qH = context.Request.QueryString["h"]; 

      if (!string.IsNullOrEmpty(qW)) 
      { 
       Int32.TryParse(qW, out destWidth); 
       if (destWidth < 0) 
       { 
        destWidth = 0; 
       } 
      } 

      if (!string.IsNullOrEmpty(qH)) 
      { 
       Int32.TryParse(qH, out destHeight); 
       if (destHeight < 0) 
       { 
        destHeight = 0; 
       } 
      } 

      if (destWidth == 0 & destHeight == 0) 
      { 
       destWidth = _DefaultWidth; 
       destHeight = _DefaultHeight; 
      } 
      else if (destWidth > 0 & destHeight > 0) 
      { 
       //do nothing, we have both sizes already 
      } 
      else if (destWidth > 0) 
      { 
       dHeight = double.Parse(destWidth.ToString())/double.Parse(img.Width.ToString()); 
       destHeight = int.Parse(Math.Floor(img.Height * dHeight).ToString()); 
      } 
      else if (destHeight > 0) 
      { 
       dWidth = double.Parse(destHeight.ToString())/double.Parse(img.Height.ToString()); 
       destWidth = int.Parse(Math.Floor(img.Width * dWidth).ToString()); 
      } 

      destRatio = (Math.Min(destWidth, destHeight)/Math.Max(destWidth, destHeight)); 

      int sourceWidth = img.Width; 
      int sourceHeight = img.Height; 

      int sourceX = 0; 
      int sourceY = 0; 

      int cmpx = img.Width/destWidth; 
      int cmpy = img.Height/destHeight; 

      if (cmpx > cmpy) 
      { 
       sourceWidth = img.Width/cmpx * cmpy; 
       sourceX = ((img.Width - (img.Width/cmpx * cmpy))/2); 
      } 
      else if (cmpy > cmpx) 
      { 
       sourceHeight = img.Height/cmpy * cmpx; 
       sourceY = ((img.Height - (img.Height/cmpy * cmpx))/2); 
      } 

      Bitmap bmpThumb = new Bitmap(destWidth, destHeight); 
      Graphics g = Graphics.FromImage(bmpThumb); 
      g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      g.CompositingQuality = CompositingQuality.HighQuality; 
      g.SmoothingMode = SmoothingMode.AntiAlias; 

      g.DrawImage(img, new Rectangle(0, 0, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel); 

      ImageCodecInfo ici = ImageCodecInfo.GetImageEncoders().Where(c => c.MimeType == "image/jpeg").First(); 

      MemoryStream ms = new MemoryStream(); 
      bmpThumb.Save(ms, ici, BuildQualityParams(context)); 

      WriteImage(ms, context); 
     } 

     private void WriteImage(MemoryStream ms, HttpContext context) 
     { 
      context.Response.Clear(); 

      context.Response.ContentType = "image/jpeg"; 

      ms.WriteTo(context.Response.OutputStream); 

      context.Response.Flush(); 
      context.Response.End(); 
     } 

     private EncoderParameters BuildQualityParams(HttpContext context) 
     { 
      EncoderParameters epParams = new EncoderParameters(1); 

      int q = _DefaultQuality; 

      string strQ = context.Request.QueryString["q"]; 
      if (!string.IsNullOrEmpty(strQ)) 
      { 
       Int32.TryParse(strQ, out q); 
      } 

      epParams.Param[0] = new EncoderParameter(Encoder.Quality, q); 

      return epParams; 
     } 

     public bool IsReusable 
     { 
      get 
      { 
       return false; 
      } 
     } 
    } 
}