2 // System.Drawing.Image.cs
4 // (C) 2002 Ximian, Inc. http://www.ximian.com
5 // Author: Christian Meyer (Christian.Meyer@cs.tum.edu)
6 // Alexandre Pigolkine (pigolkine@gmx.de)
7 // Jordi Mas i Hernandez (jordi@ximian.com)
9 namespace System.Drawing {
12 using System.Runtime.Remoting;
13 using System.Runtime.Serialization;
14 using System.Runtime.InteropServices;
15 using System.ComponentModel;
17 using System.Drawing.Imaging;
20 using Mainsoft.Drawing.Imaging;
22 using BufferedImage = java.awt.image.BufferedImage;
25 using javax.imageio.stream;
28 using image = java.awt.image;
30 public abstract class Image : MarshalByRefObject, IDisposable , ICloneable {
32 PlainImageCollection _nativeObject = new PlainImageCollection();
33 protected int _flags = 0;
35 //consider using Image[] to support many thumbnails per Image
40 protected enum ImageFlags {
42 ImageFlagsScalable = 0x0001,
43 ImageFlagsHasAlpha = 0x0002,
44 ImageFlagsHasTranslucent = 0x0004,
45 ImageFlagsPartiallyScalable = 0x0008,
46 ImageFlagsColorSpaceRGB = 0x0010,
47 ImageFlagsColorSpaceCMYK = 0x0020,
48 ImageFlagsColorSpaceGRAY = 0x0040,
49 ImageFlagsColorSpaceYCBCR = 0x0080,
50 ImageFlagsColorSpaceYCCK = 0x0100,
51 ImageFlagsHasRealDPI = 0x1000,
52 ImageFlagsHasRealPixelSize = 0x2000,
53 ImageFlagsReadOnly = 0x00010000,
54 ImageFlagsCaching = 0x00020000
59 public void Dispose () {
62 protected virtual void DisposeResources () {
65 protected virtual void Dispose (bool disposing) {
68 // Derived classes must call Initialize () when they use this constructor
72 protected Image (java.awt.Image nativeObject) : this(nativeObject, ImageFormat.MemoryBmp) {
75 protected Image (java.awt.Image nativeObject, ImageFormat format) {
76 PlainImage pi = new PlainImage( nativeObject, null, format, 0, 0, FrameDimension.Page );
77 Initialize( pi, false );
80 protected void Initialize (PlainImage pi, bool addToCollection) {
84 NativeObject.Add( pi );
91 internal PlainImageCollection NativeObject {
97 internal PlainImage CurrentImage {
99 return NativeObject.CurrentImage;
107 public static Image FromFile(string filename) {
108 //FIXME: check if it's not a metafile, throw NotImplementedException
109 return new Bitmap (filename);
113 public static Image FromFile(string filename, bool useIcm) {
114 //FIXME: check if it's not a metafile, throw NotImplementedException
115 return new Bitmap (filename, useIcm);
119 #region GetThumbnailImageAbort
121 public delegate bool GetThumbnailImageAbort();
125 public abstract object Clone();
131 public static Image FromStream (Stream stream) {
132 //FIXME: check if it's not a metafile, throw NotImplementedException
133 return new Bitmap (stream);
137 public static Image FromStream (Stream stream, bool useIcm) {
138 //FIXME: check if it's not a metafile, throw NotImplementedException
139 return new Bitmap (stream, useIcm);
143 #region GetPixelFormatSize
144 public static int GetPixelFormatSize(PixelFormat pixfmt) {
148 case PixelFormat.Format16bppArgb1555:
149 case PixelFormat.Format16bppGrayScale:
150 case PixelFormat.Format16bppRgb555:
151 case PixelFormat.Format16bppRgb565:
154 case PixelFormat.Format1bppIndexed:
157 case PixelFormat.Format24bppRgb:
160 case PixelFormat.Format32bppArgb:
161 case PixelFormat.Format32bppPArgb:
162 case PixelFormat.Format32bppRgb:
165 case PixelFormat.Format48bppRgb:
168 case PixelFormat.Format4bppIndexed:
171 case PixelFormat.Format64bppArgb:
172 case PixelFormat.Format64bppPArgb:
175 case PixelFormat.Format8bppIndexed:
183 #region IsAlphaPixelFormat
184 public static bool IsAlphaPixelFormat(PixelFormat pixfmt) {
185 return (pixfmt & PixelFormat.Alpha) != PixelFormat.Undefined;
189 #region IsCanonicalPixelFormat
190 // TBD: implement this
191 public static bool IsCanonicalPixelFormat (PixelFormat pixfmt) {
192 return (pixfmt & PixelFormat.Canonical) != PixelFormat.Undefined;
196 #region IsExtendedPixelFormat
197 // TBD: implement this
198 public static bool IsExtendedPixelFormat (PixelFormat pixfmt) {
199 return (pixfmt & PixelFormat.Extended) != PixelFormat.Undefined;
205 public RectangleF GetBounds (ref GraphicsUnit pageUnit) {
206 pageUnit = GraphicsUnit.Pixel; //java.awt.Image always returns pixels
207 return new RectangleF((float)0,(float)0,(float)Width,(float)Height);
211 #region GetEncoderParameterList
213 public EncoderParameters GetEncoderParameterList(Guid encoder) {
214 throw new NotImplementedException ();
218 #region GetFrameCount
219 public int GetFrameCount(FrameDimension dimension) {
220 // FALLBACK: now, only one dimension assigned for all frames
221 if (dimension.Guid != CurrentImage.Dimension.Guid)
222 throw new ArgumentException ("dimension");
224 return NativeObject.Count;
228 #region GetPropertyItem
230 public PropertyItem GetPropertyItem(int propid) {
231 throw new NotImplementedException ();
235 #region RemovePropertyItem
237 public void RemovePropertyItem (int propid) {
238 throw new NotImplementedException ();
243 public void RotateFlip (RotateFlipType rotateFlipType) {
244 awt.geom.AffineTransform tx;
246 if ( !(CurrentImage.NativeImage is image.BufferedImage) )
247 // TBD: This implementation is for raster formats only
248 throw new NotImplementedException("Only raster formats are supported");
250 switch (rotateFlipType) {
251 case RotateFlipType.RotateNoneFlipNone :
254 case RotateFlipType.Rotate90FlipNone :
255 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
256 tx.translate( 0, -Height );
259 case RotateFlipType.Rotate180FlipNone :
260 tx = awt.geom.AffineTransform.getScaleInstance(-1, -1);
261 tx.translate( -Width, -Height );
264 case RotateFlipType.Rotate270FlipNone :
265 tx = awt.geom.AffineTransform.getRotateInstance(-Math.PI / 2);
266 tx.translate( -Width, 0 );
269 case RotateFlipType.RotateNoneFlipX :
270 tx = awt.geom.AffineTransform.getScaleInstance(-1, 1);
271 tx.translate( -Width, 0 );
274 case RotateFlipType.Rotate90FlipX :
275 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
279 case RotateFlipType.Rotate180FlipX :
280 tx = awt.geom.AffineTransform.getScaleInstance(1, -1);
281 tx.translate( 0, -Height );
284 case RotateFlipType.Rotate270FlipX :
285 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
287 tx.translate( -Width, -Height );
291 throw new ArgumentOutOfRangeException();
293 image.AffineTransformOp op = new image.AffineTransformOp(tx, image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
294 CurrentImage.NativeImage = op.filter((BufferedImage)CurrentImage.NativeImage, null);
299 protected abstract void InternalSave (ImageOutputStream output, Guid clsid);
302 public void Save (Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) {
303 //TBD: implement encoderParams
305 throw new ArgumentNullException("Value cannot be null.");
308 java.io.OutputStream jos = vmw.common.IOUtils.ToOutputStream (stream);
309 MemoryCacheImageOutputStream output = new MemoryCacheImageOutputStream(jos);
310 InternalSave (output, encoder.Clsid);
313 catch (java.io.IOException ex) {
314 throw new System.IO.IOException(ex.Message, ex);
318 public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams) {
319 using (Stream outputStream = new FileStream(filename, FileMode.Create))
320 Save(outputStream, encoder, encoderParams);
323 public void Save (string filename) {
324 Save (filename, ImageFormat.Png);
327 public void Save (Stream stream, ImageFormat format) {
328 ImageCodecInfo encoder = ImageCodec.FindEncoder ( ImageCodec.ImageFormatToClsid (format) );
329 Save (stream, encoder, null);
332 public void Save(string filename, ImageFormat format) {
333 using (Stream outputStream = new FileStream(filename, FileMode.Create))
334 Save(outputStream, format);
340 public void SaveAdd(EncoderParameters encoderParams) {
341 throw new NotImplementedException ();
345 public void SaveAdd(Image image, EncoderParameters encoderParams) {
346 throw new NotImplementedException ();
350 #region SelectActiveFrame
352 // TBD: .Net does not load all frames at the initialization. New frames loaded by request.
354 public int SelectActiveFrame(FrameDimension dimension, int frameIndex) {
355 // FALLBACK: now, only one dimension assigned for all frames
356 if (dimension.Guid != CurrentImage.Dimension.Guid)
357 throw new ArgumentException ("dimension");
359 if (frameIndex < NativeObject.Count)
360 NativeObject.CurrentImageIndex = frameIndex;
366 #region SetPropertyItem
368 public void SetPropertyItem(PropertyItem propitem) {
369 throw new NotImplementedException ();
376 // TDB: ImageFlagsScalable, ImageFlagsHasTranslucent, ImageFlagsPartiallyScalable, ImageFlagsCaching
379 image.ColorModel colorModel = ((BufferedImage)CurrentImage.NativeImage).getColorModel();
380 int t = colorModel.getColorSpace().getType();
382 if (t == awt.color.ColorSpace.TYPE_RGB)
383 _flags |= (int)ImageFlags.ImageFlagsColorSpaceRGB;
384 else if (t == awt.color.ColorSpace.TYPE_CMYK)
385 _flags |= (int)ImageFlags.ImageFlagsColorSpaceCMYK;
386 else if (t == awt.color.ColorSpace.TYPE_GRAY)
387 _flags |= (int)ImageFlags.ImageFlagsColorSpaceGRAY;
388 else if (t == awt.color.ColorSpace.TYPE_YCbCr)
389 _flags |= (int)ImageFlags.ImageFlagsColorSpaceYCBCR;
391 if (colorModel.hasAlpha())
392 _flags |= (int)ImageFlags.ImageFlagsHasAlpha;
394 if ((CurrentImage.HorizontalResolution > 0) || (CurrentImage.VerticalResolution > 0))
395 _flags |= (int)ImageFlags.ImageFlagsHasRealDPI;
402 #region FrameDimensionsList
404 public Guid[] FrameDimensionsList {
405 // TBD: look over all frames and build array of dimensions
406 // FALLBACK: now, only one dimension assigned for all frames
408 Guid [] dimList = new Guid[]{CurrentImage.Dimension.Guid};
417 return CurrentImage.NativeImage.getHeight(null);
422 #region HorizontalResolution
423 public float HorizontalResolution {
425 if (CurrentImage.HorizontalResolution <= 1)
426 return Graphics.DefaultScreenResolution;
428 return CurrentImage.HorizontalResolution;
435 public ColorPalette Palette {
437 if (!(CurrentImage.NativeImage is BufferedImage))
438 // TBD: This implementation is for raster formats only
439 throw new NotImplementedException("Only raster formats are supported");
441 image.ColorModel colorModel = ((BufferedImage)CurrentImage.NativeImage).getColorModel();
442 if (colorModel is image.IndexColorModel) {
444 Color [] colors = new Color[ ((image.IndexColorModel)colorModel).getMapSize() ];
445 for (int i=0; i<colors.Length; i++) {
446 colors[i] = Color.FromArgb( ((image.IndexColorModel)colorModel).getRGB(i) );
448 ColorPalette palette = new ColorPalette(0, colors);
451 return new ColorPalette();
454 throw new NotImplementedException ();
459 #region PhysicalDimension
460 public SizeF PhysicalDimension {
462 return new Size(Width, Height);
468 abstract protected PixelFormat InternalPixelFormat {get;}
470 public PixelFormat PixelFormat {
472 return InternalPixelFormat;
477 #region PropertiIdList
479 public int[] PropertyIdList {
481 throw new NotImplementedException ();
488 public PropertyItem[] PropertyItems {
490 throw new NotImplementedException ();
496 public ImageFormat RawFormat {
498 return CurrentImage.ImageFormat;
506 return new Size(Width, Height);
511 #region VerticalResolution
512 public float VerticalResolution {
514 if (CurrentImage.VerticalResolution <= 1)
515 return Graphics.DefaultScreenResolution;
517 return CurrentImage.VerticalResolution;
525 return CurrentImage.NativeImage.getWidth(null);
530 public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData) {
533 #if THUMBNAIL_SUPPORTED
534 if (CurrentImage.Thumbnails != null) {
535 for (int i=0; i < CurrentImage.Thumbnails.Length; i++)
536 if (CurrentImage.Thumbnails[i] != null) {
537 img = CurrentImage.Thumbnails[i];
538 if (img.getHeight(null) == thumbHeight && img.getWidth(null) == thumbWidth)
539 return ImageFromNativeImage(img, RawFormat);
543 img = CurrentImage.NativeImage.getScaledInstance(thumbWidth, thumbHeight, awt.Image.SCALE_DEFAULT);
545 return ImageFromNativeImage(img, RawFormat);
549 public static Bitmap FromHbitmap(IntPtr hbitmap)
551 throw new NotImplementedException ();
555 public static Bitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
557 throw new NotImplementedException ();
561 internal static Image ImageFromNativeImage(awt.Image nativeImage, ImageFormat format) {
562 if (nativeImage is BufferedImage)
563 return new Bitmap(nativeImage, format);
565 throw new ArgumentException("Invalid image type");
568 protected abstract awt.Image [] CloneNativeObjects(awt.Image [] src);