charles henington Ответов: 2

Растровое изображение в векторное без автотрансформации


I'm currently in the process of writing a code snippet that converts a Raster image to a Vector image. It works but the output becomes quite large on larger images, ex. on an 960px * 800px image the output is around 160mb, I've searched relentlessly on google for a solution of creating an array of sorts for fill blocks(what i save the color values in). So far no such luck so I have decided to seek out the assistance of my fellow coders to enquire of their knowledge and expertise on the matter at hand. Please feel free to leave a comment if you have and knowledge or information, or would like to discuss this concept further or rant if you must :). So far here is the code snippet that i am working with.
public static unsafe void SaveVector(this Image @this, Stream outputStream)
		{
			
			int PixelSize = 4;
			Rectangle rect = new Rectangle(new Point(0,0), @this.Size);						
			using(StreamWriter SvgWriter = new StreamWriter(outputStream))
			{
				using(Bitmap bitmap = new Bitmap(@this))
				{
					BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
					SvgWriter.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
					SvgWriter.WriteLine("<svg");
					SvgWriter.WriteLine("   xmlns:svg=\"http://www.w3.org/2000/svg\"");
					SvgWriter.WriteLine("   xmlns=\"http://www.w3.org/2000/svg\"");
					SvgWriter.WriteLine(string.Format("   width=\"{0}\"", @this.Width));
					SvgWriter.WriteLine(string.Format("   height=\"{0}\"", @this.Height));
					SvgWriter.WriteLine("   id=\"svg2\"");
					SvgWriter.WriteLine("   version=\"1.1\">");
					SvgWriter.WriteLine("  <defs");
					SvgWriter.WriteLine("     id=\"defs4\" />");
					SvgWriter.WriteLine("  <metadata");
					SvgWriter.WriteLine("     id=\"metadata7\" />");
					SvgWriter.WriteLine("  <g");
					SvgWriter.WriteLine("     id=\"layer1\">");
					int num = 0;				
					for(int y = 0; y < bitmapData.Height; y++)
					{
						byte* row=(byte *)bitmapData.Scan0+(y*bitmapData.Stride);
						for(int x = 0; x < bitmapData.Width; x++)
						{
							SvgWriter.WriteLine("    <rect");							
							SvgWriter.WriteLine(string.Format("       style=\"fill:{0};fill-opacity:1;stroke-width:0.43599999000000000;stroke-miterlimit:4;stroke-dasharray:none\"", 
								ColorTranslator.ToHtml(Color.FromArgb(
								row[(x * PixelSize) + 3],
								row[(x * PixelSize) + 2],
								row[(x * PixelSize) + 1],
								row[x * PixelSize]))));
							SvgWriter.WriteLine(string.Format("       id=\"rect{0}\"", num));
							SvgWriter.WriteLine("       width=\"1\"");
							SvgWriter.WriteLine("       height=\"1\"");
							SvgWriter.WriteLine(string.Format("       x=\"{0}\"", x));
							SvgWriter.WriteLine(string.Format("       y=\"{0}\" />", y));							
							num++;
						}						
					}
					bitmap.UnlockBits(bitmapData);
				}
				SvgWriter.WriteLine("  </g>");
				SvgWriter.WriteLine("</svg>");
			}
		}
	}

Sergey Alexandrovich Kryukov

Это не "обращение". И зачем пытаться сделать вектор из растра? Это никогда не может быть сделано с хорошим качеством, по самой природе вещей.
—СА

BillWoodruff

Мне любопытно: вы пробовали взять свой 160-мегабайтный файл, сжать его с помощью WinRar и Zip и сравнить размеры файлов ?

Я предполагаю, что разработка этого кода-хороший опыт обучения для вас, но я не вижу ничего выходящего из него, что было бы полезно в практическом программном приложении.

2 Ответов

Рейтинг:
2

Dave Kreskowiak

Мне неприятно вам это говорить, но это не векторное преобразование. Ни в малейшей степени.

Все, что вы сделали, это прочитали пиксель из изображения и обернули его в большой блок, который выглядит как XML-текст. Да, неудивительно, что ваши результирующие файлы раздуваются до 160 МБ.

Направление, в котором вы, по-видимому, идете, - это то, что было названо кодированием длины пробега (RLE) изображений. Тем не менее, он далеко не так эффективен, как ваш оригинальный растровый рисунок в качестве носителя данных.

И вообще, что ты пытаешься с этим сделать?


Рейтинг:
1

SoMad

Я согласен с Сергеем и Дейвом - вы идете по неверному пути. Я не уверен точно, чего вы пытаетесь достичь, но я думаю, что вам было бы лучше вставить тег <image> в ваш SVG и либо связать его с файлом изображения, либо, возможно, base64 кодирует изображение и вставляет его в ваш тег SVG image.

Ниже вы должны увидеть две версии изображения Боба. Один из них связан с онлайн-изображением, другой-с версией того же изображения base64.
&ЛТ;СВГ префиксом xmlns="http://www.w3.org/2000/svg" версия="1.1" ширина="300 пикселей" высота="140px"&ГТ;Image 1
[&ЛТ;СВГ префиксом xmlns="http://www.w3.org/2000/svg" версия="1.1" ширина="300 пикселей" высота="140px"&ГТ;&ЛТ;высота изображения="125" ширина="125" х="10" г="10" языка xlink:href, то="http://www.codeproject.com/App_Themes/CodeProject/Img/logo125x125.gif"/&ГТ;&ЛТ;/СВГ&ГТ;]

&ЛТ;СВГ префиксом xmlns="http://www.w3.org/2000/svg" версия="1.1" ширина="300 пикселей" высота="140px"&ГТ;Image 2
[Чтобы увидеть встроенную версию base64, щелкните правой кнопкой мыши на изображении и выберите пункт "Проверить элемент"]

Вот несколько хороших ссылок на SVG, которые я использовал:
SVG праймер для современных браузеров[

SoMad

Первоначально я опубликовал решение 2, но мне хотелось кое-что изменить. Самая большая ошибка. Я пытался изменить текст несколько раз, но после отправки он будет HTML-кодировать тег изображения внутри SVG, и изображения не будут отображаться.
Если кто-нибудь знает, почему система так себя ведет, пожалуйста, скажите мне. Если вы видите что-то в моем решении, что вы хотите изменить, не.

Сорен Мадсен

leon de boer

Я думаю, что вы после того, как мы уже выставили демо-код в разделе советов

http://www.codeproject.com/Articles/407172/Connected-Component-Labeling-and-Vectorization

Правильное название для того, что вы пытаетесь сделать, называется маркировкой подключенных компонентов, она помечает и/или окрашивает подключенные блоки.

SoMad

На самом деле я не задаю этот вопрос, я просто попытался предложить другой подход, чем попытка построить псевдовекторную графику из простого растрового изображения.
Не стесняйтесь оставлять свой комментарий под самим вопросом или даже в качестве решения, если вы считаете, что это может помочь ОП.

Сорен Мадсен