Advertisement
Guest User

Untitled

a guest
Jan 20th, 2012
2,555
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.70 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Windows.Forms;
  6. using System.Text;
  7.  
  8. namespace img4skype
  9. {
  10.     public partial class Form1 : Form
  11.     {
  12.         private Bitmap _src;
  13.  
  14.         public Form1()
  15.         {
  16.             InitializeComponent();
  17.         }
  18.  
  19.         public static Bitmap ResizeImage(Image image, int width, int height)
  20.         {
  21.             var result = new Bitmap(width, height);
  22.  
  23.             using (var graphics = Graphics.FromImage(result))
  24.             {
  25.                 graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
  26.                 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  27.                 graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  28.  
  29.                 graphics.DrawImage(image, 0, 0, result.Width, result.Height);
  30.             }
  31.  
  32.             return result;
  33.         }
  34.  
  35.  
  36.         private void Button1Click(object sender, EventArgs e)
  37.         {
  38.             if (openFileDialog1.ShowDialog() != DialogResult.OK) return;
  39.             _src = new Bitmap(openFileDialog1.FileName);
  40.  
  41.             pictureBox1.Image = _src;
  42.  
  43.             button2.Enabled = true;
  44.             textBox2.Text = "0";
  45.         }
  46.  
  47.  
  48.         private IEnumerable<Color?> Scan(Bitmap bitmap)
  49.         {
  50.             for (var y = 0; y < bitmap.Height; y++)
  51.             {
  52.                 for (var x = 0; x < bitmap.Width; x++)
  53.                 {
  54.                     yield return bitmap.GetPixel(x, y);
  55.                 }
  56.                 yield return null;
  57.             }
  58.         }
  59.  
  60.  
  61.         private Dictionary<Color, Color> CorrectColors(IEnumerable<Color?> scaned, Bitmap img, int error)
  62.         {
  63.             Func<int, int> D = v => v * v;
  64.  
  65.             Func<Color, Color, bool> colorCmp = (color1, color2) =>
  66.                 error < 100 && ( color1 == Color.White || color2 == Color.White) ? false  :
  67.                 Math.Sqrt(D(color1.R - color2.R) + D(color1.G - color2.G) + D(color1.B - color2.B)) <= error;          
  68.  
  69.             var mapColors = scaned
  70.                 .Where(c => c != null)
  71.                 .Select(row => row.Value)
  72.                 .GroupBy(row => row)
  73.                 .ToDictionary(row => row.Key, row => new { newColor = row.Key, count = row.Count() });
  74.  
  75.             var processed = new HashSet<Color>();
  76.  
  77.             foreach (var color in mapColors.OrderByDescending(row => row.Value.count).Select(row=>row.Key).ToArray())
  78.             {
  79.                 if (processed.Add(color))
  80.                 {
  81.                     foreach (var oldcolor in mapColors.Keys.ToArray().Where(c => !processed.Contains(c)).Where(c => colorCmp(color, c)))
  82.                     {
  83.                         processed.Add(oldcolor);
  84.                         mapColors[oldcolor] = new { newColor = color, count = 0 };
  85.                     }
  86.                 }
  87.             }
  88.  
  89.             return mapColors.ToDictionary(row => row.Key, row => row.Value.newColor);
  90.         }
  91.  
  92.  
  93.         private Tuple<Action<Color?, int>, Action> Preview(int width, int height, Action<Bitmap> onCustomFinish)
  94.         {
  95.             var preview = new Bitmap(width * 4, height * 4);
  96.  
  97.             Action<int, int, Color> previewSetPixel = (x, y, c) =>
  98.             {
  99.                 for (var i = 0; i < 2; i++)
  100.                     for (var j = 0; j < 3; j++)
  101.                         preview.SetPixel(x * 2 + i, y * 3 + j, c);
  102.             };
  103.  
  104.             int lastx = 0, lasty = 0;
  105.             Action<Color?, int> write = (c, len) =>
  106.             {
  107.                 if (c != null)
  108.                 {
  109.                     for (var x = 0; x < len; x++)
  110.                     {
  111.                         previewSetPixel(lastx + x, lasty, c.Value);
  112.                     }
  113.                     lastx += len;
  114.                 }
  115.                 else
  116.                 {
  117.                     lastx = 0;
  118.                     lasty++;
  119.                 }
  120.             };
  121.  
  122.             Action onFinish = () => onCustomFinish(preview);
  123.  
  124.             return new Tuple<Action<Color?, int>, Action>(write, onFinish);
  125.         }
  126.  
  127.  
  128.         private Tuple<Action<Color?, int>, Action> ToSkype(Color backgroundColor, Action<string> onCustomFinish)
  129.         {
  130.             Func<Color, string> printColor = (color) => "#" + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
  131.  
  132.             var result = new StringBuilder();
  133.             result.AppendFormat("<font color='{0}' size='1'><b><u>", printColor(backgroundColor));
  134.  
  135.             Action<Color?, int> write = (color, len) =>
  136.             {
  137.                 if (color != null)
  138.                 {
  139.                     if (color != backgroundColor)
  140.                     {
  141.                         result.AppendFormat("<font color='{0}'>{1}</font>", printColor(color.Value), new string('█', len));
  142.                     }
  143.                     else
  144.                     {
  145.                         result.Append(new string('█', len));
  146.                     }
  147.                 }
  148.                 else
  149.                 {
  150.                     result.AppendLine();
  151.                 }
  152.             };
  153.  
  154.             Action onFinish = () =>
  155.             {
  156.                 result.Append("</u></b></font>");          
  157.                 onCustomFinish(result.ToString());
  158.             };
  159.  
  160.             return new Tuple<Action<Color?, int>, Action>(write, onFinish);
  161.         }
  162.  
  163.  
  164.         private void Button2Click(object sender, EventArgs e)
  165.         {
  166.             var rate = _src.Height/(double) _src.Width;
  167.             var h = Convert.ToInt32(textBox1.Text);
  168.             var img = ResizeImage(_src, Convert.ToInt32(h * 1.5), Convert.ToInt32(h * rate));
  169.             var scaned = Scan(img).ToArray();
  170.  
  171.             var error = Convert.ToInt32(textBox2.Text);
  172.            
  173.             // попробуем подобрать минимальное возможное колличество ошибок
  174.             if (error == 0)
  175.             {
  176.                 error = Enumerable.Range(0, int.MaxValue).BinarySearch(err =>
  177.                 {
  178.                     var mc = CorrectColors(scaned, img, err);
  179.  
  180.                     var size = 0;
  181.                     var checkSize = ToSkype(
  182.                         mc.GroupBy(row => row.Value).OrderByDescending(row => row.Count()).First().Key,                      
  183.                         (result) =>
  184.                         {
  185.                             size = result.Length;
  186.                         });
  187.  
  188.                     MergeColumns(
  189.                         scaned,
  190.                         mc,
  191.                         write: checkSize.Item1 ,
  192.                         finish: checkSize.Item2
  193.                      );
  194.  
  195.                     return size < 22000;
  196.                 });
  197.  
  198.                 textBox2.Text = error.ToString();
  199.             }
  200.  
  201.             // вывод
  202.             Dictionary<Color, Color> mapColors = CorrectColors(scaned, img, error);
  203.             var preview = Preview(img.Width, img.Height, result => pictureBox2.Image = result);
  204.             var toSkype = ToSkype(
  205.                 mapColors.GroupBy(row => row.Value).OrderByDescending(row => row.Count()).First().Key,            
  206.                 (result)=>
  207.                 {
  208.                     Clipboard.SetText(result);
  209.                     label1.Text = result.Length.ToString();                    
  210.                 });
  211.  
  212.             MergeColumns(scaned, mapColors,
  213.                 write : (Action<Color?, int>) Delegate.Combine(preview.Item1, toSkype.Item1),
  214.                 finish : (Action)Delegate.Combine(preview.Item2, toSkype.Item2)
  215.              );            
  216.         }
  217.  
  218.         private void MergeColumns(IEnumerable<Color?> scaned, Dictionary<Color, Color> mapColors, Action<Color?, int> write, Action finish)
  219.         {
  220.             var bufferLen = 0;
  221.             Color? bufferColor = null;
  222.             foreach (var c in scaned)
  223.             {
  224.                 if (c != null)
  225.                 {
  226.                     var nc = mapColors[c.Value];
  227.                     if (bufferColor != null)
  228.                     {
  229.                         if (bufferColor == nc)
  230.                         {
  231.                             bufferLen += 1;
  232.                         }
  233.                         else
  234.                         {
  235.                             write(bufferColor, bufferLen);
  236.                             bufferColor = nc;
  237.                             bufferLen = 1;
  238.                         }
  239.                     }
  240.                     else
  241.                     {
  242.                         bufferColor = nc;
  243.                         bufferLen = 1;
  244.                     }
  245.                 }
  246.                 else
  247.                 {
  248.                     if (bufferColor != null)
  249.                     {
  250.                         write(bufferColor, bufferLen);
  251.                         bufferColor = null;
  252.                         bufferLen = 0;
  253.                     }
  254.  
  255.                     write(null, 0);
  256.                 }
  257.             }
  258.  
  259.             finish();
  260.         }
  261.  
  262.        
  263.     }
  264.  
  265.     public static class Ext
  266.     {
  267.         public static T BinarySearch<T>(this IEnumerable<T> ar, Func<T, bool> check)
  268.         {
  269.             var en = ar.GetEnumerator();
  270.             var buffer = new List<T>();
  271.  
  272.             var found = false;
  273.             do
  274.             {
  275.                 buffer.Clear();
  276.                 for (var i = 0; i < 5; i++)
  277.                 {
  278.                     en.MoveNext();
  279.                     buffer.Add(en.Current);
  280.                 }
  281.  
  282.                 found = check(buffer.Last());
  283.             }
  284.             while (!found);
  285.  
  286.             buffer.Reverse();
  287.             return buffer.TakeWhile(check).Last();
  288.         }
  289.     }
  290. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement