// NOTE: MinimumSize size is only specified when background is null so that ArgumentNullException may be thrown by this constructor
        // after the base constructor is finished.
        protected BackgroundVerificationCodeImage(Image background, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
            : base((background == null) ? MinimumSize : background.Size, textProvider, characterSet, maximumCharacters, minimumCharacters)
        {
            if (background == null)
                throw new ArgumentNullException("background");

            this.background = background;
        }
        public PartitionedVerificationCodeImage(Image background, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
            : base(background, textProvider, characterSet, maximumCharacters, minimumCharacters)
        {
            if (textProvider == null)
                throw new ArgumentNullException("textProvider");

            minFontSize = textProvider.MinimumFontSize;
            maxFontSize = textProvider.MaximumFontSize;
        }
        public LineNoiseVerificationCodeImage(Size size, VerificationCodeTextProvider textProvider, IEnumerable<Color> colors, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
            : base(size, textProvider, characterSet, maximumCharacters, minimumCharacters)
        {
            if (colors == null)
                this.colors = new List<Color>(1);
            else
                this.colors = new List<Color>(colors);

            if (this.colors.Count == 0)
                this.colors.Add(Color.Black);
        }
        /// <summary>
        /// 生成干扰图像
        /// </summary>
        /// <param name="name"></param>
        /// <param name="size"></param>
        /// <param name="textProvider"></param>
        /// <param name="characterSet"></param>
        /// <param name="maximumCharacters"></param>
        /// <param name="minimumCharacters"></param>
        /// <returns></returns>
        public override VerificationCodeImage GenerateAutoInputProtectionImage(string name, Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
        {
            LineNoiseVerificationCodeImage image = new LineNoiseVerificationCodeImage(size, textProvider, colors, characterSet, maximumCharacters, minimumCharacters);

            // code added after 1.0.0 RTW:
            if (Margin != -1)
                image.Margin = Margin;

            if (MinimumCharacterRotation != -1)
                image.MinimumCharacterRotation = MinimumCharacterRotation;

            if (MaximumCharacterRotation != -1)
                image.MaximumCharacterRotation = MaximumCharacterRotation;

            return image;
        }
        protected VerificationCodeImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
        {
            if (textProvider == null)
                throw new ArgumentNullException("textProvider");

            if (size.Width < MinimumSize.Width || size.Height < MinimumSize.Height)
                throw new ArgumentOutOfRangeException("size", size, "Errors.SizePositiveIntRequired");

            this.textProvider = textProvider;
            if (maximumCharacters.HasValue)
                this.textProvider.MaximumCharacters = maximumCharacters.Value;
            if (minimumCharacters.HasValue)
                this.textProvider.MinimumCharacters = minimumCharacters.Value;
            this.size = size;
            this.fonts = new List<Font>(textProvider.Fonts);
            this.textColors = new List<Color>(textProvider.Colors);
            this.characterSet = characterSet;
        }
 protected BackgroundVerificationCodeImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
     : base(size, textProvider, characterSet, maximumCharacters, minimumCharacters)
 {
 }
        private static void InitializeTextProviders(bool isHasSection, VerificationCodeSection section)
        {
            if (isHasSection)
            {
                ProvidersHelper.InstantiateProviders(section.TextProviders, TextProviderCollection,
                    typeof (VerificationCodeTextProvider));

                if (
                    section.DefaultTextProvider.Equals(
                        section.ElementInformation.Properties["defaultTextProvider"].DefaultValue))
                {
                    if (TextProviderCollection.Count > 0)
                        textProvider = TextProviderCollection[0];
                    else
                    {
                        textProvider =
                            new BasicEnglishVerificationCodeTextProvider(new[] {Color.Black, Color.Red, Color.Brown},
                                new[]
                                {
                                    new Font("Times New Roman", 1), new Font("Arial", 1),
                                    new Font("Microsoft Sans Serif", 1)
                                });
                    }

                }
                else
                {
                    textProvider = TextProviderCollection[section.DefaultTextProvider];
                }

                if (textProvider == null) throw new InvalidOperationException("验证码字符配置出错");
            }
            else if (textProvider == null)
            {
                section.TextProviders.Add(CreateProviderSettings(section.DefaultTextProvider,
                    typeof (BasicEnglishVerificationCodeTextProvider),
                    new KeyValuePair<string, string>("colors", "Red,Green,Blue,Brown"),
                    new KeyValuePair<string, string>("fonts", "Times New Roman, Arial, Microsoft Sans Serif")));
                ProvidersHelper.InstantiateProviders(section.TextProviders, TextProviderCollection,
                    typeof (VerificationCodeTextProvider));
                textProvider = TextProviderCollection[section.DefaultTextProvider];
            }
        }
 /// <summary>
 /// 生成图像
 /// </summary>
 /// <param name="size"></param>
 /// <param name="textProvider"></param>
 /// <param name="characterSet"></param>
 /// <param name="maximumCharacters"></param>
 /// <param name="minimumCharacters"></param>
 /// <returns></returns>
 public override VerificationCodeImage GenerateRandomAutoInputProtectionImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
 {
     return GenerateAutoInputProtectionImage(null, size, textProvider, characterSet, maximumCharacters, minimumCharacters);
 }
        /// <summary>
        /// Creates an instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="size"/>
        /// and <paramref name="textProvider"/>.
        /// </summary>
        /// <remarks>
        /// Derived types can override this method to return a type that either composites or derives from 
        /// <see cref="PartitionedAutoInputProtectionImage"/>.
        /// </remarks>
        /// <seealso cref="GenerateRandomAutoInputProtectionImage(Size,AutoInputProtectionTextProvider)"/>
        /// <param name="size">The dimensions of the image.</param>
        /// <param name="textProvider">The <see cref="AutoInputProtectionTextProvider"/> implementation that generates the text to be rendered.</param>
        /// <returns>An instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="size"/>
        /// and <paramref name="textProvider"/>.</returns>
        protected virtual PartitionedVerificationCodeImage GenerateImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
        {
            PartitionedVerificationCodeImage image = new PartitionedVerificationCodeImage(size, textProvider, characterSet, maximumCharacters, minimumCharacters);

            if (margin != -1)
                image.Margin = margin;

            if (minRotation != -1)
                image.MinimumCharacterRotation = minRotation;

            if (maxRotation != -1)
                image.MaximumCharacterRotation = maxRotation;

            return image;
        }
 /// <summary>
 /// When implemented by a derived type, creates an instance of a type that derives from <see cref="AutoInputProtectionImage"/>
 /// that generates an image of the specified <paramref name="size"/> using the specified <paramref name="textProvider"/>.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This overload is used by the <see cref="AutoInputProtectionControl"/> control.
 /// </para>
 /// <para>
 /// A derived type can call <see cref="GenerateImage(Size,AutoInputProtectionTextProvider)"/> to create an instance of 
 /// <see cref="PartitionedAutoInputProtectionImage"/>, which can then be returned to the caller immediately or it can be wrapped by a specialied class that 
 /// is returned instead.  Alternatively, a derived type may override <see cref="GenerateImage(Size,AutoInputProtectionTextProvider)"/> to create a custom 
 /// implementation that is then returned by this method as is.
 /// </para>
 /// </remarks>
 /// <seealso cref="AutoInputProtection.GenerateAutoInputProtectionImage"/>
 /// <seealso cref="GenerateAutoInputProtectionImage"/>
 /// <param name="size">The dimensions of the image.</param>
 /// <param name="textProvider"><see cref="AutoInputProtectionTextProvider"/> implementation to be used by the <see cref="AutoInputProtectionImage"/> implementation that is created.</param>
 /// <returns>An <see cref="AutoInputProtectionImage"/> implementation that can generate an image of the specified <paramref name="size"/> using the specified
 /// <paramref name="textProvider"/>.</returns>
 public abstract override VerificationCodeImage GenerateRandomAutoInputProtectionImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters);
 public LineNoiseVerificationCodeImage(Size size, VerificationCodeTextProvider textProvider, CaptchaCharacterSet characterSet, int? maximumCharacters, int? minimumCharacters)
     : base(size, textProvider, characterSet, maximumCharacters, minimumCharacters)
 {
     colors = new List<Color>(1);
     colors.Add(Color.Black);
 }
        /// <summary>
        /// 加载TextProvider
        /// </summary>
        /// <param name="configHasSection"></param>
        /// <param name="section"></param>
        private static void InitializeTextProviders(bool configHasSection, VerificationCodeSection section)
        {
            //加载TextProvider 如果webconfig中没有配置 则加载默认的BasicEnglishAutoInputProtectionTextProvider

            if (configHasSection)
            {
                if (!initializedTextProviders)
                {
                    ProvidersHelper.InstantiateProviders(section.TextProviders, textProviders, typeof(VerificationCodeTextProvider));
                    initializedTextProviders = true;
                }

                if (section.DefaultTextProvider.Equals(section.ElementInformation.Properties["defaultTextProvider"].DefaultValue))
                {
                    if (textProviders.Count > 0)
                        textProvider = textProviders[0];
                    else
                        textProvider = new BasicEnglishVerificationCodeTextProvider(
                            new[] { Color.Black, Color.Red, Color.Brown },
                            new[] { new Font("Times New Roman", 1), new Font("Arial", 1), new Font("Microsoft Sans Serif", 1) });
                }
                else
                    textProvider = textProviders[section.DefaultTextProvider];

                if (textProvider == null)
                    throw new InvalidOperationException("Errors.Config_Missing_TextProvider");
            }
            else if (textProvider == null)
            {
                section.TextProviders.Add(CreateProviderSettings(section.DefaultTextProvider, typeof(BasicEnglishVerificationCodeTextProvider),
                    new KeyValuePair<string, string>("colors", "Red,Green,Blue,Brown"),
                    new KeyValuePair<string, string>("fonts", "Times New Roman, Arial, Microsoft Sans Serif")));

                ProvidersHelper.InstantiateProviders(section.TextProviders, textProviders, typeof(VerificationCodeTextProvider));
                textProvider = textProviders[section.DefaultTextProvider];
            }
        }