Click here to Skip to main content
15,885,216 members
Please Sign up or sign in to vote.
2.00/5 (4 votes)
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.
C#
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>");
			}
		}
	}
Posted
Comments
Sergey Alexandrovich Kryukov 7-Feb-14 15:26pm    
This is not "conversion". And why trying to make vector from raster? It can never be done with good quality, by the nature of things.
—SA
BillWoodruff 8-Feb-14 7:42am    
I'm curious: have you tried taking your 160mb file and compressing it with WinRar and Zip and comparing file sizes ?

I assume developing this code is a good learning experience for you, but I don't see anything coming out of it that would be useful in a practical software application.

Uhhh I hate to tell you this, but that's NOT a vector conversion. Not in the slightest.

All you did was read a pixel from the image and wrap it in a LARGE block of what looks like XML text. Yeah, it's no wonder your resulting files balloon to 160MB.

The direction you appear to be going is what was called Run Length Encoding (RLE) images. Still, it's nowhere near as efficient as your original bitmap as a storage medium.

What are you trying to do with this anyway?
 
Share this answer
 
I agree with Sergey and Dave - you are going about this the wrong way. I am not sure exactly what you are trying to accomplish, but I think you would be better off inserting an <image> tag in your SVG and either link to the image file or possibly base64 encoding the image and embedding that in your SVG image tag.

Below you should be able see two versions of a Bob image. One is linking to the online image, the other is embedding a base64 version of the same image.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="140px">
[<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="140px"><image height="125" width="125" x="10" y="10" xlink:href="http://www.codeproject.com/App_Themes/CodeProject/Img/logo125x125.gif"/></svg>]

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="140px">
[To see the base64 embedded version, right-click on the image and select "Inspect Element"]

Here are a few good SVG reference links I have used:
An SVG Primer for Today's Browsers[^]
Adding SVG to a webpage[^]
SVG Tutorial - Jenkov[^]

I used this online converter to generate the base64 version of the Bob image:
http://webcodertools.com/imagetobase64converter/Create[^]


Soren Madsen
 
Share this answer
 
Comments
SoMad 7-Feb-14 23:44pm    
I had originally posted Solution 2, but I wanted to change a few things. Big mistake. I tried modifying the text several times, but after submitting, it would HTML encode the Image tag inside the SVG and the images would not display.
If anyone know why the system behaves like that, please tell me. If you see something in my solution that you want to change, don't.

Soren Madsen
leon de boer 2-Mar-14 23:45pm    
I think what you are after we have already put up in demo code in the tips section

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

The correct name for what you are trying to do is called connected component labeling, it labels and/or colors connected blocks.
SoMad 3-Mar-14 0:32am    
I am actually not the one asking the question, I merely tried to suggest a different approach than trying to construct a pseudo-vector graphics from a plain bitmap.
Feel free to post your comment under the Question itself or even as a solution if you believe it can help the OP.

Soren Madsen

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900