\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
get { return _nativeReader; }\r
set { \r
_nativeReader = value; \r
+ if (value == null)\r
+ return;\r
_imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() );\r
}\r
}\r
get { return _nativeWriter; }\r
set { \r
_nativeWriter = value; \r
+ if (value == null)\r
+ return;\r
_imageFormat = MimeTypesToImageFormat( value.getOriginatingProvider().getMIMETypes() );\r
}\r
}\r
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
}\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
}\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
}
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
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;
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;
}
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;
if (xResPath == string.Empty)
xRes = rc.XResDefault;
else
- xRes = GetValueFromMetadata(xResPath);
+ xRes = GetValueFromMetadata(metaData, xResPath);
if ((xRes == null) || (xRes == string.Empty))
xRes = rc.XResDefault;
if (yResPath == string.Empty)
yRes = rc.YResDefault;
else
- yRes = GetValueFromMetadata(yResPath);
+ yRes = GetValueFromMetadata(metaData, yResPath);
if ((yRes == null) || (yRes == string.Empty))
yRes = rc.YResDefault;
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
\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