.NET System.Drawing differences in Windows Server 2008R2 64bit compared to all other windows (image is broken in 2008R2-64 but not other Windows)

吃可爱长大的小学妹 提交于 2019-12-25 03:52:47

问题


I have been given a development PC that has Windows Server 2008R2 64bit (x86) installed, so it is used as a workstation. My development environment is VS2008 targeting .NET3.5 (YES, 2008!!!)

In our website (which is a few years old now) there is a in-house developed Captcha.

To cut a long story short, the letters are not outputted on my dev machine 2008R2-64 but on all other windows (our test & live servers are 2003 64bit) and Virtual PC's (2008 32bit NOT R2, XP, Win7) they are.

I have seen some posts on the web that saying that the way pixels is measured might have changed (hard to find out for certain) but not much else.

Here is a small web-application to illustrate the problem.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Captcha1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Random _randomNumberGenerator = new Random();

            /* Output random string */
            float _xPosition = 20;
            float _xPositionMax = 0;
            float _yPosition = 0;
            float _yPositionMax = 0;
            string strRandom = string.Empty;

            /* Prepare drawing functions to output */
            System.Drawing.Bitmap objBmp = new System.Drawing.Bitmap(500, 200);
            System.Drawing.Graphics objGraphics = System.Drawing.Graphics.FromImage(objBmp);
            objGraphics.Clear(System.Drawing.Color.AliceBlue);
            objGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

            string[] strFont = new string[] { "Arial" };
            string[] strArray = new string[] { "a", "b", "c", "d", "e" };
            strRandom = "AAAAAA";//these are the characters for the captcha. In normal circumstances it would be random!

            /* Render the image */
            int _rotate = -1;
            objGraphics.RotateTransform(3);
            foreach (char _char in strRandom.ToCharArray())
            {
                /* Rotate the image */
                objGraphics.RotateTransform((float)(_rotate * 5));
                _rotate = (_rotate == 1) ? -1 : 1;

                /* Generate random y position */
                _yPosition = Convert.ToInt32(_randomNumberGenerator.Next(15, 20));

                /* Select random font */
                System.Drawing.Font objFont = new System.Drawing.Font("Arial", 22, System.Drawing.FontStyle.Bold);

                /* Output the next character */
                objGraphics.DrawString(_char.ToString(), objFont, System.Drawing.Brushes.Black, _xPosition, _yPosition);

                /* Get the width of the string added */
                System.Drawing.SizeF _stringSize = objGraphics.MeasureString(_char.ToString(), objFont);

                /* Dispose of the font */
                objFont.Dispose();

                /* Output the next character */
                objGraphics.DrawImage(objBmp, _xPosition, _yPosition);

                /* Increment x position */
                _xPosition = _xPosition + (_stringSize.Width * (float)0.8);

                /* Get bounding area */
                _xPositionMax = _xPosition;
                _yPositionMax = (int)(_yPosition + _stringSize.Height);
            }
            _xPositionMax += 20;
            _yPositionMax += 15;

            System.Drawing.Bitmap objBmpFinal = new System.Drawing.Bitmap((int)_xPositionMax, (int)_yPositionMax);
            System.Drawing.Graphics objGraphicsFinal = System.Drawing.Graphics.FromImage(objBmpFinal);
            System.Drawing.Rectangle _rectDest = new System.Drawing.Rectangle(0, 0, (int)_xPositionMax, (int)_yPositionMax);
            objGraphicsFinal.DrawImageUnscaledAndClipped(objBmp, _rectDest);

            /* Draw a curve over the image */
            float _yPositionMaxCurve = _yPositionMax - 20;
            System.Drawing.Pen _penCurve = new System.Drawing.Pen(System.Drawing.Color.Black, 2);
            objGraphicsFinal.DrawBezier(_penCurve,
                _randomNumberGenerator.Next(5, 10), _randomNumberGenerator.Next(5, (int)_yPositionMaxCurve),
                _randomNumberGenerator.Next((int)(_xPositionMax / 6), (int)(_xPositionMax / 5)), _randomNumberGenerator.Next((int)(_yPositionMaxCurve / 2), (int)_yPositionMaxCurve),              // y2
                _randomNumberGenerator.Next((int)(_xPositionMax / 4), (int)(_xPositionMax / 3)), _randomNumberGenerator.Next(5, (int)_yPositionMaxCurve),                             // y3
                _randomNumberGenerator.Next((int)(_xPositionMax - 5), (int)_xPositionMax), _randomNumberGenerator.Next(5, (int)_yPositionMaxCurve));                            // y4
            _penCurve.Dispose();

            /* Draw diagonal lines */
            System.Drawing.Pen _penHatch = new System.Drawing.Pen(System.Drawing.Color.Black, 1);
            for (int _i = -100; _i < _xPositionMax; _i += ((int)_xPositionMax / 8))
            {
                float _bottomPos = ((float)Math.Tan((Math.PI * 45 / 180.0)) * _yPositionMax);
                objGraphicsFinal.DrawLine(_penHatch, _i, 0, _bottomPos + _i, _yPositionMax);
            }
            for (int _i = 0; _i < (_xPositionMax + 100); _i += ((int)_xPositionMax / 8))
            {
                float _bottomPos = ((float)Math.Tan((Math.PI * 45 / 180.0)) * _yPositionMax);
                objGraphicsFinal.DrawLine(_penHatch, _i, 0, ((-_bottomPos) + _i), _yPositionMax);
            }
            _penHatch.Dispose();

            /* Draw bounding rectangle */
            System.Drawing.Pen _penBorder = new System.Drawing.Pen(System.Drawing.Color.Black, 1);
            objGraphicsFinal.DrawRectangle(_penBorder, 0, 0, (int)(_xPositionMax - 1), (int)(_yPositionMax - 1));
            _penBorder.Dispose();

            /* Draw random speckles */
            for (int _speckle = 0; _speckle < 100; _speckle++)
            {
                /* Generate a random colour */
                System.Drawing.Color _speckleColor = System.Drawing.Color.FromArgb((byte)_randomNumberGenerator.Next(0, 255), (byte)_randomNumberGenerator.Next(0, 255), (byte)_randomNumberGenerator.Next(0, 255));

                /* Create a brush */
                System.Drawing.SolidBrush _speckleBrush = new System.Drawing.SolidBrush(_speckleColor);

                /* Select random font */
                System.Drawing.Font _speckleFont = new System.Drawing.Font(strFont[_randomNumberGenerator.Next(0, (strFont.Length - 1))], _randomNumberGenerator.Next(2, 6), System.Drawing.FontStyle.Regular);

                /* Get speckle character */
                int i = Convert.ToInt32(_randomNumberGenerator.Next(0, (strArray.Length - 1)));
                string _speckleCharacter = strArray[i].ToString();

                /* Draw speckle */
                objGraphicsFinal.DrawString(_speckleCharacter, _speckleFont, _speckleBrush, _randomNumberGenerator.Next(0, (int)_xPositionMax), _randomNumberGenerator.Next(0, (int)_yPositionMax));

                /* Dispose of objects */
                _speckleBrush.Dispose();
                _speckleFont.Dispose();
            }

            /* Output the image */
            Response.ContentType = "image/GIF";
            objBmpFinal.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);

            objGraphics.Dispose();
            objGraphicsFinal.Dispose();

            objBmpFinal.Dispose();
            objBmp.Dispose();

            /* End the response */
            Response.End();
        }
    }
}

and here are some images showing what it should look like and what it looks like on Win 2008R2 64.

How it should look:

Not Working!!!!

I have only just got this PC so it's possible that some of the "roles" are not switched on (ASP.NET, .NET3.5, Static Content are all ticked).

Anyone got any bright ideas?


回答1:


You need to divide and conquer this problem. The way to do this is to start eliminating the things that aren't affecting your output (background items). Then eliminate the random elements (you could seed your generator so that it gives you the same results), or use constants. When you can get it down to "when I have this line in I get no text, but when I take it out, I have text" you have located the cause.

It's fun to mung around with the captcha, but you've done it in a way that makes it very hard to debug and verify. This type of code should be unit tested and made unit testable so that given a particular starting seed you get consistent output everywhere.

In our environment, we have issues now and again where fonts don't render pixel-identical because one test server has one version of the font and another doesn't. I don't see that as your issue.



来源:https://stackoverflow.com/questions/15526124/net-system-drawing-differences-in-windows-server-2008r2-64bit-compared-to-all-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!