Monday, May 21, 2007

Convert embedded images into base64 in SVG using Java

Its a nice feature that you can include images in SVG. But the embedded images still refer to an external file. So while the svg is downloaded all the relevant image files have to be downloaded as well. To avoid this you can convert your images into Base64 before embedding. All the referred images will remain in the same SVG file, SVG will not refer external image files. The functions mentioned use the Base64 utility from here : http://iharder.sourceforge.net/current/java/base64/. Pass the SVG file as a string into the method fillBase64(). This will return an SVG string with your image files Base64 embedded. What I have done here is a small text parsing to find image tag and include the corresponding Base64 code. Enjoy!

public String fillBase64(String svg) throws Exception
{
String newSvg = "";

try
{

int imageStartPos = svg.indexOf("<image",0);
int imageEndPos = 0;
int imageUrlPos = 0;
int copyStartPos = 0;
int fileNameStartPos = 0;
int fileNameEndPos = 0;

while(imageStartPos != -1)
{
imageEndPos = svg.indexOf("/>",imageStartPos);
imageUrlPos = svg.indexOf("xlink:href=",imageStartPos);

if((imageUrlPos > imageStartPos)||(imageUrlPos < imageEndPos))
{
fileNameStartPos = imageUrlPos+12 ;
fileNameEndPos = svg.indexOf("\"",fileNameStartPos);
String imageFilePath = svg.substring(fileNameStartPos, fileNameEndPos);

String base64String = getBase64(imageFilePath);

new File(imageFilePath).delete();

newSvg += svg.substring(copyStartPos, fileNameStartPos);
newSvg += "data:image/jpeg;base64,"+base64String;

copyStartPos = fileNameEndPos;
}
imageStartPos = svg.indexOf("<image",imageEndPos+2);
}

newSvg += svg.substring(copyStartPos);
}
catch(Exception e)
{
System.out.println("Exception in fillBase64() : ");e.printStackTrace();
}

return newSvg;
}



private String getBase64(String filePath) throws Exception
{
String h = "";
try
{
System.out.println("PRINTING THE FILEPATH \""+filePath+"\"");
File f = new File(filePath);

byte[] b = new byte[(int)f.length()];
System.out.println("FILELENGTH : "+(int)f.length());
FileInputStream fis = new FileInputStream(f);
fis.read(b);
h = Base64.encodeBytes(b);
}
catch(Exception e)
{
System.out.println("Exception in getBase64() : ");e.printStackTrace();
}

return h;
}

No comments: