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 ("mainsoft.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 ("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;
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