using System; using System.Configuration; using System.Collections; using System.Collections.Specialized; using System.Drawing.Imaging; using System.Xml; using Mainsoft.Drawing.Configuration; using imageio = javax.imageio; using stream = javax.imageio.stream; using awt = java.awt; using image = java.awt.image; using spi = javax.imageio.spi; using dom = org.w3c.dom; namespace Mainsoft.Drawing.Imaging { /// /// Summary description for ImageCodec. /// public class ImageCodec : IDisposable { #region Members imageio.ImageReader _nativeReader = null; imageio.ImageWriter _nativeWriter = null; stream.ImageInputStream _nativeStream = null; ImageFormat _imageFormat = null; int _currentFrame = 0; #endregion #region Constructros protected ImageCodec() { } static ImageCodec() { } #endregion #region Internal properties internal imageio.ImageReader NativeReader { get { return _nativeReader; } set { _nativeReader = value; if (value == null) return; _imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() ); } } internal imageio.ImageWriter NativeWriter { get { return _nativeWriter; } set { _nativeWriter = value; if (value == null) return; _imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() ); } } internal stream.ImageInputStream NativeStream { get { return _nativeStream; } set { _nativeStream = value; if (value == null) return; if (NativeReader != null) NativeReader.setInput( value ); if (NativeWriter != null) NativeWriter.setOutput( value ); } } #endregion #region ImageCodec factory methods public static ImageCodec CreateReader(stream.ImageInputStream inputStream) { java.util.Iterator iter = imageio.ImageIO.getImageReaders( inputStream ); return CreateReader(iter); } public static ImageCodec CreateReader(ImageFormat imageFormat) { return CreateReader( ImageFormatToClsid( imageFormat ) ); } public static ImageCodec CreateReader(Guid clsid) { ImageCodec codec = null; try { ImageCodecInfo codecInfo = FindDecoder(clsid); java.util.Iterator iter = imageio.ImageIO.getImageReadersByMIMEType( codecInfo.MimeType ); codec = CreateReader(iter); } catch {} if (codec == null) { ImageFormat format = ClsidToImageFormat(clsid); string name = (format != null) ? format.ToString() : clsid.ToString(); throw new NotSupportedException(String.Format("The '{0}' format decoder is not installed.", name)); } return codec; } private static ImageCodec CreateReader(java.util.Iterator iter) { if ( !iter.hasNext() ) return null; ImageCodec imageCodec = new ImageCodec(); imageCodec.NativeReader = (imageio.ImageReader) iter.next(); return imageCodec; } public static ImageCodec CreateWriter(ImageFormat imageFormat) { return CreateWriter( ImageFormatToClsid( imageFormat ) ); } public static ImageCodec CreateWriter(Guid clsid) { ImageCodec codec = null; try { ImageCodecInfo codecInfo = FindEncoder(clsid); java.util.Iterator iter = imageio.ImageIO.getImageWritersByMIMEType( codecInfo.MimeType ); codec = CreateWriter(iter); } catch {} if (codec == null) { ImageFormat format = ClsidToImageFormat(clsid); string name = (format != null) ? format.ToString() : clsid.ToString(); throw new NotSupportedException(String.Format("The '{0}' format encoder is not installed.", name)); } return codec; } private static ImageCodec CreateWriter(java.util.Iterator iter) { if ( !iter.hasNext() ) return null; ImageCodec imageCodec = new ImageCodec(); imageCodec.NativeWriter = (imageio.ImageWriter) iter.next(); return imageCodec; } #endregion #region Codec enumerations internal static Hashtable Decoders { get { const string MYNAME = "System.Drawing.Imaging.ImageCodecInfo.decoders"; Hashtable o = (Hashtable) AppDomain.CurrentDomain.GetData (MYNAME); if (o != null) return o; o = new ReaderSpiIterator().Iterate(); AppDomain.CurrentDomain.SetData(MYNAME, o); return o; } } internal static Hashtable Encoders { get { const string MYNAME = "System.Drawing.Imaging.ImageCodecInfo.encoders"; Hashtable o = (Hashtable) AppDomain.CurrentDomain.GetData (MYNAME); if (o != null) return o; o = new WriterSpiIterator().Iterate(); AppDomain.CurrentDomain.SetData(MYNAME, o); return o; } } internal static ImageCodecInfo FindEncoder (Guid 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) { ImageCodecInfo codec = (ImageCodecInfo) Decoders[clsid]; if (codec == null) { ImageFormat format = ClsidToImageFormat(clsid); string name = (format != null) ? format.ToString() : clsid.ToString(); throw new NotSupportedException(String.Format("The '{0}' format decoder is not installed.", name)); } return codec; } #endregion #region SpiIterators abstract class BaseSpiIterator { protected abstract java.util.Iterator GetIterator (string mimeType); protected abstract spi.ImageReaderWriterSpi GetNext (java.util.Iterator iter); #region ProcessOneCodec 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 = 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.Version = (int)Convert.ToDouble(rw.getVersion ()); } catch (Exception) { ici.Version = 1; } break; } return ici; } #endregion internal Hashtable Iterate () { // TBD: Insert Exception handling here NameValueCollection nvc = (NameValueCollection) System.Configuration.ConfigurationSettings .GetConfig ("system.drawing/codecs"); Hashtable codecs = new Hashtable (10); for (int i=0; i 0) { thArray = new awt.Image[ tmbNumber ]; for (int i = 0; i < tmbNumber; i++) { thArray[i] = NativeReader.readThumbnail(frameIndex, i); } } } return thArray; } catch (java.io.IOException ex) { throw new System.IO.IOException(ex.Message, ex); } } #endif internal void WritePlainImage(PlainImageCollection pic) { if ((pic == null) || (pic.Count == 0)) return; if (pic.Count == 1) { WritePlainImage( pic[0] ); return; } try { if (NativeWriter.canWriteSequence ()) { NativeWriter.prepareWriteSequence (null); for (int i=0; i < pic.Count; i++) { imageio.IIOImage iio = GetIIOImageContainer( pic[i] ); NativeWriter.writeToSequence (iio, null); } NativeWriter.endWriteSequence (); } else WritePlainImage( pic[0] ); } catch (java.io.IOException ex) { throw new System.IO.IOException(ex.Message, ex); } } internal void WritePlainImage(PlainImage pi) { try { imageio.IIOImage iio = GetIIOImageContainer( pi ); WriteImage( iio ); } catch (java.io.IOException ex) { throw new System.IO.IOException(ex.Message, ex); } } private void WriteImage(imageio.IIOImage iio) { if (NativeStream == null) throw new Exception("Output stream not specified"); NativeWriter.write( iio ); } private imageio.IIOImage GetIIOImageContainer(PlainImage pi) { java.util.ArrayList al = null; // prepare thumbnails list if (pi.Thumbnails != null) { al = new java.util.ArrayList( pi.Thumbnails.Length ); for (int i=0; i < pi.Thumbnails.Length; i++) al.add(pi.Thumbnails[i]); } // prepare IIOImage container if (pi.NativeImage is image.BufferedImage) { imageio.IIOImage iio = new javax.imageio.IIOImage( (image.BufferedImage)pi.NativeImage, al, null /*pi.NativeMetadata*/); return iio; } else // TBD: This codec is for raster formats only throw new NotSupportedException("Only raster formats are supported"); } private imageio.metadata.IIOMetadata ReadImageMetadata(int frameIndex) { if (NativeStream == null) throw new Exception("Input stream not specified"); try { imageio.metadata.IIOMetadata md = NativeReader.getImageMetadata( frameIndex ); return md; } catch (java.io.IOException ex) { throw new System.IO.IOException(ex.Message, ex); } } #endregion #region Extra properties public ImageFormat ImageFormat { get { return _imageFormat; } } #endregion #region Metadata parse private float [] GetResolution(XmlDocument metaData) { if (metaData == null) return new float[]{0, 0}; ResolutionConfigurationCollection rcc = (ResolutionConfigurationCollection) ConfigurationSettings.GetConfig("system.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; if (xResPath == string.Empty) xRes = rc.XResDefault; else xRes = GetValueFromMetadata(metaData, xResPath); if ((xRes == null) || (xRes == string.Empty)) xRes = rc.XResDefault; // Vertical resolution string yResPath = rc.YResPath; string yRes; if (yResPath == string.Empty) yRes = rc.YResDefault; else yRes = GetValueFromMetadata(metaData, yResPath); if ((yRes == null) || (yRes == string.Empty)) yRes = rc.YResDefault; // Resolution units string resUnitsPath = rc.UnitsTypePath; string resUnitsType; if (resUnitsPath == string.Empty) resUnitsType = rc.UnitsTypeDefault; else resUnitsType = GetValueFromMetadata(metaData, resUnitsPath); if (resUnitsType == null) resUnitsType = rc.UnitsTypeDefault; // Unit scale string unitScale = rc.UnitsScale[resUnitsType].ToString(); // Adjust resolution to its units float [] res = new float[2]; res[0] = ParseFloatValue(xRes) * ParseFloatValue(unitScale); res[1] = ParseFloatValue(yRes) * ParseFloatValue(unitScale); return res; } private string GetValueFromMetadata(XmlDocument metaData, string path) { XmlNode n = metaData.SelectSingleNode(path); if (n == null) return null; return n.InnerText; } private XmlDocument ConvertImageMetadata(imageio.metadata.IIOMetadata metaData) { string [] formatNames = metaData.getMetadataFormatNames(); dom.Element rootNode = (dom.Element) metaData.getAsTree(formatNames[0]); XmlDocument _metadataDocument = new XmlDocument(); XmlConvert(rootNode, _metadataDocument); return _metadataDocument; } private void XmlConvert(dom.Node jNode, XmlNode nNode) { XmlDocument document = nNode.OwnerDocument; if (document == null) document = (XmlDocument)nNode; XmlNode n = null; switch (jNode.getNodeType()) { case 1 : n = document.CreateNode(XmlNodeType.Element, jNode.getNodeName(), jNode.getNamespaceURI()); break; case 4 : n = document.CreateNode(XmlNodeType.CDATA, jNode.getNodeName(), jNode.getNamespaceURI()); break; default: return; } //set value n.InnerText = jNode.getNodeValue(); nNode.AppendChild( n ); //copy attributes org.w3c.dom.NamedNodeMap nm = jNode.getAttributes(); for (int i=0; i