using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;

namespace ynhtm.Common
{
    /// <summary>
    /// 缩放模式。
    /// </summary>
    public enum ImageThumbMode
    {
        /// <summary>
        /// 默认（按比例，可能出现空白）。
        /// </summary>
        None = 0,
        /// <summary>
        /// 自动（按比例，背景大小自动改变）。
        /// </summary>
        Auto,
        /// <summary>
        /// 拉伸（不按比例）。
        /// </summary>
        Pull,
        /// <summary>
        /// 剪切（按比例，可能会剪切图片）。
        /// </summary>
        Cut
    }

    /// <summary>
    // 图片处理。
    /// </summary>
    public static class Img
    {
        /// <summary>
        /// 缩略图。
        /// </summary>
        /// <param name="image">要缩略的图片</param>
        /// <param name="mode">缩放模式</param>
        /// <param name="autoSize">自动缩放地图</param>
        /// <param name="contentAlignment">对齐方式</param>
        /// <returns>返回已经缩放的图片。</returns>
        public static Image Thumb(Image img, Size size, ImageThumbMode mode, ContentAlignment contentAlignment)
        {
            //先取得比例。
            var imgWidth = (float)img.Width;
            var imgHeight = (float)img.Height;
            var scale = Math.Max(imgWidth / size.Width, imgHeight / size.Height);
            var newSize = new SizeF(img.Width / scale, img.Height / scale);
            if (newSize.Width > size.Width) newSize.Width = size.Width;
            if (newSize.Height > size.Height) newSize.Height = size.Height;
            Bitmap result = null;
            switch (mode)
            {
                case ImageThumbMode.None:
                    result = new Bitmap(size.Width, size.Height);
                    break;
                case ImageThumbMode.Pull:
                    newSize = size;
                    result = new Bitmap(size.Width, size.Height);
                    break;
                case ImageThumbMode.Cut:
                    newSize = img.Size;
                    if (img.Width > img.Height)
                    {
                        newSize.Height /= imgHeight / size.Height;
                        newSize.Width /= imgHeight / size.Height;
                    }
                    else
                    {
                        newSize.Width /= imgWidth / size.Width;
                        newSize.Height /= imgWidth / size.Width;
                    }
                    if (newSize.Width < size.Width)
                    {
                        newSize.Height *= size.Width / newSize.Width;
                        newSize.Width = size.Width;
                    }
                    if (newSize.Height < size.Height)
                    {
                        newSize.Width *= size.Height / newSize.Height;
                        newSize.Height = size.Height;
                    }
                    if (img.Width < size.Width)
                    {
                        size.Width = img.Width;
                        newSize.Width = img.Width;
                    }
                    if (img.Height < size.Height)
                    {
                        size.Height = img.Height;
                        newSize.Height = img.Height;
                    }
                    result = new Bitmap(size.Width, size.Height);
                    break;
                default:
                    result = new Bitmap((int)newSize.Width, (int)newSize.Height);
                    break;
            }

            using (var g = Graphics.FromImage(result))
            {
                g.FillRectangle(Brushes.White, new RectangleF(PointF.Empty, size));
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g.CompositingMode = CompositingMode.SourceOver;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                //对齐方式
                RectangleF destRect;
                switch (contentAlignment)
                {
                    case ContentAlignment.TopCenter:
                        destRect = new RectangleF(new PointF(-((newSize.Width - result.Width) / 2), 0), newSize);
                        break;
                    case ContentAlignment.TopRight:
                        destRect = new RectangleF(new PointF(-(newSize.Width - result.Width), 0), newSize);
                        break;
                    case ContentAlignment.MiddleLeft:
                        destRect = new RectangleF(new PointF(0, -((newSize.Height - result.Height) / 2)), newSize);
                        break;
                    case ContentAlignment.MiddleCenter:
                        destRect = new RectangleF(new PointF(-((newSize.Width - result.Width) / 2), -((newSize.Height - result.Height) / 2)), newSize);
                        break;
                    case ContentAlignment.MiddleRight:
                        destRect = new RectangleF(new PointF(-(newSize.Width - result.Width), -((newSize.Height - result.Height) / 2)), newSize);
                        break;
                    case ContentAlignment.BottomLeft:
                        destRect = new RectangleF(new PointF(0, -(newSize.Height - result.Height)), newSize);
                        break;
                    case ContentAlignment.BottomCenter:
                        destRect = new RectangleF(new PointF(-((newSize.Width - result.Width) / 2), -(newSize.Height - result.Height)), newSize);
                        break;
                    case ContentAlignment.BottomRight:
                        destRect = new RectangleF(new PointF(-(newSize.Width - result.Width), -(newSize.Height - result.Height)), newSize);
                        break;
                    default:
                        destRect = new RectangleF(PointF.Empty, newSize);
                        break;
                }
                g.DrawImage(img, destRect, new RectangleF(PointF.Empty, img.Size), GraphicsUnit.Pixel);
            }
            return result;
        }

        public static void Mask(this Image img, Image mask, ContentAlignment contentAlignment)
        {
            RectangleF rect;
            var imgSize = img.Size;
            var maskSize = mask.Size;
            using (var g = Graphics.FromImage(img))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                g.CompositingMode = CompositingMode.SourceOver;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
                switch (contentAlignment)
                {
                    case ContentAlignment.TopCenter:
                        rect = new RectangleF(new PointF((imgSize.Width - maskSize.Width) / 2, 0), maskSize);
                        break;
                    case ContentAlignment.TopRight:
                        rect = new RectangleF(new PointF(imgSize.Width - maskSize.Width, 0), maskSize);
                        break;
                    case ContentAlignment.MiddleLeft:
                        rect = new RectangleF(new PointF(0, (imgSize.Height - maskSize.Height) / 2), maskSize);
                        break;
                    case ContentAlignment.MiddleCenter:
                        rect = new RectangleF(new PointF((imgSize.Width - maskSize.Width) / 2, (imgSize.Height - maskSize.Height) / 2), maskSize);
                        break;
                    case ContentAlignment.MiddleRight:
                        rect = new RectangleF(new PointF(imgSize.Width - maskSize.Width, (imgSize.Height - maskSize.Height) / 2), maskSize);
                        break;
                    case ContentAlignment.BottomLeft:
                        rect = new RectangleF(new PointF(0, imgSize.Height - maskSize.Height), maskSize);
                        break;
                    case ContentAlignment.BottomCenter:
                        rect = new RectangleF(new PointF((imgSize.Width - maskSize.Width) / 2, imgSize.Height - maskSize.Height), maskSize);
                        break;
                    case ContentAlignment.BottomRight:
                        rect = new RectangleF(new PointF(imgSize.Width - maskSize.Width, imgSize.Height - maskSize.Height), maskSize);
                        break;
                    default:
                        rect = new RectangleF(PointF.Empty, maskSize);
                        break;
                }
                g.DrawImage(mask, rect);
            }
        }

        public static void SaveJpeg(this Image img, long quality, Stream stream)
        {
            var format = ImageFormat.Jpeg;
            ImageCodecInfo encoder = null;
            //得到解码、编码器
            foreach (var codecInfo in ImageCodecInfo.GetImageEncoders())
            {
                if (codecInfo.FormatID.Equals(format.Guid))
                {
                    encoder = codecInfo;
                    break;
                }
            }
            using (var encoderParams = new EncoderParameters(1))
            {
                using (var parameter = (encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality))) img.Save(stream, encoder, encoderParams);
            }
        }

        public static long SaveJpeg(this Image img, long quality, string filename)
        {
            using (var stream = File.OpenWrite(filename))
            {
                img.SaveJpeg(quality, stream);
                stream.Flush();
                return stream.Length;
            }
        }
    }
}