2012-12-07 2 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