Сжатие и восстановление картинки, чтобы мог передать одним пакетом по протоколу UDP? - C#
Формулировка задачи:
У меня есть 2 клиента,первый отправляет онлайн трансляцию своего экрана на другого клиента.
Мне нужен такой алгоритм сжатия, чтобы я мог отослать одним пакетом по UDP.
когда устанавливаю значения 40L и меньше, то полученная картинка вмещается в UDP пакет. Но я хочу восстановить в оригинальное качество,подскажите как сделать?или какой-нибудь другой алгоритм, заранее спасибо)
private: ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg); System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality; EncoderParameters myEncoderParameters = new EncoderParameters(1); EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 40L); myEncoderParameters.Param[0] = myEncoderParameter; private ImageCodecInfo GetEncoder(ImageFormat jpeg) { ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); foreach (ImageCodecInfo codec in codecs) { if (codec.FormatID == jpeg.Guid) { return codec; } } return null; } private byte[] CompressFrame(Bitmap bitmap, ImageFormat format) { bitmap.Save(stream, GetEncoder(format), myEncoderParameters); return stream.ToArray(); } byte[] message = CompressFrame((Bitmap)frame.Clone(),ImageFormat.Jpeg); // тут получаю сжатую картинку(40L)
Решение задачи: «Сжатие и восстановление картинки, чтобы мог передать одним пакетом по протоколу UDP?»
textual
Листинг программы
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication345 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //создаем Image для отображения скриншота и Graphics для него var image = new Bitmap(1300, 1300); var gr = Graphics.FromImage(image); //создаем PictureBox для отображения скриншотов var pb = new PictureBox { Parent = this, Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.Zoom, Image = image }; //создаем поток для клиента (на самом деле это должно запускаться на машине клиента, но для теста, клиент запускается здесь) ThreadPool.QueueUserWorkItem(delegate { new Client().Start(); }); //создаем поток для сервера ThreadPool.QueueUserWorkItem( delegate { //получаем в цикле скриншоты с клиента foreach (var chunk in new Server().GetScreenshots()) { //заносим скриншот в PictureBox gr.DrawImage(chunk.Image, chunk.Position); pb.Invalidate(); } }); } } /// <summary> /// Сервер /// </summary> class Server { public IEnumerable<Chunk> GetScreenshots(int port = 24432) { using (var udp = new UdpClient(port)) while (true)//делаем бесконечно { //принимаем массив IPEndPoint ip = null; var arr = udp.Receive(ref ip); //читаем координаты var x = arr[0] * Client.CHUNK_SIZE; var y = arr[1] * Client.CHUNK_SIZE; using (var ms = new MemoryStream(arr, 2, arr.Length - 2))//создаем временный поток для сжатого изображения { //создаем изображение var bmp = Bitmap.FromStream(ms); //возвращаем yield return new Chunk {Position = new Point(x, y), Image = bmp}; } } } public class Chunk { public Point Position; public Image Image; } } /// <summary> /// Клиент /// </summary> class Client { public const int CHUNK_SIZE = 128; public void Start(string host = "localhost", int port = 24432) { //размеры экрана var rect = Screen.PrimaryScreen.Bounds; var chunkHash = new Dictionary<Point, int>(); //конкетимся к серверу, получаем поток using (var udp = new UdpClient(host, port)) //создаем TcpClient using (var screenshot = new Bitmap(rect.Width, rect.Height)) //создаем битмап для отправки using (var gr = Graphics.FromImage(screenshot)) //создаем канву скриншота while (true) //делаем бесконечно { //захватываем изображение экрана gr.CopyFromScreen(rect.Left, rect.Top, 0, 0, new Size(rect.Width + CHUNK_SIZE, rect.Height + CHUNK_SIZE)); //перебираем кусочки for (int x = 0; x < rect.Width; x += CHUNK_SIZE) for (int y = 0; y < rect.Height; y += CHUNK_SIZE) //вырезаем кусочек using (var bmp = screenshot.Clone(new Rectangle(x, y, CHUNK_SIZE, CHUNK_SIZE), screenshot.PixelFormat)) using (var ms = new MemoryStream()) //создаем временный поток для сжатого изображения { //отправляем координаты кусочка ms.WriteByte((byte)(x/CHUNK_SIZE)); ms.WriteByte((byte)(y/CHUNK_SIZE)); //конвертируем изображение в массив в формат jpeg bmp.Save(ms, ImageFormat.Jpeg); //получаем массив байт var arr = ms.ToArray(); //отправляем датаграмму (только изменившиеся кусочки) var p = new Point(x, y); if (!chunkHash.ContainsKey(p) || chunkHash[p] != arr.Length)//хеш кусочка изменился? { udp.Send(arr, arr.Length);//отправляем chunkHash[p] = arr.Length;//сохраняем новый хеш Thread.Sleep(10);//если убрать эту задержку, то не все UDP пакеты приходит, почему - хз } } } } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д