/// <summary>
        /// 为图片添加图片水印
        /// </summary>
        /// <param name="parameters">添加图片水印相关参数体</param>
        /// <param name="errorMsg">错误信息</param>
        /// <returns>已加水印的图片数据流</returns>
        public static MemoryStream DrawImage(ImageWatermarkParameters parameters, out string errorMsg)
        {
            errorMsg = string.Empty;

            try
            {
                // 参数检查
                if (!parameters.CheckAndSetDefault(out errorMsg))
                    throw new InvalidDataException(errorMsg);

                // 为源图片添加图片水印
                Bitmap finalImage = AddWatermarkImageForSourceImage(parameters, out errorMsg);
                if (finalImage == null && !string.IsNullOrEmpty(errorMsg))
                    throw new InvalidDataException("生成水印图片失败:" + errorMsg);

                // 获取Bitmap的MemoryStream
                return GetMemoryStreamFromBitmap(finalImage, parameters.SourceImageFileExtensionName);
            }
            catch (Exception ex)
            {
                errorMsg = ex.Message.ToString();
                return null;
            }
        }
        /// <summary>
        /// 获取源图片和水印图片的数据流
        /// </summary>
        /// <param name="parameters">参数实例</param>
        /// <param name="sourceImageStream">源图片数据流</param>
        /// <param name="waterImageStream">水印图片数据流</param>
        /// <param name="errorMsg">错误信息</param>
        /// <returns>是否获取成功</returns>
        private static bool GetSourceAndWatermarkImageStream(ImageWatermarkParameters parameters,
            out MemoryStream sourceImageStream, out MemoryStream waterImageStream, out string errorMsg)
        {
            errorMsg = string.Empty;

            // 根据是否设置图片路径来判断如何获取图片数据流,分别获取源图片和水印图片的数据流。
            string scErrMsg = string.Empty, wmErrMsg = string.Empty;
            sourceImageStream = parameters.SourceImageStream == null ?
                GetImageMemoryStream(parameters.SourceImagePath, out scErrMsg) : parameters.SourceImageStream;

            waterImageStream = parameters.WatermarkImageStream == null ?
                GetImageMemoryStream(parameters.WatermarkImagePath, out wmErrMsg) : parameters.WatermarkImageStream;

            if (!string.IsNullOrEmpty(scErrMsg) || !string.IsNullOrEmpty(wmErrMsg))
            {
                errorMsg = "通过图片路径获取数据流失败:" + scErrMsg + ";" + wmErrMsg;
                return false;
            }

            return true;
        }
        /// <summary>
        /// 为源图片添加图片水印
        /// </summary>
        /// <param name="parameters">参数集合</param>
        /// <param name="errMsg">错误消息</param>
        /// <returns>添加完水印的位图对象</returns>
        private static Bitmap AddWatermarkImageForSourceImage(ImageWatermarkParameters parameters, out string errMsg)
        {
            Image sourceImage = null;
            Bitmap sourceBitmap = null;
            Graphics sourceGraphics = null;
            Image watermarkImage = null;
            Graphics watermarkGraphics = null;
            errMsg = string.Empty;

            try
            {
                // 获取源图片和水印图片的数据流
                MemoryStream sourceImageStream, waterImageStream = null;
                if (GetSourceAndWatermarkImageStream(parameters, out sourceImageStream, out waterImageStream, out errMsg) == false)
                    throw new InvalidDataException(errMsg);

                sourceImage = Image.FromStream(sourceImageStream as Stream);
                // 实例化一个与源图大小一样、分辨率一致的位图对象,并将其载入Graphics对象中,以便后续编辑;
                // 需要根据图像的像素格式来判断是否需要重新绘制该图像
                sourceBitmap = (IsPixelFormatIndexed(sourceImage.PixelFormat)) ?
                    RedrawBitmapByImage(sourceImage) :
                    new Bitmap(sourceImage.Width, sourceImage.Height, sourceImage.PixelFormat);
                sourceBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                sourceGraphics = Graphics.FromImage(sourceBitmap);

                // SmoothingMode:指定是否将平滑处理(消除锯齿)应用于直线、曲线和已填充区域的边缘。
                // 成员名称 说明
                // AntiAlias 指定消除锯齿的呈现。
                // Default 指定不消除锯齿。
                // HighQuality 指定高质量、低速度呈现。
                // HighSpeed 指定高速度、低质量呈现。
                // Invalid 指定一个无效模式。
                // None 指定不消除锯齿。
                sourceGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                // 将源图像Image对象添加到绘图板中
                sourceGraphics.DrawImage(sourceImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
                                            0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel);

                //
                // 按照源图片的操作方式,需要创建水印图片的Image对象、位图对象,
                // 只是需要根据输入参数来调整水印图片在源图片中的位置、显示效果等。
                watermarkImage = new Bitmap(waterImageStream);
                // 这里尤其注意,生成新位图的时候,载入的是已经添加了源图片作为背景的位图哦!
                // 并将设定好分辨率的位图载入到新的Graphics实例中,以进一步绘制水印。
                Bitmap watermarkBitmap = new Bitmap(sourceBitmap);
                watermarkBitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                watermarkGraphics = Graphics.FromImage(watermarkBitmap);

                // 通过imageAttributes实例来设定水印图片的绘制效果,包括位置和现实效果等
                ImageAttributes imageAttributes = GetImageAttributesInstance(parameters.Alpha);
                // 获取水印图片的起始位置
                int xPosOfWm, yPosOfWm = 0;
                GetWatermarkImagePosition(parameters.WmPosition, sourceImage.Width, sourceImage.Height, watermarkImage.Width, watermarkImage.Height, out xPosOfWm, out yPosOfWm);
                // 绘制水印图片
                watermarkGraphics.DrawImage(watermarkImage, new Rectangle(xPosOfWm, yPosOfWm, watermarkImage.Width, watermarkImage.Height),
                                                0, 0, watermarkImage.Width, watermarkImage.Height, GraphicsUnit.Pixel, imageAttributes);

                return watermarkBitmap;
            }
            catch (Exception e)
            {
                errMsg = e.Message.ToString();
                return null;
            }
            finally
            {
                // 释放
                if (sourceImage != null)
                    sourceImage.Dispose();
                if (sourceBitmap != null)
                    sourceBitmap.Dispose();
                if (sourceGraphics != null)
                    sourceGraphics.Dispose();
                if (watermarkImage != null)
                    watermarkImage.Dispose();
                if (watermarkGraphics != null)
                    watermarkGraphics.Dispose();
            }
        }