开发者

How can I resize an image from a database in C#, in good quality

I have the following C# code (not mine) which pulls an image out of a database and displays it on a web page:

public partial class Image : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        getFullImage();
    }



    public void getFullImage()
    {
        SqlConnection objCon = new SqlConnection();
        objCon = new SqlConnection(Globals.ConnectionString);
        objCon.Open();

        String TmpStr;
        try
        {

            byte[] imgData = null;

            SqlCommand objCmd = new SqlCommand("Select * from Login where user_Name='" + Request["Id"].ToString() + "'", objCon);
            SqlDataReader reader = objCmd.ExecuteReader();


            while (reader.Read())
            {
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.AddHeader("Content-Disposition",
                    "attachment; filename=" + reader["ImageName"]);
                imgData = (byte[])reader[开发者_运维百科"ImageFile"];
                TmpStr = reader["ImageFile"].ToString();
                TmpStr = TmpStr.Substring(1, TmpStr.Length - 1);
            }
            HttpContext.Current.Response.ContentType = "image/jpeg";
            HttpContext.Current.Response.BinaryWrite(imgData);
        }
        catch(Exception ex)
        {
            Response.Write(ex.Message.ToString());
        }
        finally
        {

        }
    }
}

I know it's probably really bad practice to store images in a database and use them in this way, but I'm not a hardcore .NET dev and can't rewrite this whole thing (much as I'd love to be able to!).

Anyhow, currently the method above creates full size (often huge) images, which are then resized using CSS, which causes them to degrade terribly in quality. I wondered if there was anything I could do to resize the image prior to render, so improve quality and reduce load time?

Thanks for any pointers folks...


Here are some good links/suggestions to high quality resizing of the images:

High Quality Image Scaling Library


I've been using this function whenever I needed to resize a bitmap... didn't write this code and don't even remember where I got it from... give it a try

public static Bitmap ResizePhoto(Bitmap b, int nWidth, int nHeight)
{
    Bitmap bTemp = (Bitmap)b.Clone();
    b = new Bitmap(nWidth, nHeight, bTemp.PixelFormat);

    double nXFactor = (double)bTemp.Width / (double)nWidth;
    double nYFactor = (double)bTemp.Height / (double)nHeight;


    double fraction_x, fraction_y, one_minus_x, one_minus_y;
    int ceil_x, ceil_y, floor_x, floor_y;
    Color c1 = new Color();
    Color c2 = new Color();
    Color c3 = new Color();
    Color c4 = new Color();
    byte red, green, blue;

    byte b1, b2;

    for (int x = 0; x < b.Width; ++x)
        for (int y = 0; y < b.Height; ++y)
        {
            floor_x = (int)Math.Floor(x * nXFactor);
            floor_y = (int)Math.Floor(y * nYFactor);
            ceil_x = floor_x + 1;
            if (ceil_x >= bTemp.Width) ceil_x = floor_x;
            ceil_y = floor_y + 1;
            if (ceil_y >= bTemp.Height) ceil_y = floor_y;
            fraction_x = x * nXFactor - floor_x;
            fraction_y = y * nYFactor - floor_y;
            one_minus_x = 1.0 - fraction_x;
            one_minus_y = 1.0 - fraction_y;

            c1 = bTemp.GetPixel(floor_x, floor_y);
            c2 = bTemp.GetPixel(ceil_x, floor_y);
            c3 = bTemp.GetPixel(floor_x, ceil_y);
            c4 = bTemp.GetPixel(ceil_x, ceil_y);

            // Blue

            b1 = (byte)(one_minus_x * c1.B + fraction_x * c2.B);

            b2 = (byte)(one_minus_x * c3.B + fraction_x * c4.B);

            blue = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            // Green

            b1 = (byte)(one_minus_x * c1.G + fraction_x * c2.G);

            b2 = (byte)(one_minus_x * c3.G + fraction_x * c4.G);

            green = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            // Red

            b1 = (byte)(one_minus_x * c1.R + fraction_x * c2.R);

            b2 = (byte)(one_minus_x * c3.R + fraction_x * c4.R);

            red = (byte)(one_minus_y * (double)(b1) + fraction_y * (double)(b2));

            b.SetPixel(x, y, Color.FromArgb(255, red, green, blue));
        }

    return b;
}


I use something like this:

    using (Graphics g = Graphics.FromImage(targetImage)) 
    { 
        g.DrawImage(myImage, 0, 0, Width, Height); 
    } 

You may need to play around with CompositingQuality, InterpolationMode and SmoothingMode to get the best results for you specific images.


You may use the Image class with the GetThumbnailImage method from the namespace System.Drawing.Imaging. Regarding load time there are two large parts: Transmitting the image and loading the image from database. Maybe just store a reference to a file and then use that might be on alternative.

Edit: Scaling down almost always leads to some decease in quality. Maybe the GetThumbnailImage is better as it may use embedded thumbnail data, but don't expect the same quality than from professional grade algorithms like the ones used in Photoshop.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜