Saving and Loading imagedata to XML


#1

Hi There,

I’m building an application that saves and read project settings to an XML document. All works fine thanx to the easy to use XML functions from Juce.
But now i’ve been searching for a way to store and load JPEG image data in XML format.
The Jucer seems to be able to do this but haven’t yet discovered how it is done.

If this can’t be done i would we be helped by some code that actually saves and loads and JPEG image to and from disk.

My application creates thumbnails from video files so i have an Image created from raw image data. I wan’t these thumbnails saved in an XML file or as a .jpg file on disk.

can somebody help me this?

Cheers
Edwin de Koning


#2

i would also like to know if there’s a way of doing this. I believe that XML supports binary data embedded in tags (perhaps with some kind of ‘cdata’ tag?) but i’m not sure if the juce XmlElement supports this yet. It would be very good if it did.

Until that becomes possible however, the other method I’ve had in mind (for having a single file that can hold XML and image data) is to use a .zip file, containing first the XML file, and then the image files. However, again, I believe Juce does not currently have zip writing support built in (another thing I request).


#3

if tehre is a base64 encoding method somewhere that should be perfect for storing binary data in a text document (any). but i don’t know if JUCE has anything like that.


#4

If you create a component in the Jucer wich uses a Jpeg as background the data is written in the .cpp file. I guess this technique could be used for storing the same data in an XML file as well, or am i looking in the wrong direction?

Cheers
Edwin


#5

Well, that uses the BinaryBuilder system, which is for embedding binary data (as c code) into an application/library. What we want is to have a way of embedding binary data into a dynamic file format. I guess it’s a good start for converting binary data to text though, so it could be adapted, but you would need to convert the text into bytes, which would involve parsing the characters as blocks and converting them into bytes. As several characters represent all the memory units, it would actually bump up the size of the file quite a bit, so it’s probably not the best idea!

If that seems a bit odd, remember that the size of the code doesn’t really affect the size of the memory required by a program. E.g., “why does this not make the file size of my app bigger when i embed data?”. The number of characters in a text file doesn’t relate to the size of the data it represents once the compiler’s had its way with it. As an example, if a line of code said “int a = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1;”, the code file would have a large number of bytes used to represent the value, but when it’s compiled that value will just be a constant which sits in sizeof(int). The data from binarybuilder is stored in code as text, but the compiler turns it into an array of bytes which is how it’s stored in the app binary. The files we want to create are our ‘storage’, the end-result of writing the data. If we’re storing image data as text in this way, we’ll be creating large files which will perhaps cause the user to cry.


#6

Hmmm, no the file would probably get way too large.

O.k but then how about just saving an Image to disk in Jpeg format.
Any idea on how this should be done, i can’t seem to find a way.
I have an Image object filled with raw RGB data, can i convert this to a stream that the JPEGImageFormat accepts.

Could i then use the JPEGImageFormat ::writeImageToStream to create a file?

Cheers
Edwin


#7

Dead easy. Something along these lines:

[code]MemoryOutputStream out;
JPEGImageFormat format;

format.writeImageToStream (yourImage, out);
MemoryBlock jpegData (out.getData(), out.getDataSize(), false);
xml.addAttribute (T(“myAttributeName”), jpegData.to64BitEncoding());
[/code]


#8

ahhh…thanx for this, going to try it right away.
Cool!
Edwin


#9

Be sure to check the other thread that appeared today about a bug in the 64-bit encoding code though…


#10

Hi i just finished the code that makes me read and write thumbnails into an XML. Check the code below, maybe somebody has some use for this.
And maybe it can be improved. ‘thumbImage’ is an standard Image.

Cheers
Edwin

//get xml representation of clip
XmlElement* ClipObject::createThumb() const
{
	if (!opened) return 0;

	MemoryOutputStream out;
	JPEGImageFormat format;

	format.writeImageToStream (*thumbImage, out);
	juce::MemoryBlock jpegData ( out.getData(), out.getDataSize());

	XmlElement* const glThumbElm = new XmlElement (T("thumbInfo"));

	glThumbElm->setAttribute (T("preview"), jpegData.to64BitEncoding());
	
	
	

	return glThumbElm;

}

[code]
void ClipObject::readThumb(XmlElement *const glThumbElm)
{

//search for sub elements
XmlElement* childElement = glThumbElm->getFirstChildElement();
if (childElement != 0)
{

	if (childElement->hasTagName ( (T("thumbInfo")) )) //
	{
		

		juce::MemoryBlock *jpegData = new juce::MemoryBlock();
		if ( jpegData->from64BitEncoding( childElement->getStringAttribute( T("preview"), 0) ) ) {
			
			MemoryInputStream *in = new MemoryInputStream(jpegData->getData(), jpegData->getSize(), true) ;
			

			Image *tempImage = ImageFileFormat::loadFrom( *in );
			
			if (tempImage != 0) {
				try {
					Graphics thumbCanvas (*thumbImage);
					thumbCanvas.fillAll(Colours::black);
					thumbCanvas.drawImageAt(tempImage,0,0,false);
				} catch(...) {

				}
			
				deleteAndZero( tempImage);

			}
			
		}
		

	}
}

}
[/code][/code]


#11

Wow - some serious memory leakage going on there! Try using more stack objects - this ain’t java!


#12

Hi,
Well don’t know about Java but before i actually start coding some c++ a year ago i allways used to develop in Delphi.

And since Delphi takes care of most of the cleaning for you i’m not used to do this all manually.
I just looked up the term ‘stack objects’ and finally know what it means :wink:

Anyway, i reposted the code, is there still something i forgot?
Do i have to cleanup the XMl childElement as well, set the pointer to zero?
I know this maybe is not the place to ask these questions, but there is really noone in my surroundings that has any experience in coding in c++ or in any other language for that matter. I’m surrounded by graphic designers so that doesn’t help.

void ClipObject::readThumb(XmlElement *const glThumbElm)
{

	//search for sub elements
	
	XmlElement* childElement = glThumbElm->getFirstChildElement();
	if (childElement != 0)
	{

		if (childElement->hasTagName ( (T("thumbInfo")) )) //
		{
			
			juce::MemoryBlock jpegData;

			if ( jpegData.from64BitEncoding( childElement->getStringAttribute( T("preview"), 0) ) ) {
				
				MemoryInputStream in( jpegData.getData(), jpegData.getSize(), true);
				Image *tempImage = ImageFileFormat::loadFrom( in );
				
				if (tempImage != 0) {
					try {
						Graphics thumbCanvas (*thumbImage);
						thumbCanvas.fillAll(Colours::black);
						thumbCanvas.drawImageAt(tempImage,0,0,false);
					} catch(...) {

					}
				
				}

				deleteAndZero( tempImage);

			}
			

		}

	}


} 

#13

Really? Does Delphi do garbage collection?

Anyway, it’s looking better this time! No need to delete the xml child elements, that’s all done for you.


#14

I don’t know if Delphi has done something recently (maybe with the .NET stuff then), but last time I checked the garbage collection worked only for strings and interfaced objects (that is any standard object would need to be freed manually).


#15