0

画像を取得してサイズを変更し、exif情報を保持して保存するメソッドがあります。私が今やりたいのは、透かしとして画像の上に透明なPNG画像をオーバーレイすることです。pngのサイズは、配置したいどの画像よりも常に大きくなります。透かしのアスペクト比を維持しながら、画像の中央に配置したいと思います。これが私がこれまでに持っているコードです:

private static void ResizeImage(Image theImage, int newSize, string savePath, IEnumerable<PropertyItem> propertyItems)
{
    int width;
    int height;
    CalculateNewRatio(theImage.Width, theImage.Height, newSize, out width, out height);
    using (var b = new Bitmap(width, height))
    {
        using (var g = Graphics.FromImage(b))
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            using(var a = Image.FromFile("Watermark.png"))
            {
                g.DrawImage();  //What to do here?
            }
            g.DrawImage(theImage, new Rectangle(0, 0, width, height));

            var qualityParam = new EncoderParameter(Encoder.Quality, 80L);
            var codecs = ImageCodecInfo.GetImageEncoders();
            var jpegCodec = codecs.FirstOrDefault(t => t.MimeType == "image/jpeg");
            var encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;
            foreach(var item in propertyItems)
            {
                b.SetPropertyItem(item);
            }
            b.Save(savePath, jpegCodec, encoderParams);
        }
    }
}
4

2 に答える 2

2

解決策を見つけました。コードは以下のとおりです。最適なコードではないかもしれませんが、高速で、ディレクトリ内のすべての JPG 画像を取得し、画像に透かしを重ねながら、フォト ギャラリーのフルおよびサム画像にサイズ変更する必要があることを実行します。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace ImageResize
{
    internal class Program
    {
        private static readonly string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        private static void Main()
        {
            var strFiles = Directory.GetFiles(directory, "*.jpg");

            //Using parallel processing for performance
            Parallel.ForEach(strFiles, strFile =>
                                           {
                                               using (var image = Image.FromFile(strFile, true))
                                               {
                                                   var exif = image.PropertyItems;
                                                   var b = directory + "\\" + Path.GetFileNameWithoutExtension(strFile);
                                                   ResizeImage(image, 800, b + "_FULL.jpg", exif);
                                                   ResizeImage(image, 200, b + "_THUMB.jpg", exif);
                                               }
                                               File.Delete(strFile);
                                           });
        }

        private static void ResizeImage(Image theImage, int newSize, string savePath, IEnumerable<PropertyItem> propertyItems)
        {
            try
            {
                int width;
                int height;
                CalculateNewRatio(theImage.Width, theImage.Height, newSize, out width, out height);
                using (var b = new Bitmap(width, height))
                {
                    using (var g = Graphics.FromImage(b))
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                        g.DrawImage(theImage, new Rectangle(0, 0, width, height));

                        //Using FileStream to avoid lock issues because of the parallel processing
                        using (var stream = new FileStream(directory + "\\Watermark.png", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        {
                            using (var overLay = Image.FromStream(stream))
                            {
                                stream.Close();
                                int newWidth;
                                int newHeight;
                                CalculateNewRatio(overLay.Width, overLay.Height, height > width ? width : newSize, out newWidth, out newHeight);
                                var x = (b.Width - newWidth) / 2;
                                var y = (b.Height - newHeight) / 2;
                                g.DrawImage(overLay, new Rectangle(x, y, newWidth, newHeight));
                            }
                        }

                        var qualityParam = new EncoderParameter(Encoder.Quality, 80L);
                        var codecs = ImageCodecInfo.GetImageEncoders();
                        var jpegCodec = codecs.FirstOrDefault(t => t.MimeType == "image/jpeg");
                        var encoderParams = new EncoderParameters(1);
                        encoderParams.Param[0] = qualityParam;
                        foreach (var item in propertyItems)
                        {
                            b.SetPropertyItem(item);
                        }
                        b.Save(savePath, jpegCodec, encoderParams);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        private static void CalculateNewRatio(int width, int height, int desiredSize, out int newWidth, out int newHeight)
        {
            if ((width >= height && width > desiredSize) || (width <= height && height > desiredSize))
            {
                if (width > height)
                {
                    newWidth = desiredSize;
                    newHeight = height*newWidth/width;
                }
                else if (width < height)
                {
                    newHeight = desiredSize;
                    newWidth = width*newHeight/height;
                }
                else
                {
                    newWidth = desiredSize;
                    newHeight = desiredSize;
                }
            }
            else
            {
                newWidth = width;
                newHeight = height;
            }
        }
    }
}
于 2012-12-10T16:36:23.923 に答える
0

縦横比を維持しながら最適なサイズになるようにキャンバスに画像を拡大縮小するプロセスは非常に簡単です。

double widthFactor = b.Width / a.Width;
double heightFactor = b.Height / a.Height;
double scaleFactor = Math.Min(widthFactor, heightFactor);
int newWidth = a.Width * scaleFactor;
int newHeight = a.Width * scaleFactor;

画像を中央に配置する位置を計算するには、もう少し計算が必要です。

int left = (b.Width - newWidth) / 2;
int top = (b.Height - newHeight) / 2;

次に、適切な形式の Graphics.DrawImage メソッドを使用します。

于 2012-12-07T22:36:18.773 に答える