标题:一步步教你制作缩略图控件
只看楼主
铲铲
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:34
帖 子:506
专家分:0
注 册:2006-5-2
结帖率:100%
 问题点数:0 回复次数:15 
一步步教你制作缩略图控件
前言
所谓缩略图控件,就是能把一个指定的图片缩放成合适大小并显示在网页上。有人可能要问了,我通过设置img标记样式中的width和height属性就可以轻易把图片缩放到我需要的大小,何必要缩略图控件呢?是的,img样式固然可以强制调整图片显示的大小,但它不能改变图片从服务器到客户端下载的数据量,假如是一张巨型图片,那么等待图片在浏览器显示出来就足以让你崩溃,况且~~巨量数据的图片仅仅占据一小块网页位置,鉴于IE浏览器缩放图片的算法丑陋,看起来实在让人作呕,即浪费带宽又令人不满。因此有必要将图片处理一下,让他以最合适的大小,占据最合适的位置,不但数据量减少,且因为采用更精确的算法,图片质量有所提高。另外,假如你的图片拥有版权,你还可以在图片上面生成一些图案,表示版权,以免他人非法冒用。
这种好事何乐不为呢?

原理:
下面就要讲讲原理了~~
打开一张五彩斑斓的网页,你在看看它的源代码,你会发现,看不到那些五彩斑斓图片的真实数据,而是依靠img标记的src属性指向一个URL地址,在浏览一个网页时,浏览器除了要请求网页本身的URL,还要负责解析网页中img标记所指向的URL,下载这些图片,填充到网页指定位置,所以一次网页请求,实际上是对网页本身和其所指向的全部图片的请求。
上面是作网站的朋友最基本要明白的道理。那缩略图也一样,对于客户端来说,它本质就是一张图片,和其他图片毫无区别,在网页上不同位置显示,依靠网页上img标记所在的不同位置。Img标记指向一个地址,然后在这个地址上请求得到图片。
那有朋友要问,要实时产生缩略图,我如何知道这个缩略图的地址呢?我编程时又不知道,况且我也不可能指定一个地址,这样的话,程序就被箍住,死掉了,难以发挥全部水平。
这时候,我请朋友们放开思路,拓展思维,要知道,并不是要文件系统中真真实实存在的图片,我们才能够请求它,当然我们也可以“虚拟”出一个貌似图片的地址,然后对这个地址请求,虽然文件系统中不存在这个所谓地址,但是,要知道,我们的请求操作并非直接面对文件系统,而是要经过处理的,因此我们就有办法在中虚拟出一个地址,让浏览器乖乖地去请求它,然后我们又借助,在请求这个虚拟地址的时候,把图片发给浏览器,这样就大功告成了!

如果不能理解上述道理,麻烦多读几遍,呵呵。

工作模型上入手,寻求解决答案:
浏览器发出请求一个aspx后缀的网页,IIS收到请求后,根据后缀,就将该请求影射到请求入口,我们姑且称请求进入执行管道,请求在管道内流动,最后到达HttpFactory类,在这里,它将发现文件系统中存在的aspx页面,并找到bin目录下的dll中的对应Page派生类,将其作运行时编译并执行,形成要返回的数据流(也就是标准HTML代码了),经过管道,流出到IIS,最终发往客户端浏览器,客户端就看到被执行的网页了。

而一个aspx中,控件同样将被初始化执行,以便在控件所在位置生成HTML代码,最终获得一张HTML式的静态网页。假设这是个缩略图控件,我们就可以在控件所在位置输出img标记,并且能够在运行时动态构造img标记的src属性,有办法将src指定到一个缩略图地址上。

然而~~然而~~,朋友们有没有想过,难不成我还要真的在文件系统的某一个位置上生成了缩略图,让后构造src去请求?然后,朋友们再想想,这里有个巨大的难题确实几乎无法解决的:我们希望程序简单,总在一个固定位置生成缩略图文件,但访问服务器的每个客户,他们都有自己想要查看的图片,假如用户A请求了图片A,A图片所生成的缩略图还来不及发送,B用户就请求了B图片,这时,B图片在同一个位置生成,显然就覆盖了A图片,最后A用户获得的也只是B图片,明显,我们这样做显然没有考虑到每个用户会话之间的相互隔离。但文件系统几乎不能很好地解决这个问题,难啊,难。怎么办呢?
幸好!我们再把思维拓展开、再拓展开,想想看,我们总是习惯于请求aspx文件总是包含HTML代码,它是一个网页,那它可不可以是其他内容呢?行啊,没问题!历来就没有把aspx后缀和aspx文件的内容等同起来,这只是一种约定而已,你甚至可以把aspx文件修改为输出一个文本、一个应用程序、当然,还可以使一张图片。记住,是一张真正的图片(整个文件都是图片数据),而不是一个网页中包含的图片(网页中没有图片,只有标记,而是用标记去定位另外的图片地址)。

不知道朋友们能不能理解这一点。说专业一点,整个把用户的请求和响应当作流来看待,并且给你提供了操纵这些流的机会,你可以不必理会文件系统中是否存在真正要请求的东西,你可以在客户的请求到来,或者响应给客户之前,通过操纵流,向客户端发送你想发送的东西。

有了这些平台上的基础,我们就寻求到了如何方便、紧凑地生成缩略图给客户端的途径了。

接下来才真正讲到这个控件的实现原理:
实现原理:
1、    我们现在要做的是自定义Web控件,这和平常设计aspx网页或者用户控件有本质区别,自定义控件是一个派生自System.Web.WebControls.WebControl的类,它是一个类,而不是你想象中的HTML代码,甚至在自定义控件中你完全找不到HTMl的任何风格。因此,你必须对类的编写设计非常数量,或者是,跳出设计HTML的圈子,拓展思维!
2、    我们要实现不依靠文件系统、不依靠额外的任何其他东西,仅仅依靠一个类来实现它,这样做好处自然明显——各位只要复制得下面的一堆代码,自己建一个cs文件放进去就可以编译(编译为dll)。所有功能都是自含的,除了位于公共位置的.net类库,其他任何dll我都不需要引用。

然而,要实现如第2条这样的效果,我们得把对缩略图的请求设计成为对包含控件网页本身的请求,因为针对缩略图的这一次请求,本质仍然对本网页的请求,这样,网页中包含的缩略图控件才有机会操纵流。当然,两次请求都针对同一张网页的话,我们要设法区分开,哪一次是真正请求网页的原内容,哪一次是针对请求一个缩略图。
不知上述这段话大家能否理解,
如果不这样做的话,我们就不得不需要额外的控件或网页来实行了。

看懂了上述原理,我现在把流程写在下面,就自然好理解了:

1、    客户请求一张网页,如index.aspx,网页中含有缩略图控件,
2、    Index.aspx编译执行为HTML后被发送到客户端浏览器。这个控件生成了一个img标记,src属性指向一张该网页本身,但是后面附带的参数改变了。浏览器解析了,知道要向src属性获得一张图片。它开始向这个位置请求(也就是重新以新的附带参数请求这个网页)。
3、    获得了这个请求,index.aspx这个页面又开始执行,因为index.aspx中包含这个缩略图控件,控件就有机会识别这段特殊的参数,并且重新改写响应流,它会在文件系统中获得原始图像,然后根据你的要求,使用将原图重新按照新尺寸绘制,得到的新图是一个流对象,我们不存储它,而是将它直接附着在响应流中,发送给客户端。
4、    客户端浏览器得到这张图片。网页加载完成。

好,原理是说了不少,虽然我尽量写得通俗,但难免大家一时半会儿可能不好理解。那我现在就把代码贴出来让大家参考。
这个缩略图控件还没有添加水印等类似版权保护的功能,各位有兴趣的高手不妨完善一下这部分内容。同时与各位朋友相互学习,加强思考,增进思维。我们不管孰优孰劣,对于个人来说,既然追随,就要把用好,随波逐流的程序员永远不会优秀。
程序代码:
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using  System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Text;
using  BlogLan.Web.Controls
{
    /// <summary>
    /// 缩略图控件。
    /// </summary>
    [DefaultProperty("ImageUrl")]
    [ToolboxData("<{0}:Thumbnail runat=server></{0}:Thumbnail>")]
    [DesignerAttribute(typeof(Designer.ThumbnailDesigner))]
    [Description("缩略图控件。")]
    public class Thumbnail : WebControl
    {
        public Thumbnail()
            : base(HtmlTextWriterTag.Img)
        {
            this.Width = Unit.Parse("100");
            this.Height = Unit.Parse("75");
        }


        //Private Members
        private bool urlResolved;

        /// <summary>
        /// 获取或设置图片路径。
        /// </summary>
        [Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), Description("获取或设置图片路径"), Bindable(true), Category("Appearance"), DefaultValue(""), UrlProperty]
        public string ImageUrl
        {
            get
            {
                if (this.ViewState["ImageUrl"] != null)
                {
                    return (string)this.ViewState["ImageUrl"];
                }
                return string.Empty;
            }
            set
            {
                this.ViewState["ImageUrl"] = value;
            }
        }

        /// <summary>
        /// 获取或设置Jpeg缩略图的质量,值范围-100。
        /// </summary>
        [DefaultValue(80)]
        public int JpegQuality
        {
            get
            {
                if (this.ViewState["JpegQuility"] != null)
                {
                    return (int)this.ViewState["JpegQuility"];
                }
                return 80;
            }
            set
            {
                if (value > 100)
                {
                    this.ViewState["JpegQuility"] = 100;
                }
                else if (value < 20)
                {
                    this.ViewState["JpegQuility"] = 20;
                }
                else
                {
                    this.ViewState["JpegQuility"] = value;
                }
            }
        }

        [DefaultValue(typeof(Unit), "100px")]
        public override Unit Width
        {
            get
            {
                return base.Width;
            }
            set
            {
                base.Width = value;
            }
        }

        [DefaultValue(typeof(Unit), "75px")]
        public override Unit Height
        {
            get
            {
                return base.Height;
            }
            set
            {
                base.Height = value;
            }
        }

        internal bool UrlResolved
        {
            get
            {
                return this.urlResolved;
            }
            set
            {
                this.urlResolved = value;
            }
        }

        /// <summary>
        /// 获取或设置控件相对于网页上其他元素的对齐方式。
        /// </summary>
        [DefaultValue(ImageAlign.NotSet), Description("获取或设置控件相对于网页上其他元素的对齐方式。")]
        public virtual ImageAlign ImageAlign
        {
            get
            {
                object obj2 = this.ViewState["ImageAlign"];
                if (obj2 != null)
                {
                    return (ImageAlign)obj2;
                }
                return ImageAlign.NotSet;
            }
            set
            {
                if ((value < ImageAlign.NotSet) || (value > ImageAlign.TextTop))
                {
                    throw new ArgumentOutOfRangeException("value");
                }
                this.ViewState["ImageAlign"] = value;
            }
        }

        /// <summary>
        /// [禁用Enabled属性在任何位置编辑。]
        /// </summary>
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
        public override bool Enabled
        {
            get
            {
                return base.Enabled;
            }
            set
            {
                base.Enabled = value;
            }
        }

        /// <summary>
        /// 如无法显示图片时显示的替代文本。
        /// </summary>
        [DefaultValue(""), Bindable(true), Localizable(true), Description("如无法显示图片时显示的替代文本。")]
        public virtual string AlternateText
        {
            get
            {
                if (this.ViewState["AlternateText"] != null)
                {
                    return (string)this.ViewState["AlternateText"];
                }
                return string.Empty;
            }
            set
            {
                this.ViewState["AlternateText"] = value;
            }
        }

        /// <summary>
        /// 获取或设置一个值,该值指示控件是否生成空字符串值的替换文字属性。
        /// </summary>
        [DefaultValue(true), Description("获取或设置一个值,该值指示控件是否生成空字符串值的替换文字属性。")]
        public virtual bool GenerateEmptyAlternateText
        {
            get
            {
                if (this.ViewState["GenerateEmptyAlternateText"] != null)
                {
                    return (bool)this.ViewState["GenerateEmptyAlternateText"];
                }
                return true;
            }
            set
            {
                this.ViewState["GenerateEmptyAlternateText"] = value;
            }
        }

        /// <summary>
        /// 获取或设置图像详细说明的位置。
        /// </summary>
        [Editor("System.Web.UI.Design.UrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor)), UrlProperty, DefaultValue(""), Description("获取或设置图像详细说明的位置。")]
        public virtual string DescriptionUrl
        {
            get
            {
                string str = (string)this.ViewState["DescriptionUrl"];
                if (str != null)
                {
                    return str;
                }
                return string.Empty;
            }
            set
            {
                this.ViewState["DescriptionUrl"] = value;
            }
        }


        //Methods

        /// <summary>
        /// 重写AddAttributesToRender方法。
        /// </summary>
        /// <param name="writer"></param>
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            if (string.IsNullOrEmpty(this.Page.Request["thumbnail"]))
            {
                this.AddThumbnailAttributesToRender(writer, string.Empty);
            }
        }

        protected virtual internal void AddThumbnailAttributesToRender(HtmlTextWriter writer, string ForcedImageUrl)
        {
            base.AddAttributesToRender(writer);
            string imageUrl = this.ImageUrl;
            

            if (!this.UrlResolved)
            {
                imageUrl = base.ResolveClientUrl(imageUrl);
            }

            //在设计时强制赋予图形路径。
            if (!string.IsNullOrEmpty(ForcedImageUrl))
            {
                imageUrl = ForcedImageUrl;
                writer.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
            }
            else
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Src, this.Page.Request.Url.AbsolutePath + "?" + this.GetQueryString(), false);
            }

            

            imageUrl = this.DescriptionUrl;
            if (imageUrl.Length != 0)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Longdesc, base.ResolveClientUrl(imageUrl));
            }
            imageUrl = this.AlternateText;
            if ((imageUrl.Length > 0) || this.GenerateEmptyAlternateText)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Alt, imageUrl);
            }
            switch (this.ImageAlign)
            {
                case ImageAlign.Left:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "left");
                    break;

                case ImageAlign.Right:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");
                    break;

                case ImageAlign.Baseline:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "baseline");
                    break;

                case ImageAlign.Top:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "top");
                    break;

                case ImageAlign.Middle:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "middle");
                    break;

                case ImageAlign.Bottom:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "bottom");
                    break;

                case ImageAlign.AbsBottom:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "absbottom");
                    break;

                case ImageAlign.AbsMiddle:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "absmiddle");
                    break;

                case ImageAlign.NotSet:
                    break;

                default:
                    writer.AddAttribute(HtmlTextWriterAttribute.Align, "texttop");
                    break;
            }

            if (this.BorderWidth.IsEmpty)
            {
                writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0px");
            }
        }

        private string GetQueryString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("thumbnail=" + this.Page.Server.HtmlEncode(this.ImageUrl));
            sb.Append("&w=" + this.Width.Value.ToString());
            sb.Append("&h=" + this.Height.Value.ToString());
            sb.Append("&bc=" + this.BackColor.ToArgb().ToString());
            sb.Append("&jq=" + this.JpegQuality.ToString());

            return sb.ToString();
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
        }

        protected override ControlCollection CreateControlCollection()
        {
            return new EmptyControlCollection(this);
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            this.Init += new EventHandler(Thumbnail_Init);
            this.PreRender += new EventHandler(Thumbnail_PreRender);
        }

        void Thumbnail_PreRender(object sender, EventArgs e)
        {
            if (HttpContext.Current != null)
            {
                RenderThumbnailImage(this.Page.Request, this.Page.Response);
            }
        }

        void Thumbnail_Init(object sender, EventArgs e)
        {
            if (HttpContext.Current != null)
            {
                RenderThumbnailImage(this.Page.Request, this.Page.Response);
            }
        }

        static void RenderThumbnailImage(HttpRequest request, HttpResponse response)
        {
            if (string.IsNullOrEmpty(request["thumbnail"]))
            {
                return;
            }

            Thumbnail thumbnail = new Thumbnail();
            

            Bitmap tmb;
            try
            {
                thumbnail.ImageUrl = request["thumbnail"];

                try
                {
                    thumbnail.Width = Unit.Parse(request["w"]);
                }
                catch
                {
                    thumbnail.Width = Unit.Pixel(100);
                }

                try
                {
                    thumbnail.Height = Unit.Parse(request["h"]);
                }
                catch
                {
                    thumbnail.Height = Unit.Pixel(75);
                }
                try
                {
                    thumbnail.BackColor = Color.FromArgb(Convert.ToInt32(request["bc"]));
                }
                catch
                {
                    thumbnail.BackColor = Color.Black;
                }
                try
                {
                    thumbnail.JpegQuality = Convert.ToInt32(request["jq"]);
                }
                catch
                {
                    thumbnail.JpegQuality = 80;
                }

                tmb = thumbnail.GetThumbnail();
            }
            catch
            {
                tmb = Properties.Resources.GenerateImageError;
            }

            response.Clear();
            string[] ImageFilePart = thumbnail.ImageUrl.ToLower().Split('.');
            string Suffix = "bmp";
            if (ImageFilePart.Length > 1)
            {
                Suffix = ImageFilePart[ImageFilePart.Length - 1];
            }

            if (Suffix == "gif")
            {
                response.ContentType = "image/gif";
                tmb.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
            }
            else if (Suffix == "jpg" || Suffix == "jpeg")
            {
                response.ContentType = "image/jpeg";

                System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
                long[] quality = new long[] { Convert.ToInt64(thumbnail.JpegQuality) };
                System.Drawing.Imaging.EncoderParameter encoderParam = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
                encoderParams.Param[0] = encoderParam;
                System.Drawing.Imaging.ImageCodecInfo[] arrayICI = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
                System.Drawing.Imaging.ImageCodecInfo jpegICI = null;
                for (int fwd = 0; fwd < arrayICI.Length - 1; fwd++)
                {
                    if (arrayICI[fwd].FormatDescription.Equals("JPEG"))
                    {
                        jpegICI = arrayICI[fwd];
                        break;
                    }
                }

                if (jpegICI != null)
                {
                    tmb.Save(response.OutputStream, jpegICI, encoderParams);
                }
                else
                {
                    tmb.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                }


            }
            else
            {
                response.ContentType = "image/bmp";
                tmb.Save(response.OutputStream, System.Drawing.Imaging.ImageFormat.Bmp);
            }

            tmb.Dispose();

            response.Flush();
            
        }

        //

        public Bitmap GetThumbnail()
        {
            return this.GetThumbnail(this);
        }

        private Bitmap GetThumbnail(Thumbnail thumbnail)
        {
            if (thumbnail == null)
                return Properties.Resources.GenerateImageError;

            System.Drawing.Image OriginalImage;
            try
            {
                if (thumbnail.DesignMode)
                {
                    //string pagepath = thumbnail.MapPathSecure("/");
                    OriginalImage = (System.Drawing.Image)Properties.Resources.ThumbnailDesign;
                    
                }
                else
                {
                    OriginalImage = System.Drawing.Image.FromFile(thumbnail.Context.Server.MapPath(thumbnail.ImageUrl));
                }
            }
            catch
            {
                return Properties.Resources.GenerateImageError;
            }

            Size thumbnailNewSize = this.GetNewSize(Convert.ToInt32(thumbnail.Width.Value), Convert.ToInt32(thumbnail.Height.Value), OriginalImage.Width, OriginalImage.Height);

            Bitmap outbmp = new Bitmap(Convert.ToInt32(thumbnail.Width.Value), Convert.ToInt32(thumbnail.Height.Value));
            Graphics g = Graphics.FromImage(outbmp);
            try
            {
                 = CompositingQuality.HighQuality;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;

                g.Clear(thumbnail.BackColor);

                Rectangle _Vb_t_record_0 = new Rectangle((int)Math.Round((double)(((double)(thumbnail.Width.Value - thumbnailNewSize.Width)) / 2.0)), (int)Math.Round((double)(((double)(thumbnail.Height.Value - thumbnailNewSize.Height)) / 2.0)), thumbnailNewSize.Width, thumbnailNewSize.Height);
                g.DrawImage(OriginalImage, _Vb_t_record_0, 0, 0, OriginalImage.Width, OriginalImage.Height, GraphicsUnit.Pixel);
                g.Dispose();
            }
            catch
            {
                return Properties.Resources.GenerateImageError;
            }
            finally
            {
                g.Dispose();
                OriginalImage.Dispose();
            }

            return outbmp;

        }

        private Size GetNewSize(int maxWidth, int maxHeight, int width, int height)
        {
            double w = 0.0;
            double h = 0.0;
            double sw = Convert.ToDouble(width);
            double sh = Convert.ToDouble(height);
            double mw = Convert.ToDouble(maxWidth);
            double mh = Convert.ToDouble(maxHeight);
            if ((sw < mw) & (sh < mh))
            {
                w = sw;
                h = sh;
            }
            else if ((sw / sh) > (mw / mh))
            {
                w = maxWidth;
                h = (w * sh) / sw;
            }
            else
            {
                h = maxHeight;
                w = (h * sw) / sh;
            }
            return new Size(Convert.ToInt32(w), Convert.ToInt32(h));
        }



    }
}
搜索更多相关主题的帖子: 控件 缩略图 原理 
2008-11-02 23:20
青格儿
Rank: 4
等 级:贵宾
威 望:11
帖 子:698
专家分:20
注 册:2007-7-31
得分:0 
呵呵,版主辛苦了 。顶一下
2008-11-03 16:56
hebingbing
Rank: 6Rank: 6
来 自:黄土高坡
等 级:贵宾
威 望:27
帖 子:3417
专家分:371
注 册:2007-10-22
得分:0 
这样的帖子应该加精的&
2008-11-04 22:01
frankqnj
Rank: 4
等 级:贵宾
威 望:12
帖 子:320
专家分:278
注 册:2008-4-6
得分:0 
学习!
2008-11-06 04:07
雪雨星风
Rank: 1
来 自:北京
等 级:新手上路
威 望:1
帖 子:566
专家分:0
注 册:2007-10-11
得分:0 

C#发烧友QQ群1:5953354   QQ群2:68096127  QQ群3:30217249  QQ群4:37023079   为了更好方便大家交流学习,请不要重复加群
2008-11-06 09:49
铲铲
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:34
帖 子:506
专家分:0
注 册:2006-5-2
得分:0 
缩略图在现在网页中应该是比较常用的,我做过好几个网站,无一例外都用到缩略图来展示,比如,一个找吃的网站,我可以为每一道菜拍个照片,将原图上传至服务器,当在菜品列表中显示时,以100*75像素重新绘制,当点击该菜品,浏览详细菜品信息时,我们又可以以200*150像素绘制显示。重新绘制以后,图片多大就对应多大的数据量,而不是原图(可能有几个兆)的数据量。不依靠浏览器强制设定尺寸,那样会导致浏览器对图像重新插值,但浏览器的插值很垃圾,看起来像一堆马赛克。

铲铲是也
2008-11-06 11:27
_断肠人_
Rank: 1
等 级:新手上路
帖 子:85
专家分:0
注 册:2008-10-28
得分:0 

事在人为
2008-11-06 22:50
qiujm4614
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2008-11-12
得分:0 
UP UP UP ...
2008-11-13 18:56
闻启学
Rank: 2
来 自:宇宙
等 级:论坛游民
帖 子:82
专家分:44
注 册:2009-4-8
得分:0 
呵呵,版主辛苦了 。顶一
2010-01-02 11:46
blbikkk
Rank: 1
等 级:新手上路
帖 子:9
专家分:2
注 册:2010-3-1
得分:0 
随波逐流的程序员永远不会优秀~~~~呵呵,很喜欢这句话呢。写得太好了,真的
2010-03-09 17:32



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-242071-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.536035 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved