Skip to content

Instantly share code, notes, and snippets.

@pisceanfoot
Created May 14, 2014 04:56
Show Gist options
  • Save pisceanfoot/4257818faefa5ade59a3 to your computer and use it in GitHub Desktop.
Save pisceanfoot/4257818faefa5ade59a3 to your computer and use it in GitHub Desktop.
GetNewSize - Thumbnail image
/// <summary>
/// </summary>
/// <remarks>
/// 原图路径
/// <add key="SourcePath" value="D:\Temp\Image\P800"/>
/// 压缩尺寸,多个尺寸“;”分隔
/// <add key="Destination" value="340*255"/>
/// <add key="Destination" value="340*255;640*480"/>
/// 保存路径,多个路径“;”分隔
/// <add key="NewSizePath" value="D:\Temp\Image\P340"/>
/// <add key="NewSizePath" value="D:\Temp\Image\P340;D:\Temp\Image\P640"/>
/// 压缩质量
/// <add key="Quality" value="90"/>
/// 是否强制转换,不计算等比
/// <add key="ForceDimension" value="false"/>
/// </remarks>
public class Thumbnail
{
#region Fields
private const string SourceFilePath = "product.txt";
private const string SourceFilePathPattern = "product_{0}.txt";
private string logFile;
private string logNotImage;
private long fileCount;
private long errorCount;
private double runtime;
private string sourcePath;
private bool sourceFromFile;
private List<ThumbnailInfo> thumbnailList;
private int quality;
private bool forceDimension;
#endregion
public Thumbnail()
{
runtime = 0d;
fileCount = 0L;
errorCount = 0L;
#region INIT
sourcePath = ConfigurationManager.AppSettings["SourcePath"];
if (string.IsNullOrEmpty(sourcePath))
{
throw new Exception("未配置 SourcePath");
}
if (!Directory.Exists(sourcePath))
{
throw new Exception("未知路径 SourcePath");
}
string tmpSourceFile = ConfigurationManager.AppSettings["SourceFile"];
bool.TryParse(tmpSourceFile, out sourceFromFile);
if (sourceFromFile)
{
if (!File.Exists(SourceFilePath))
{
throw new Exception("未知文件 product.txt");
}
}
sourcePath = sourcePath.Replace("/", "\\");
if (!sourcePath.EndsWith("\\"))
{
sourcePath += "\\";
}
string tmpDimension = ConfigurationManager.AppSettings["Dimension"];
string tmpNewSizePath = ConfigurationManager.AppSettings["NewSizePath"];
if (string.IsNullOrEmpty(tmpDimension) || string.IsNullOrEmpty(tmpNewSizePath))
{
throw new Exception("请检查配置文件 Dimension 和 NewSizePath");
}
string[] size = tmpDimension.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
string[] dir = tmpNewSizePath.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (dir.Length != size.Length)
{
throw new Exception("请检查配置文件 Dimension 和 NewSizePath");
}
thumbnailList = new List<ThumbnailInfo>();
for (int i = 0; i < dir.Length; i++)
{
string path = dir[i].Replace("/", "\\");
if (!path.EndsWith("\\"))
{
path += "\\";
}
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
thumbnailList.Add(new ThumbnailInfo(path, size[i]));
}
string tmpQuality = ConfigurationManager.AppSettings["quality"];
if (!string.IsNullOrEmpty(tmpQuality))
{
if (!int.TryParse(tmpQuality, out quality))
{
quality = 0;
}
}
string tmpForceDimension = ConfigurationManager.AppSettings["ForceDimension"];
bool.TryParse(tmpForceDimension, out this.forceDimension);
#endregion
logFile = string.Format("logError_{0}.log", DateTime.Now.ToString("yyyyMMddHHmmss"));
logNotImage = string.Format("logNotImage_{0}.log", DateTime.Now.ToString("yyyyMMddHHmmss"));
}
#region 公有属性
/// <summary>
/// 获取处理文件数量
/// </summary>
public long FileCount
{
get { return this.fileCount; }
}
/// <summary>
/// 获取出错次数
/// </summary>
public long ErrorCount
{
get { return this.errorCount; }
}
/// <summary>
/// 获取处理时间
/// </summary>
public double RunTime
{
get { return this.runtime; }
}
#endregion
#region 处理图片
public void Start()
{
DateTime start = DateTime.Now;
if (this.sourceFromFile)
{
GetProductFile(sourcePath);
}
else
{
GetFilesRecusive(sourcePath);
}
TimeSpan timespan = DateTime.Now - start;
runtime = timespan.TotalSeconds;
}
/// <summary>
/// 从产品ID文件中获取处理文件列表
/// </summary>
/// <param name="path"></param>
private void GetProductFile(string path)
{
Dictionary<string, string> histroyList = GetProductHistory();
string content = File.ReadAllText(SourceFilePath);
string[] array = content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
// 生成产品列表
foreach (string pic in array)
{
if (histroyList.ContainsKey(pic))
{
continue;
}
fileCount++;
string tmp;
string file = ConvertProductIdToDirectory(pic, out tmp);
file = Path.Combine(path, file);
file = file.Replace("/", "\\") + ".jpg";
string picPath = Path.Combine(path, tmp);
picPath = picPath.Replace("/", "\\");
if (!Directory.Exists(picPath))
{
continue;
}
string[] extFiles = Directory.GetFiles(picPath, pic + "*.jpg");
// n 张
if (extFiles.Length > 0)
{
foreach (string tmpExtFile in extFiles)
{
foreach (ThumbnailInfo info in thumbnailList)
{
DoThumnail(tmpExtFile, info);
}
}
}
}
// move to history
File.WriteAllText(string.Format(SourceFilePathPattern, historyCount), content);
}
private int historyCount = 0;
private Dictionary<string, string> GetProductHistory()
{
Dictionary<string, string> list = new Dictionary<string, string>();
do
{
string history = string.Format(SourceFilePathPattern, historyCount);
if (!File.Exists(history))
{
break;
}
historyCount++;
string content = File.ReadAllText(history);
string[] array = content.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tmp in array)
{
if (!list.ContainsKey(tmp))
{
list.Add(tmp.ToLower(), tmp);
}
}
}
while (true);
return list;
}
/// <summary>
/// 获取
/// </summary>
/// <param name="path"></param>
private void GetFilesRecusive(string path)
{
Dictionary<string, string> history = GetProductHistory();
Stack<string> stack = new Stack<string>();
stack.Push(path);
do
{
string tmppath = stack.Pop();
string[] files = Directory.GetFiles(tmppath);
foreach (string file in files)
{
fileCount++;
foreach (ThumbnailInfo info in thumbnailList)
{
string newFileAddress = Path.Combine(info.Path, file.Substring(sourcePath.Length));
if (File.Exists(newFileAddress))
{
continue;
}
DoThumnail(file, info);
}
}
string[] dirs = Directory.GetDirectories(tmppath);
foreach (string dir in dirs)
{
stack.Push(dir);
}
}
while (stack.Count > 0);
}
/// <summary>
/// 生成缩略图
/// </summary>
/// <param name="file"></param>
/// <param name="info"></param>
private void DoThumnail(string file, ThumbnailInfo info)
{
Graphics g = null;
Image img = null;
Image thumbnailImage = null;
try
{
if (File.Exists(file))
{
if (!IsImage(file))
{
File.AppendAllText(logNotImage, string.Format("{0}\r\n", file));
return;
}
img = Image.FromFile(file);
if (img.Width > info.Size.Width || img.Height > info.Size.Height)
{
int h = img.Height;
int w = img.Width;
if (this.forceDimension)
{
h = info.Size.Height;
w = info.Size.Width;
}
else
{
if (h > w)
{
h = info.Size.Height;
w = (int)(((float)img.Width / (float)img.Height) * info.Size.Height);
}
else
{
w = info.Size.Width;
h = (int)(((float)img.Height / (float)img.Width) * info.Size.Width);
}
}
thumbnailImage = new Bitmap(w, h);
g = Graphics.FromImage(thumbnailImage);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(img, new Rectangle(0, 0, w, h), new Rectangle(0, 0, img.Width, img.Height), GraphicsUnit.Pixel);
img.Dispose();
img = null;
img = thumbnailImage;
}
string newFileAddress = Path.Combine(info.Path, file.Substring(sourcePath.Length));
string dir = Path.GetDirectoryName(newFileAddress);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo encoder = null;
foreach (ImageCodecInfo info2 in imageEncoders)
{
if (info2.MimeType.IndexOf("jpeg") > -1)
{
encoder = info2;
}
}
// 保存图片质量
if ((quality < 0) || (quality > 100))
{
quality = 0;
}
if (quality != 0)
{
EncoderParameters encoderParams = new EncoderParameters();
long[] numArray2 = new long[1];
numArray2[0] = quality;
EncoderParameter parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, numArray2);
encoderParams.Param[0] = parameter;
if (encoder != null)
{
img.Save(newFileAddress, encoder, encoderParams);
}
else
{
img.Save(newFileAddress);
}
}
else
{
img.Save(newFileAddress);
}
}
}
catch
{
errorCount++;
File.AppendAllText(logFile, string.Format("\"{0}\" \"{1}\" \"{2}*{3}\"\r\n", DateTime.Now, file, info.Size.Width, info.Size.Height));
}
finally
{
if (img != null)
{
img.Dispose();
img = null;
}
if (thumbnailImage != null)
{
thumbnailImage.Dispose();
thumbnailImage = null;
}
if (g != null)
{
g.Dispose();
}
}
}
/// <summary>
/// 判断是否为图片文件
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private bool IsImage(string file)
{
string ext = Path.GetExtension(file).ToLower();
if (ext == ".gif" || ext == ".png" || ext == ".jpeg" || ext == ".jpg" || ext == ".bmp")
{
return true;
}
else
{
return false;
}
}
private class ThumbnailInfo
{
private string destPath;
private Size newSize;
public ThumbnailInfo(string path, string size)
{
this.destPath = path;
string[] newSizeInfo = size.Split(new char[]{'*'}, StringSplitOptions.RemoveEmptyEntries);
if (newSizeInfo.Length != 2)
{
throw new InvalidOperationException("错误的参数" + size);
}
this.newSize = new Size(int.Parse(newSizeInfo[0]), int.Parse(newSizeInfo[1]));
}
public string Path
{
get { return this.destPath; }
}
public Size Size
{
get { return this.newSize; }
}
}
#endregion
#region 产品图片链接生产
/// <summary>
/// 根据产品代号获取产品图片存在相对路径。
/// </summary>
/// <param name="productId">产品代号。</param>
/// <returns>产品图片存在相对路径。</returns>
private static string ConvertProductIdToDirectory(string productId, out string path)
{
path = string.Empty;
if (productId == null || productId.Trim().Length < 10)
return string.Empty;
productId = productId.Substring(0, 10);
string[] idPaths = productId.Split(new char[] { '-' });
if (idPaths.Length != 3)
return string.Empty;
path = string.Format("{0}/{1}", idPaths[0], idPaths[1]);
return string.Format("{0}/{1}/{2}", idPaths[0], idPaths[1], productId);
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment