2010-05-27 William Holmes <billholmes54@gmail.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing.Imaging / ImageCodec.jvm.cs
index e410187b5af3fa5a213880e2bbb5f58dd3fd938b..8ded371ba7523563123e6639120dba51be139e9b 100644 (file)
@@ -8,27 +8,27 @@ using Mainsoft.Drawing.Configuration;
 \r
 using imageio = javax.imageio;\r
 using stream = javax.imageio.stream;\r
+using awt = java.awt;\r
 using image = java.awt.image;\r
 using spi = javax.imageio.spi;\r
 using dom = org.w3c.dom;\r
 \r
-namespace Mainsoft.Drawing.Services {\r
+namespace Mainsoft.Drawing.Imaging {\r
        /// <summary>\r
        /// Summary description for ImageCodec.\r
        /// </summary>\r
-       public class ImageCodec {\r
+       public class ImageCodec : IDisposable {\r
+\r
                #region Members\r
 \r
                imageio.ImageReader _nativeReader = null;\r
                imageio.ImageWriter _nativeWriter = null;\r
                stream.ImageInputStream _nativeStream = null;\r
 \r
-               float _imageHorizontalResolution = 0;\r
-               float _imageVerticalResolution = 0;\r
-\r
-               XmlDocument _metadataDocument = null;\r
                ImageFormat _imageFormat = null;\r
 \r
+               int _currentFrame = 0;\r
+\r
                #endregion\r
 \r
                #region Constructros\r
@@ -47,6 +47,8 @@ namespace Mainsoft.Drawing.Services {
                        get { return _nativeReader; }\r
                        set { \r
                                _nativeReader = value; \r
+                               if (value == null)\r
+                                       return;\r
                                _imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() );\r
                        }\r
                }\r
@@ -54,6 +56,8 @@ namespace Mainsoft.Drawing.Services {
                        get { return _nativeWriter; }\r
                        set { \r
                                _nativeWriter = value; \r
+                               if (value == null)\r
+                                       return;\r
                                _imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() );\r
                        }\r
                }\r
@@ -61,10 +65,9 @@ namespace Mainsoft.Drawing.Services {
                internal stream.ImageInputStream NativeStream {\r
                        get { return _nativeStream; }\r
                        set {\r
-                               if (value == null)\r
-                                       throw new ArgumentNullException("stream");\r
-\r
                                _nativeStream = value;\r
+                               if (value == null)\r
+                                       return;\r
 \r
                                if (NativeReader != null)\r
                                        NativeReader.setInput( value );\r
@@ -88,14 +91,26 @@ namespace Mainsoft.Drawing.Services {
                }\r
 \r
                public static ImageCodec CreateReader(Guid clsid) {\r
-                       ImageCodecInfo codecInfo = (ImageCodecInfo) Decoders[clsid];\r
-                       java.util.Iterator iter = imageio.ImageIO.getImageReadersByMIMEType( codecInfo.MimeType );\r
-                       return CreateReader(iter);\r
+                       ImageCodec codec = null;\r
+                       try {\r
+                               ImageCodecInfo codecInfo = FindDecoder(clsid);\r
+                               java.util.Iterator iter = imageio.ImageIO.getImageReadersByMIMEType( codecInfo.MimeType );\r
+                               codec = CreateReader(iter);\r
+                       }\r
+                       catch {}\r
+\r
+                       if (codec == null) {\r
+                               ImageFormat format = ClsidToImageFormat(clsid);\r
+                               string name = (format != null) ? format.ToString() : clsid.ToString();\r
+                               throw new NotSupportedException(String.Format("The '{0}' format decoder is not installed.", name));\r
+                       }\r
+\r
+                       return codec;\r
                }\r
 \r
                private static ImageCodec CreateReader(java.util.Iterator iter) {\r
                        if ( !iter.hasNext() )
-                               throw new OutOfMemoryException ("Out of memory"); 
+                               return null;
 \r
                        ImageCodec imageCodec = new ImageCodec();\r
                        imageCodec.NativeReader = (imageio.ImageReader) iter.next();\r
@@ -107,14 +122,26 @@ namespace Mainsoft.Drawing.Services {
                }\r
 \r
                public static ImageCodec CreateWriter(Guid clsid) {\r
-                       ImageCodecInfo codecInfo = (ImageCodecInfo) Encoders[clsid];\r
-                       java.util.Iterator iter = imageio.ImageIO.getImageWritersByMIMEType( codecInfo.MimeType );\r
-                       return CreateWriter(iter);\r
+                       ImageCodec codec = null;\r
+                       try {\r
+                               ImageCodecInfo codecInfo = FindEncoder(clsid);\r
+                               java.util.Iterator iter = imageio.ImageIO.getImageWritersByMIMEType( codecInfo.MimeType );\r
+                               codec = CreateWriter(iter);\r
+                       }\r
+                       catch {}\r
+\r
+                       if (codec == null) {\r
+                               ImageFormat format = ClsidToImageFormat(clsid);\r
+                               string name = (format != null) ? format.ToString() : clsid.ToString();\r
+                               throw new NotSupportedException(String.Format("The '{0}' format encoder is not installed.", name));\r
+                       }\r
+\r
+                       return codec;\r
                }\r
 \r
-               public static ImageCodec CreateWriter(java.util.Iterator iter) {\r
+               private static ImageCodec CreateWriter(java.util.Iterator iter) {\r
                        if ( !iter.hasNext() )
-                               throw new OutOfMemoryException ("Out of memory"); 
+                               return null;
                        \r
                        ImageCodec imageCodec = new ImageCodec();\r
                        imageCodec.NativeWriter = (imageio.ImageWriter) iter.next();\r
@@ -150,11 +177,22 @@ namespace Mainsoft.Drawing.Services {
                }
 
                internal static ImageCodecInfo FindEncoder (Guid clsid) {
-                       return (ImageCodecInfo) Encoders[clsid];
+                       ImageCodecInfo codec = (ImageCodecInfo) Encoders[clsid];
+                       if (codec == null) {
+                               // .net saves in png if cannot find requested encoder. atc id 316563
+                               codec = (ImageCodecInfo) Encoders[ ImageCodec.PngClsid ];
+                       }
+                       return codec;
                }
 
                internal static ImageCodecInfo FindDecoder (Guid clsid) {
-                       return (ImageCodecInfo) Decoders[clsid];
+                       ImageCodecInfo codec = (ImageCodecInfo) Decoders[clsid];
+                       if (codec == null) {\r
+                               ImageFormat format = ClsidToImageFormat(clsid);\r
+                               string name = (format != null) ? format.ToString() : clsid.ToString();\r
+                               throw new NotSupportedException(String.Format("The '{0}' format decoder is not installed.", name));\r
+                       }\r
+                       return codec;\r
                }
 \r
                #endregion\r
@@ -166,56 +204,60 @@ namespace Mainsoft.Drawing.Services {
                        protected abstract spi.ImageReaderWriterSpi GetNext (java.util.Iterator iter);
 
                        #region ProcessOneCodec
-                       ImageCodecInfo ProcessOneCodec (Guid clsid, Guid formatID, string mimeType) {
+                       private ImageCodecInfo ProcessOneCodec (Guid clsid, Guid formatID, string mimeType) {
                                ImageCodecInfo ici = new ImageCodecInfo ();
                                ici.Clsid = clsid;
                                ici.FormatID = formatID;
                                ici.MimeType = mimeType;
-                               java.util.Iterator iter = GetIterator (mimeType);
+                               java.util.Iterator iter = null;
+                               try {
+                                       iter = GetIterator (mimeType);
+                               }
+                               catch(Exception) {
+                                       return null;
+                               }
                                while (iter.hasNext ()) {
                                        spi.ImageReaderWriterSpi rw = GetNext (iter);
+
+                                       ici.CodecName = rw.getDescription (java.util.Locale.getDefault ());
+                                       //ici.DllName = null;
+                                       foreach (string suffix in rw.getFileSuffixes ()) {
+                                               if (ici.FilenameExtension != null)
+                                                       ici.FilenameExtension += ";";
+                                               ici.FilenameExtension += "*."+suffix;
+                                       }
+                                       ici.Flags = ImageCodecFlags.Builtin|ImageCodecFlags.SupportBitmap;
+                                       if (rw is spi.ImageReaderSpi)
+                                               ici.Flags |= ImageCodecFlags.Decoder;
+
+                                       if (rw is spi.ImageWriterSpi)
+                                               ici.Flags |= ImageCodecFlags.Encoder;
+
+                                       ici.FormatDescription = string.Join(";",
+                                               rw.getFormatNames());
                                        try {
-                                               ici.CodecName = rw.getDescription (java.util.Locale.getDefault ());
-                                               ici.DllName = null;
-                                               foreach (string suffix in rw.getFileSuffixes ()) {
-                                                       if (ici.FilenameExtension != null)
-                                                               ici.FilenameExtension += ";";
-                                                       ici.FilenameExtension += "*."+suffix;
-                                               }
-                                               ici.Flags = ImageCodecFlags.Builtin|ImageCodecFlags.SupportBitmap;
-                                               if (rw is spi.ImageReaderSpi) {
-                                                       ici.Flags |= ImageCodecFlags.Decoder;
-                                                       if ((rw as spi.ImageReaderSpi).getImageWriterSpiNames().Length != 0)
-                                                               ici.Flags |= ImageCodecFlags.Encoder;
-                                               }
-                                               if (rw is spi.ImageWriterSpi) {
-                                                       ici.Flags |= ImageCodecFlags.Encoder;
-                                                       if ((rw as spi.ImageWriterSpi).getImageReaderSpiNames().Length != 0)
-                                                               ici.Flags |= ImageCodecFlags.Decoder;
-                                               }
-                                               ici.FormatDescription = string.Join(";",
-                                                       rw.getFormatNames());
                                                ici.Version = (int)Convert.ToDouble(rw.getVersion ());
-                                               break;
                                        }
-                                       catch {
+                                       catch (Exception) {
+                                               ici.Version = 1;
                                        }
+                                       break;
                                }
                                return ici;
                        }
                        #endregion
 
-                       public Hashtable Iterate () {
+                       internal Hashtable Iterate () {
                                // TBD: Insert Exception handling here
-                               NameValueCollection nvc = (NameValueCollection) System.Configuration.ConfigurationSettings
-                                       .GetConfig ("system.drawing/codecs");
+                               NameValueCollection nvc = (NameValueCollection) System.Configuration.ConfigurationSettings\r
+                                       .GetConfig ("mainsoft.drawing/codecs");
                                Hashtable codecs = new Hashtable (10);
                        
                                for (int i=0; i<nvc.Count; i++) {
                                        Guid clsid = new Guid (nvc.GetKey (i));
                                        ImageFormat format = ClsidToImageFormat (clsid);
                                        ImageCodecInfo codec = ProcessOneCodec (clsid, format.Guid, nvc[i]);
-                                       if (codec.FilenameExtension != null)
+                                       if ((codec != null) && (codec.FilenameExtension != null))
                                                codecs [clsid] = codec;
                                }
                                return codecs;
@@ -253,11 +295,11 @@ namespace Mainsoft.Drawing.Services {
                static Guid PngClsid = new Guid ("557cf406-1a04-11d3-9a73-0000f81ef32e");
                static Guid IconClsid = new Guid ("557cf407-1a04-11d3-9a73-0000f81ef32e");
 
-               internal static ImageFormat MimeTypesToImageFormat (string [] mimeTypes) {
+               private static ImageFormat MimeTypesToImageFormat (string [] mimeTypes) {
                        foreach (ImageCodecInfo codec in Decoders.Values)
-                               for (int i=0; i<mimeTypes.Length; i++)
-                                       if (codec.MimeType == mimeTypes [i])
-                                               return new ImageFormat (codec.FormatID);
+                               for (int i=0; i<mimeTypes.Length; i++)\r
+                                       if (codec.MimeType == mimeTypes [i])\r
+                                               return ClsidToImageFormat (codec.Clsid);\r
                        return null;
                }
 
@@ -305,138 +347,215 @@ namespace Mainsoft.Drawing.Services {
                        else
                                return Guid.Empty;
                }
+
+               private FrameDimension FormatFrameDimesion {
+                       get {
+                               if (ImageFormat == null)
+                                       return FrameDimension.Page;
+
+                               if (ImageFormat.Guid.Equals (ImageFormat.Bmp.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Jpeg.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Gif))
+                                       return FrameDimension.Time;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Emf.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Wmf.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Tiff.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Png.Guid))
+                                       return FrameDimension.Page;
+                               else if (ImageFormat.Guid.Equals (ImageFormat.Icon.Guid))
+                                       return FrameDimension.Resolution;
+                               else
+                                       return FrameDimension.Page;
+                       }
+               }
+
                #endregion
                \r
                #region Image read/write methods\r
 \r
-               public image.BufferedImage [] ReadImage() {\r
-                       int imgNumber = 0;
-                       ArrayList nativeObjects = new ArrayList();
-
-                       while (true) {
-                               try {
-                                       nativeObjects.Add( ReadImage(imgNumber++) );
-                               }
-                               catch (java.lang.IndexOutOfBoundsException) {
-                                       break;
-                               }
-                               catch (java.io.IOException ex) {
-                                       throw new System.IO.IOException(ex.Message, ex);
-                               }
-                       }
-                       return (image.BufferedImage[]) nativeObjects.ToArray(typeof(image.BufferedImage));
+               internal PlainImage ReadPlainImage() {\r
+                       awt.Image img = ReadImage( _currentFrame );\r
+                       if (img == null)\r
+                               return null;\r
+\r
+                       // its possible to fail to load thumbnails and metadata, but image is ok.\r
+                       awt.Image [] th = null;\r
+#if THUMBNAIL_SUPPORTED\r
+                       try {\r
+                               th = ReadThumbnails( _currentFrame );\r
+                       }\r
+                       catch (Exception) {}\r
+#endif\r
+                       \r
+                       XmlDocument md = null;\r
+                       imageio.metadata.IIOMetadata nativeMd = null;\r
+                       try {\r
+                               nativeMd = ReadImageMetadata( _currentFrame );\r
+                               md = ConvertImageMetadata( nativeMd );\r
+                       }\r
+                       catch (Exception) {}\r
+\r
+                       float [] resolution = GetResolution( md );\r
+\r
+                       PlainImage pi = new PlainImage( img, th, ImageFormat, resolution[0], resolution[1], FormatFrameDimesion );\r
+                       pi.NativeMetadata = nativeMd;\r
+                       return pi;\r
+               }\r
+\r
+               internal PlainImage ReadNextPlainImage() {\r
+                       _currentFrame++;\r
+                       return ReadPlainImage();\r
                }\r
 \r
-               public image.BufferedImage ReadImage(int frame) {\r
+               private awt.Image ReadImage(int frame) {\r
                        if (NativeStream == null)\r
                                throw new Exception("Input stream not specified");\r
 \r
-                       return NativeReader.read (frame);
+                       try {\r
+                               return NativeReader.read (frame);
+                       }
+                       catch (java.lang.IndexOutOfBoundsException) {
+                               return null;
+                       }
+                       catch (java.io.IOException ex) {
+                               throw new System.IO.IOException(ex.Message, ex);
+                       }
                }\r
 \r
-               public image.BufferedImage [] ReadThumbnails(int frame) {\r
-                       // FIXME: seems to be incorrect on multiframe with multi thumbnail\r
-                       if (NativeReader.hasThumbnails(frame)) {
-                               
-                               int tmbNumber = NativeReader.getNumThumbnails(frame);
-                               if (tmbNumber > 0) {
-                                       image.BufferedImage [] thumbnails = new image.BufferedImage[ tmbNumber ];
+#if THUMBNAIL_SUPPORTED\r
+               private awt.Image [] ReadThumbnails(int frameIndex) {\r
+                       awt.Image [] thArray = null;
+
+                       try {
+                               if (NativeReader.readerSupportsThumbnails()) {
+                                       int tmbNumber = NativeReader.getNumThumbnails(frameIndex);
 
-                                       for (int i = 0; i < tmbNumber; i++) {
-                                               thumbnails[i] = NativeReader.readThumbnail(frame, i);
+                                       if (tmbNumber > 0) {
+                                               thArray = new awt.Image[ tmbNumber ];
+
+                                               for (int i = 0; i < tmbNumber; i++) {
+                                                       thArray[i] = NativeReader.readThumbnail(frameIndex, i);
+                                               }
                                        }
-                                       return thumbnails;
-                               }
+                               }\r
+                               return thArray;\r
+                       }\r
+                       catch (java.io.IOException ex) {
+                               throw new System.IO.IOException(ex.Message, ex);
                        }
-                       return null;
                }\r
+#endif\r
+               internal void WritePlainImage(PlainImageCollection pic) {\r
+                       if ((pic == null) || (pic.Count == 0))\r
+                               return;\r
+\r
+                       if (pic.Count == 1) {\r
+                               WritePlainImage( pic[0] );\r
+                               return;\r
+                       }\r
 \r
-               public void ReadImageMetadata(int index) {\r
-                       if (NativeStream == null)\r
-                               throw new Exception("Input stream not specified");\r
+                       try {\r
+                               if (NativeWriter.canWriteSequence ()) {\r
+                                       NativeWriter.prepareWriteSequence (null);\r
+                                       for (int i=0; i < pic.Count; i++) {\r
+                                               imageio.IIOImage iio = GetIIOImageContainer( pic[i] );\r
+                                               NativeWriter.writeToSequence (iio, null);\r
+                                       }\r
+                                       NativeWriter.endWriteSequence ();\r
+                               }\r
+                               else\r
+                                       WritePlainImage( pic[0] );\r
+                       }\r
+                       catch (java.io.IOException ex) {
+                               throw new System.IO.IOException(ex.Message, ex);
+                       }
+               }\r
 \r
-                       imageio.metadata.IIOMetadata md = NativeReader.getImageMetadata( index );\r
-
-                       string [] formatNames = md.getMetadataFormatNames();
-                       dom.Element rootNode = (dom.Element) md.getAsTree(formatNames[0]);
-
-                       MetadataDocument = new XmlDocument();\r
-                       XmlConvert(rootNode, MetadataDocument);\r
+               internal void WritePlainImage(PlainImage pi) {\r
+                       try {\r
+                               imageio.IIOImage iio = GetIIOImageContainer( pi );\r
+                               WriteImage( iio );\r
+                       }\r
+                       catch (java.io.IOException ex) {
+                               throw new System.IO.IOException(ex.Message, ex);
+                       }\r
                }\r
 \r
-               public void WriteImage(image.BufferedImage bitmap) {\r
+               private void WriteImage(imageio.IIOImage iio) {\r
                        if (NativeStream == null)\r
                                throw new Exception("Output stream not specified");\r
 \r
-                       NativeWriter.write(bitmap);\r
+                       NativeWriter.write( iio );\r
                }\r
+               \r
+               private imageio.IIOImage GetIIOImageContainer(PlainImage pi) {\r
+                       java.util.ArrayList al = null;\r
+                       \r
+                       // prepare thumbnails list\r
+                       if (pi.Thumbnails != null) {\r
+                               al = new java.util.ArrayList( pi.Thumbnails.Length );\r
+                               for (int i=0; i < pi.Thumbnails.Length; i++)\r
+                                       al.add(pi.Thumbnails[i]);\r
+                       }\r
 \r
-               public void WriteImage(image.BufferedImage [] bitmap) {\r
-                       //FIXME: does not supports metadata and thumbnails for now
-                       if (bitmap.Length == 1) {
-                               WriteImage(bitmap[0]);
-                       }
-                       else {
-                               if (NativeWriter.canWriteSequence ()) {
-                                       NativeWriter.prepareWriteSequence (null);
-
-                                       for (int i = 0; i < bitmap.Length; i++) {
-                                               imageio.IIOImage iio = new imageio.IIOImage ((image.BufferedImage)bitmap[i], null, null);
-                                               NativeWriter.writeToSequence (iio, null);
-                                       }
-                                       NativeWriter.endWriteSequence ();\r
-                               }\r
-                               else\r
-                                       throw new ArgumentException();\r
+                       // prepare IIOImage container\r
+                       if (pi.NativeImage is image.BufferedImage) {\r
+                               imageio.IIOImage iio = new javax.imageio.IIOImage(\r
+                                       (image.BufferedImage)pi.NativeImage, al, null /*pi.NativeMetadata*/);\r
+                               return iio;\r
                        }\r
+                       else\r
+                               // TBD: This codec is for raster formats only\r
+                               throw new NotSupportedException("Only raster formats are supported");\r
                }\r
 \r
-               #endregion\r
 \r
-               #region Extra properties\r
+               private imageio.metadata.IIOMetadata ReadImageMetadata(int frameIndex) {\r
+                       if (NativeStream == null)\r
+                               throw new Exception("Input stream not specified");\r
 \r
-               public float ImageHorizontalResolution {\r
-                       get {return _imageHorizontalResolution;}\r
-               }\r
-               public float ImageVerticalResolution {\r
-                       get {return _imageVerticalResolution;}\r
+                       try {\r
+                               imageio.metadata.IIOMetadata md = NativeReader.getImageMetadata( frameIndex );\r
+                               return md;\r
+                       }\r
+                       catch (java.io.IOException ex) {
+                               throw new System.IO.IOException(ex.Message, ex);
+                       }
                }\r
 \r
-               public ImageFormat ImageFormat {\r
-                       get { return _imageFormat; }\r
-               }\r
+               #endregion\r
 \r
-               public XmlDocument MetadataDocument {\r
-                       get { return _metadataDocument; }\r
-                       set { \r
-                               if (value == null)\r
-                                       throw new ArgumentNullException();\r
+               #region Extra properties\r
 \r
-                               _metadataDocument = value; \r
-                       }\r
+               public ImageFormat ImageFormat {\r
+                       get { return _imageFormat; }\r
                }\r
 \r
                #endregion\r
 \r
                #region Metadata parse\r
 \r
-               public void ParseMetadata() {\r
-                       if (MetadataDocument == null)\r
-                               ReadImageMetadata(0);\r
-\r
-                       SetResolution();\r
-               }\r
+               private float [] GetResolution(XmlDocument metaData) {\r
+                       if (metaData == null)\r
+                               return new float[]{0, 0};\r
 \r
-               protected void SetResolution() {\r
                        ResolutionConfigurationCollection rcc = 
-                               (ResolutionConfigurationCollection)
-                               ConfigurationSettings.GetConfig("system.drawing/codecsmetadata");
+                               (ResolutionConfigurationCollection)\r
+                               ConfigurationSettings.GetConfig ("mainsoft.drawing/codecsmetadata");
 
                        if (rcc == null)
                                throw new ConfigurationException("Configuration section codecsmetadata not found");
 
                        ResolutionConfiguration rc = rcc[ ImageFormat.ToString() ];
 
+                       if (rc == null)
+                               return new float[]{0, 0};
+
                        // Horizontal resolution
                        string xResPath = rc.XResPath;
                        string xRes;
@@ -444,7 +563,7 @@ namespace Mainsoft.Drawing.Services {
                        if (xResPath == string.Empty)
                                xRes = rc.XResDefault;
                        else
-                               xRes = GetValueFromMetadata(xResPath);
+                               xRes = GetValueFromMetadata(metaData, xResPath);
 
                        if ((xRes == null) || (xRes == string.Empty))
                                xRes = rc.XResDefault;
@@ -456,7 +575,7 @@ namespace Mainsoft.Drawing.Services {
                        if (yResPath == string.Empty)
                                yRes = rc.YResDefault;
                        else
-                               yRes = GetValueFromMetadata(yResPath);
+                               yRes = GetValueFromMetadata(metaData, yResPath);
 
                        if ((yRes == null) || (yRes == string.Empty))
                                yRes = rc.YResDefault;
@@ -468,19 +587,38 @@ namespace Mainsoft.Drawing.Services {
                        if (resUnitsPath == string.Empty)
                                resUnitsType = rc.UnitsTypeDefault;
                        else
-                               resUnitsType = GetValueFromMetadata(resUnitsPath);
+                               resUnitsType = GetValueFromMetadata(metaData, resUnitsPath);
+
+                       if (resUnitsType == null)
+                               resUnitsType = rc.UnitsTypeDefault;
 
                        // Unit scale
                        string unitScale = rc.UnitsScale[resUnitsType].ToString();
 
                        // Adjust resolution to its units
-                       _imageHorizontalResolution = ParseFloatValue(xRes) * ParseFloatValue(unitScale);
-                       _imageVerticalResolution = ParseFloatValue(yRes) * ParseFloatValue(unitScale);
+                       float [] res = new float[2];
+                       res[0] = ParseFloatValue(xRes) * ParseFloatValue(unitScale);
+                       res[1] = ParseFloatValue(yRes) * ParseFloatValue(unitScale);
+
+                       return res;
                }\r
 \r
+               private string GetValueFromMetadata(XmlDocument metaData, string path) {\r
+                       XmlNode n = metaData.SelectSingleNode(path);\r
+                       if (n == null)\r
+                               return null;\r
+\r
+                       return n.InnerText;\r
+               }\r
+\r
+               private XmlDocument ConvertImageMetadata(imageio.metadata.IIOMetadata metaData) {\r
+                       string [] formatNames = metaData.getMetadataFormatNames();
+                       dom.Element rootNode = (dom.Element) metaData.getAsTree(formatNames[0]);
+
+                       XmlDocument _metadataDocument = new XmlDocument();\r
+                       XmlConvert(rootNode, _metadataDocument);\r
 \r
-               protected string GetValueFromMetadata(string path) {\r
-                       return MetadataDocument.SelectSingleNode(path).InnerText;\r
+                       return _metadataDocument;\r
                }\r
 \r
                private void XmlConvert(dom.Node jNode, XmlNode nNode) {\r
@@ -542,5 +680,21 @@ namespace Mainsoft.Drawing.Services {
 \r
                #endregion\r
 \r
+               #region IDisposable members\r
+\r
+               public void Dispose() {\r
+                       if (NativeReader != null) {\r
+                               NativeReader.dispose();\r
+                               NativeReader = null;\r
+                       }\r
+\r
+                       if (NativeWriter != null) {\r
+                               NativeWriter.dispose();\r
+                               NativeWriter = null;\r
+                       }\r
+               }\r
+\r
+               #endregion\r
+\r
        }\r
 }\r