代码之家  ›  专栏  ›  技术社区  ›  user70192

动态写入图像

  •  3
  • user70192  · 技术社区  · 14 年前

    我有三个值正在我的Web表单后面的代码中动态生成。这三个值将显示给用户。虽然这听起来很奇怪,但我不希望用户能够复制和粘贴这些值。因此,我希望通过动态构建的图像写出值。

    我的问题是,有没有一种方法可以动态地创建一个图像并将其写在响应中?我不希望创建图像,将其保存到服务器,然后将URL传回页面。我真的很想写出二进制内容和响应。这有可能吗?如果有的话,有人能解释/演示一下怎么做吗?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Doug    14 年前

    在Simplist表单中,您可以使用 context.Response.BinaryWrite() 将字节数组写入响应流。通常,您可以从一个映射到特定mime类型的自定义HTTP处理程序调用它,例如*.jpg或*.png等。

    下面的代码块显示了一种创建简单capcha图像并将其作为字节数组返回的方法,该数组可由 context.response.binaryWrite()。

    private Byte[] GenerateImage()
    {
      RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
      Byte[] rand = new Byte[200];
      rng.GetBytes(rand);
      int i = 0;
    
      Bitmap bmp = new Bitmap(_imageWidth, _imageHeight, PixelFormat.Format24bppRgb);
      Bitmap cloneBmp = null;
      Graphics g = null;
      LinearGradientBrush backgroundBrush = null;
      LinearGradientBrush textBrush = null;
      SolidBrush[] circleBrush = new SolidBrush[3];
      Font font = null;
      GraphicsPath path = null;
    
      try
      {
        g = Graphics.FromImage(bmp);
        g.SmoothingMode = SmoothingMode.AntiAlias;
        Rectangle r = new Rectangle(0, 0, _imageWidth, _imageHeight);
        backgroundBrush = new LinearGradientBrush(
                new RectangleF(0, 0, _imageWidth, _imageHeight),
                Color.FromArgb(rand[i++] / 2 + 128, rand[i++] / 2 + 128, 255),
                Color.FromArgb(255, rand[i++] / 2 + 128, rand[i++] / 2 + 128),
                rand[i++] * 360 / 256);
        g.FillRectangle(backgroundBrush, r);
    
        for (int br = 0; br < circleBrush.Length; br++)
        {
          circleBrush[br] = new SolidBrush(Color.FromArgb(128, rand[i++], rand[i++], rand[i++]));
        }
    
        for (int circle = 0; circle < 30; circle++)
        {
          int radius = rand[i++] % 10;
          g.FillEllipse(circleBrush[circle % 2],
              rand[i++] * _imageWidth / 256,
              rand[i++] * _imageHeight / 256,
              radius, radius);
        }
    
        font = new Font("Tahoma", _imageHeight / 2, FontStyle.Regular);
        StringFormat format = new StringFormat();
        format.Alignment = StringAlignment.Center;
        format.LineAlignment = StringAlignment.Center;
    
        path = new GraphicsPath();
        path.AddString(_challengeKey, font.FontFamily, (int)font.Style, font.Size, r, format);
    
        textBrush = new LinearGradientBrush(
                new RectangleF(0, 0, _imageWidth, _imageHeight),
                Color.FromArgb(rand[i] % 128, rand[i] % 128, rand[i++] % 128),
                Color.FromArgb(rand[i] % 128, rand[i] % 128, rand[i++] % 128),
                rand[i++] * 360 / 256);
        g.FillPath(textBrush, path);
    
        cloneBmp = (Bitmap)bmp.Clone();
    
        int distortionSeed = rand[i++];
        double distortion = distortionSeed > 128 ? 5 + (distortionSeed - 128) % 5 : -5 - distortionSeed % 5;
        for (int y = 0; y < _imageHeight; y++)
        {
          for (int x = 0; x < _imageWidth; x++)
          {
            // Adds a simple wave
            int newX = (int)(x + (distortion * Math.Sin(Math.PI * y / 96.0)));
            int newY = (int)(y + (distortion * Math.Cos(Math.PI * x / 64.0)));
            if (newX < 0 || newX >= _imageWidth)
            {
              newX = 0;
            }
            if (newY < 0 || newY >= _imageHeight)
            {
              newY = 0;
            }
            bmp.SetPixel(x, y, cloneBmp.GetPixel(newX, newY));
          }
        }
    
        MemoryStream stream = new MemoryStream();
        bmp.Save(stream, ImageFormat.Jpeg);
        return stream.ToArray();
      }
      finally
      {
        if (backgroundBrush != null)
        {
          backgroundBrush.Dispose();
        }
        if (textBrush != null)
        {
          textBrush.Dispose();
        }
        for (int br = 0; br < circleBrush.Length; br++)
        {
          if (circleBrush[br] != null)
          {
            circleBrush[br].Dispose();
          }
        }
        if (font != null)
        {
          font.Dispose();
        }
        if (path != null)
        {
          path.Dispose();
        }
        if (g != null)
        {
          g.Dispose();
        }
        if (bmp != null)
        {
          bmp.Dispose();
        }
        if (cloneBmp != null)
        {
          cloneBmp.Dispose();
        }
      }
    }
    

    下面是您的HTTP处理程序的外观。请注意,这是非常基本的,可以完成任务,但不包括客户端或服务器端的任何图像缓存代码,您最终希望添加这些代码以提高性能。

     public class ImageHandler : IHttpHandler
      {
        public bool IsReusable
        {
          get
          {
            return true;
          }
        }
    
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = MimeTypeConstants.JPG;
            context.Response.Clear();
            context.Response.BinaryWrite(GenerateImage());
            context.Response.End();
        }
      }
    

    享受!

        2
  •  0
  •   lc.    14 年前

    至于与页面内联发送二进制内容,您可能希望了解使用 data URIs (维基百科页面上提到了利弊)。

        3
  •  0
  •   Ed B    14 年前

    是的,从文本创建图像非常容易:

    http://chiragrdarji.wordpress.com/2008/05/09/generate-image-from-text-using-c-or-convert-text-in-to-image-using-c/

    使用通用处理程序(.ashx)文件输出图像。 然后从页面链接到处理程序..它将显示为图像。