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 {
\r
42 ImageFlagsScalable = 0x0001,
\r
43 ImageFlagsHasAlpha = 0x0002,
\r
44 ImageFlagsHasTranslucent = 0x0004,
\r
45 ImageFlagsPartiallyScalable = 0x0008,
\r
46 ImageFlagsColorSpaceRGB = 0x0010,
\r
47 ImageFlagsColorSpaceCMYK = 0x0020,
\r
48 ImageFlagsColorSpaceGRAY = 0x0040,
\r
49 ImageFlagsColorSpaceYCBCR = 0x0080,
\r
50 ImageFlagsColorSpaceYCCK = 0x0100,
\r
51 ImageFlagsHasRealDPI = 0x1000,
\r
52 ImageFlagsHasRealPixelSize = 0x2000,
\r
53 ImageFlagsReadOnly = 0x00010000,
\r
54 ImageFlagsCaching = 0x00020000
\r
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;
106 public static Image FromFile(string filename) {
107 //FIXME: check if it's not a metafile, throw NotImplementedException
108 return new Bitmap (filename);
111 public static Image FromFile(string filename, bool useIcm) {
112 //FIXME: check if it's not a metafile, throw NotImplementedException
113 return new Bitmap (filename, useIcm);
117 #region GetThumbnailImageAbort
119 public delegate bool GetThumbnailImageAbort();
123 public virtual object Clone() {
124 throw new NotImplementedException ("Must be implemented in child class");
130 public static Image FromStream (Stream stream) {
131 //FIXME: check if it's not a metafile, throw NotImplementedException
132 return new Bitmap (stream);
135 public static Image FromStream (Stream stream, bool useIcm) {
136 //FIXME: check if it's not a metafile, throw NotImplementedException
137 return new Bitmap (stream, useIcm);
141 #region GetPixelFormatSize
142 public static int GetPixelFormatSize(PixelFormat pixfmt) {
146 case PixelFormat.Format16bppArgb1555:
147 case PixelFormat.Format16bppGrayScale:
148 case PixelFormat.Format16bppRgb555:
149 case PixelFormat.Format16bppRgb565:
152 case PixelFormat.Format1bppIndexed:
155 case PixelFormat.Format24bppRgb:
158 case PixelFormat.Format32bppArgb:
159 case PixelFormat.Format32bppPArgb:
160 case PixelFormat.Format32bppRgb:
163 case PixelFormat.Format48bppRgb:
166 case PixelFormat.Format4bppIndexed:
169 case PixelFormat.Format64bppArgb:
170 case PixelFormat.Format64bppPArgb:
173 case PixelFormat.Format8bppIndexed:
181 #region IsAlphaPixelFormat
182 public static bool IsAlphaPixelFormat(PixelFormat pixfmt) {
183 return (pixfmt & PixelFormat.Alpha) != PixelFormat.Undefined;
187 #region IsCanonicalPixelFormat
188 // TBD: implement this
189 public static bool IsCanonicalPixelFormat (PixelFormat pixfmt) {
190 return (pixfmt & PixelFormat.Canonical) != PixelFormat.Undefined;
194 #region IsExtendedPixelFormat
195 // TBD: implement this
196 public static bool IsExtendedPixelFormat (PixelFormat pixfmt) {
197 return (pixfmt & PixelFormat.Extended) != PixelFormat.Undefined;
203 public RectangleF GetBounds (ref GraphicsUnit pageUnit) {
204 pageUnit = GraphicsUnit.Pixel; //java.awt.Image always returns pixels
205 return new RectangleF((float)0,(float)0,(float)Width,(float)Height);
209 #region GetEncoderParameterList
210 // TBD: implement this
211 public EncoderParameters GetEncoderParameterList(Guid encoder) {
212 throw new NotImplementedException ();
216 #region GetFrameCount
217 public int GetFrameCount(FrameDimension dimension) {
218 // FALLBACK: now, only one dimension assigned for all frames
219 if (dimension.Guid != CurrentImage.Dimension.Guid)
220 throw new ArgumentException ("dimension");
222 return NativeObject.Count;
226 #region GetPropertyItem
227 // TBD: implement this
228 public PropertyItem GetPropertyItem(int propid) {
229 throw new NotImplementedException ();
233 #region RemovePropertyItem
234 // TBD: implement this
235 public void RemovePropertyItem (int propid) {
236 throw new NotImplementedException ();
241 public void RotateFlip (RotateFlipType rotateFlipType) {
242 awt.geom.AffineTransform tx;
244 if ( !(CurrentImage.NativeImage is image.BufferedImage) )
245 // TBD: This implementation is for raster formats only
246 throw new NotImplementedException("Only raster formats are supported");
248 switch (rotateFlipType) {
249 case RotateFlipType.RotateNoneFlipNone :
252 case RotateFlipType.Rotate90FlipNone :
253 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
254 tx.translate( 0, -Height );
257 case RotateFlipType.Rotate180FlipNone :
258 tx = awt.geom.AffineTransform.getScaleInstance(-1, -1);
259 tx.translate( -Width, -Height );
262 case RotateFlipType.Rotate270FlipNone :
263 tx = awt.geom.AffineTransform.getRotateInstance(-Math.PI / 2);
264 tx.translate( -Width, 0 );
267 case RotateFlipType.RotateNoneFlipX :
268 tx = awt.geom.AffineTransform.getScaleInstance(-1, 1);
269 tx.translate( -Width, 0 );
272 case RotateFlipType.Rotate90FlipX :
273 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
277 case RotateFlipType.Rotate180FlipX :
278 tx = awt.geom.AffineTransform.getScaleInstance(1, -1);
279 tx.translate( 0, -Height );
282 case RotateFlipType.Rotate270FlipX :
283 tx = awt.geom.AffineTransform.getRotateInstance(Math.PI / 2);
285 tx.translate( -Width, -Height );
289 throw new ArgumentOutOfRangeException();
291 image.AffineTransformOp op = new image.AffineTransformOp(tx, image.AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
\r
292 CurrentImage.NativeImage = op.filter((BufferedImage)CurrentImage.NativeImage, null);
\r
297 protected abstract void InternalSave (ImageOutputStream output, Guid clsid);
299 public void Save (Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) {
300 //TBD: implement encoderParams
301 java.io.OutputStream jos = vmw.common.IOUtils.ToOutputStream (stream);
302 MemoryCacheImageOutputStream output = new MemoryCacheImageOutputStream(jos);
304 InternalSave (output, encoder.Clsid);
307 public void Save(string filename, ImageCodecInfo encoder, EncoderParameters encoderParams) {
308 //TBD: implement encoderParams
309 java.io.File jf = vmw.common.IOUtils.getJavaFile (filename);
310 FileImageOutputStream output = new FileImageOutputStream (jf);
311 InternalSave (output, encoder.Clsid);
314 public void Save (string filename) {
315 Save (filename, ImageFormat.Png);
318 public void Save (Stream stream, ImageFormat format) {
319 Save (stream, ImageCodec.FindEncoder (
320 ImageCodec.ImageFormatToClsid (format)), null);
323 public void Save(string filename, ImageFormat format) {
324 Save (filename, ImageCodec.FindEncoder (
325 ImageCodec.ImageFormatToClsid (format)), null);
330 // TBD: implement this
331 public void SaveAdd(EncoderParameters encoderParams) {
332 throw new NotImplementedException ();
335 public void SaveAdd(Image image, EncoderParameters encoderParams) {
336 throw new NotImplementedException ();
340 #region SelectActiveFrame
342 // TBD: .Net does not load all frames at the initialization. New frames loaded by request.
343 public int SelectActiveFrame(FrameDimension dimension, int frameIndex) {
344 // FALLBACK: now, only one dimension assigned for all frames
345 if (dimension.Guid != CurrentImage.Dimension.Guid)
346 throw new ArgumentException ("dimension");
348 if (frameIndex < NativeObject.Count)
349 NativeObject.CurrentImageIndex = frameIndex;
355 #region SetPropertyItem
356 // TBD: implement this
357 public void SetPropertyItem(PropertyItem propitem) {
358 throw new NotImplementedException ();
365 // TDB: ImageFlagsScalable, ImageFlagsHasTranslucent, ImageFlagsPartiallyScalable, ImageFlagsCaching
367 image.ColorModel colorModel = ((BufferedImage)CurrentImage.NativeImage).getColorModel();
368 int t = colorModel.getColorSpace().getType();
370 if (t == awt.color.ColorSpace.TYPE_RGB)
371 _flags |= (int)ImageFlags.ImageFlagsColorSpaceRGB;
372 else if (t == awt.color.ColorSpace.TYPE_CMYK)
373 _flags |= (int)ImageFlags.ImageFlagsColorSpaceCMYK;
374 else if (t == awt.color.ColorSpace.TYPE_GRAY)
375 _flags |= (int)ImageFlags.ImageFlagsColorSpaceGRAY;
376 else if (t == awt.color.ColorSpace.TYPE_YCbCr)
377 _flags |= (int)ImageFlags.ImageFlagsColorSpaceYCBCR;
379 if (colorModel.hasAlpha())
380 _flags |= (int)ImageFlags.ImageFlagsHasAlpha;
382 if ((CurrentImage.HorizontalResolution > 0) || (CurrentImage.VerticalResolution > 0))
383 _flags |= (int)ImageFlags.ImageFlagsHasRealDPI;
390 #region FrameDimensionsList
391 public Guid[] FrameDimensionsList {
392 // TBD: look over all frames and build array of dimensions
393 // FALLBACK: now, only one dimension assigned for all frames
395 Guid [] dimList = new Guid[]{CurrentImage.Dimension.Guid};
404 return CurrentImage.NativeImage.getHeight(null);
409 #region HorizontalResolution
410 public float HorizontalResolution {
412 if (CurrentImage.HorizontalResolution == 0)
413 return Graphics.DefaultScreenResolution;
415 return CurrentImage.HorizontalResolution;
421 public ColorPalette Palette {
423 if (!(CurrentImage.NativeImage is BufferedImage))
424 // TBD: This implementation is for raster formats only
425 throw new NotImplementedException("Only raster formats are supported");
427 image.ColorModel colorModel = ((BufferedImage)CurrentImage.NativeImage).getColorModel();
428 if (colorModel is image.IndexColorModel) {
430 Color [] colors = new Color[ ((image.IndexColorModel)colorModel).getMapSize() ];
431 for (int i=0; i<colors.Length; i++) {
432 colors[i] = Color.FromArgb( ((image.IndexColorModel)colorModel).getRGB(i) );
434 ColorPalette palette = new ColorPalette(0, colors);
437 return new ColorPalette();
441 throw new NotImplementedException ();
446 #region PhysicalDimension
447 public SizeF PhysicalDimension {
449 return new Size(Width, Height);
455 abstract protected PixelFormat InternalPixelFormat {get;}
457 public PixelFormat PixelFormat {
459 return InternalPixelFormat;
464 #region PropertiIdList
465 // TBD: implement this
466 public int[] PropertyIdList {
468 throw new NotImplementedException ();
474 // TBD: implement this
475 public PropertyItem[] PropertyItems {
477 throw new NotImplementedException ();
483 public ImageFormat RawFormat {
485 return CurrentImage.ImageFormat;
493 return new Size(Width, Height);
498 #region VerticalResolution
499 public float VerticalResolution {
501 if (CurrentImage.VerticalResolution == 0)
502 return Graphics.DefaultScreenResolution;
504 return CurrentImage.VerticalResolution;
512 return CurrentImage.NativeImage.getWidth(null);
517 public Image GetThumbnailImage(int thumbWidth, int thumbHeight, Image.GetThumbnailImageAbort callback, IntPtr callbackData) {
520 #if THUMBNAIL_SUPPORTED
521 if (CurrentImage.Thumbnails != null) {
522 for (int i=0; i < CurrentImage.Thumbnails.Length; i++)
523 if (CurrentImage.Thumbnails[i] != null) {
524 img = CurrentImage.Thumbnails[i];
525 if (img.getHeight(null) == thumbHeight && img.getWidth(null) == thumbWidth)
526 return ImageFromNativeImage(img, RawFormat);
530 img = CurrentImage.NativeImage.getScaledInstance(thumbWidth, thumbHeight, awt.Image.SCALE_DEFAULT);
532 return ImageFromNativeImage(img, RawFormat);
535 public static Bitmap FromHbitmap(IntPtr hbitmap)
537 throw new NotImplementedException ();
540 public static Bitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
542 throw new NotImplementedException ();
546 internal static Image ImageFromNativeImage(awt.Image nativeImage, ImageFormat format) {
547 if (nativeImage is BufferedImage)
548 return new Bitmap(nativeImage, format);
550 throw new ArgumentException("Invalid image type");
553 protected abstract awt.Image [] CloneNativeObjects(awt.Image [] src);