2012-12-07 32 views
0

我有一種方法可以拍攝圖像並調整大小並保存exif信息。我現在想要做的是在圖像頂部疊加一個透明的PNG圖像作爲水印。 png的大小將總是比我想要放置的任何圖像都大。我想將它居中放置在保留水印寬高比的圖像上。下面是代碼,因爲我有它到目前爲止:以JPG文件爲中心的重疊水印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); 
     } 
    } 
} 
+0

我編輯了你的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

回答

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; 
      } 
     } 
    } 
} 
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; 

爲了計算將圖像居中的位置只需要更多的數學運算:

然後使用Graphics.DrawImage方法的適當形式。

+0

謝謝,我知道如何調整圖像大小,我正在尋找如何將調整大小後的圖像置於其他圖像上。我的CalculateNewRatio方法(不包括)做了一些非常相似的事情。 – Cyberdrew

+0

既然您已經掌握了定位和規模,那麼您仍需要哪些部分的幫助?它是否正在處理您遇到麻煩的水印透明度? – JamieSee

+0

我想通了,會發布解決方案。 int newWidth和int newHeight由於將double轉換爲int而引發編譯時錯誤。即便是固定後,利用公式圖像仍然粉碎有點因此不能保持它的縱橫比。 – Cyberdrew