* GraphicsPath.jvm.cs: fixed FillMode, ConvertArcAngle, AddPath, CloseFigure
[mono.git] / mcs / class / System.Drawing / System.Drawing / Bitmap.jvm.cs
1 using System;
2 using System.IO;
3 using System.Drawing.Imaging;
4 using System.Runtime.Serialization;
5 using Mainsoft.Drawing.Imaging;
6
7 using io = java.io;
8 using imageio = javax.imageio;
9 using stream = javax.imageio.stream;
10 using spi = javax.imageio.spi;
11 using BufferedImage = java.awt.image.BufferedImage;
12 using JavaImage = java.awt.Image;
13 using awt = java.awt;
14 using image = java.awt.image;
15
16 namespace System.Drawing 
17 {
18         public sealed class Bitmap : Image {
19
20                 #region constructors
21
22                 Bitmap (PlainImage orig) {
23                         base.Initialize( orig, false );
24                 }
25
26                 private Bitmap (SerializationInfo info, StreamingContext context) {
27                         throw new NotImplementedException ();
28                 }
29
30                 public Bitmap (int width, int height, Graphics g) 
31                         :this (width, height, PixelFormat.Format32bppArgb) {
32                         CurrentImage.HorizontalResolution = g.DpiX;
33                         CurrentImage.VerticalResolution = g.DpiY;
34                 }
35
36                 public Bitmap (Image original) 
37                         :this (original, original.Size) {}
38
39                 public Bitmap (Image orig, Size newSize)
40                         :this (orig, newSize.Width, newSize.Height) {}
41
42                 public Bitmap (Image orig, int width, int height)
43                         :base (CreateScaledImage (orig, width, height), ImageFormat.MemoryBmp) {}
44
45                 internal Bitmap (java.awt.Image nativeObject, ImageFormat format)
46                         :base (nativeObject, format) {}
47
48                 private Bitmap (java.awt.Image nativeObject, ImageFormat format, PixelFormat pixFormat)
49                         :this (nativeObject, format) {
50                         if (pixFormat != this.PixelFormat)
51                                 throw new NotImplementedException ("Converting PixelFormat is not implemented yet.");
52                 }
53
54                 public Bitmap (int width, int height) 
55                         :this (width, height, PixelFormat.Format32bppArgb) {}
56
57                 public Bitmap (int width, int height, PixelFormat format)
58                         :base (
59                         new java.awt.image.BufferedImage (width, height,
60                         ToBufferedImageFormat (format)),
61                         ImageFormat.Bmp) {
62                 }
63
64                 public Bitmap (Stream stream)
65                         :this (stream, false) {}
66
67                 public Bitmap (string filename) 
68                         :this (filename, false) {}
69
70                 public Bitmap (Stream stream, bool useIcm)
71                         :this (stream, useIcm, null) {}
72
73                 public Bitmap (string filename, bool useIcm)
74                         :this (filename, useIcm, null) {}
75
76                 internal Bitmap (Stream stream, bool useIcm, ImageFormat format) {
77                         // TBD: useIcm param
78                         io.InputStream jis = vmw.common.IOUtils.ToInputStream (stream);
79             Initialize (new stream.MemoryCacheImageInputStream (jis), format);
80                 }
81
82                 internal Bitmap (string filename, bool useIcm, ImageFormat format) {
83                         // TBD: useIcm param
84                         java.io.File file = vmw.common.IOUtils.getJavaFile (filename);
85                         if (!file.exists ())
86                                  throw new System.IO.FileNotFoundException (filename);
87                         Initialize (new stream.FileImageInputStream (file), format);
88                 }
89
90                 public Bitmap (Type type, string resource) {
91                         using (Stream s = type.Assembly.GetManifestResourceStream (resource)) {
92                                 if (s == null)
93                                         throw new ArgumentException("Resource '" + resource + "' could not be found in class '" + type.ToString() + "'");
94
95                                 io.InputStream jis = vmw.common.IOUtils.ToInputStream (s);
96                                 Initialize (new stream.MemoryCacheImageInputStream (jis), null);
97                         }
98                 }
99 #if INTPTR_SUPPORT
100                 public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
101                 {                                               
102                         throw new NotImplementedException();                    
103                 }
104 #endif
105                 #endregion
106
107                 #region Internal Initialization
108
109                 private void Initialize (stream.ImageInputStream input, ImageFormat format) {
110                         ImageCodec ic = null;
111
112                         if (format == null)
113                                 ic = ImageCodec.CreateReader(input);
114                         else
115                                 ic = ImageCodec.CreateReader(format);
116
117                         try {
118                                 ic.NativeStream = input;
119                                 PlainImage pi = ic.ReadPlainImage();
120                                 base.Initialize( pi, false );
121
122                                 pi = ic.ReadNextPlainImage();
123                                 while ( pi != null) {
124                                         base.Initialize( pi, true );
125                                         pi = ic.ReadNextPlainImage();
126                                 }
127
128                                 _flags |= (int)(ImageFlags.ImageFlagsReadOnly | ImageFlags.ImageFlagsHasRealPixelSize);
129                         }
130                         catch (IOException ex) {
131                                 throw ex;
132                         }
133                         catch (Exception) {
134                                 throw new OutOfMemoryException ("Out of memory");
135                         }
136                 }
137
138                 #endregion
139
140                 #region InternalSave
141                 protected override void InternalSave (stream.ImageOutputStream output, Guid clsid) {
142
143                         ImageCodec ic = ImageCodec.CreateWriter( clsid );
144
145                         // .net saves in png if cannot find requested encoder. act id 316563
146                         if (ic == null)
147                                 ic = ImageCodec.CreateWriter( ImageFormat.Png );
148
149                         if (ic != null) {
150                                 ic.NativeStream = output;
151                                 ic.WritePlainImage( CurrentImage );
152                                 
153                                 try {
154                                         output.close();
155                                 }
156                                 catch (java.io.IOException ex) {
157                                         throw new System.IO.IOException(ex.Message, ex);
158                                 }
159                         }
160                         else {
161                                 throw new NotSupportedException("The requested format encoder is not supported");
162                         }
163                 }
164
165                 #endregion
166
167                 #region private statics: ToBufferedImageFormat, CreateScaledImage
168
169                 private static int ToBufferedImageFormat (PixelFormat format) {
170                         switch(format) {
171                                 case PixelFormat.Format16bppGrayScale:
172                                         return BufferedImage.TYPE_USHORT_GRAY;
173                                 case PixelFormat.Format1bppIndexed:
174                                         return BufferedImage.TYPE_BYTE_GRAY;
175                                 case PixelFormat.Format32bppArgb:
176                                         return BufferedImage.TYPE_INT_ARGB;
177                                 case PixelFormat.Format32bppRgb:
178                                         return BufferedImage.TYPE_INT_RGB;
179                                 case PixelFormat.Format32bppPArgb:
180                                         return BufferedImage.TYPE_INT_ARGB_PRE;
181                                 case PixelFormat.Format16bppRgb555:
182                                         return BufferedImage.TYPE_USHORT_555_RGB;
183                                 case PixelFormat.Format16bppRgb565:
184                                         return BufferedImage.TYPE_USHORT_565_RGB;
185                                 case PixelFormat.Indexed:
186                                         return BufferedImage.TYPE_BYTE_INDEXED;
187                                 default:
188                                         return BufferedImage.TYPE_INT_ARGB;
189                         }                       
190                 }
191
192                 private static java.awt.Image CreateScaledImage(Image original, int width, int height) {
193                         JavaImage oldscaled = original.CurrentImage.NativeImage.getScaledInstance(width, height,
194                                 JavaImage.SCALE_DEFAULT);
195                         BufferedImage newimage = new BufferedImage(oldscaled.getWidth(null), 
196                                 oldscaled.getHeight(null),
197                                 BufferedImage.TYPE_INT_ARGB);
198                         java.awt.Graphics2D graphics2d = newimage.createGraphics();
199                         graphics2d.drawImage(oldscaled, 0, 0, null);
200                         graphics2d.dispose();
201                         return newimage;                                
202                 }
203                 #endregion
204
205                 #region Get-SetPixel
206                 public Color GetPixel (int x, int y) 
207                 {
208
209                         int argb = NativeObject.getRGB(x,y);                            
210                         return Color.FromArgb(argb); 
211                 }
212
213                 public void SetPixel (int x, int y, Color color)
214                 {                               
215                         int rgb = color.ToArgb();
216                         NativeObject.setRGB(x,y,rgb);
217                 }
218                 #endregion
219
220                 #region Clone
221                 public override object Clone () {
222                         return new Bitmap ( (PlainImage)CurrentImage.Clone() );
223                 }
224
225                 public Bitmap Clone (Rectangle rect, PixelFormat pixFormat)
226                 {
227                         return Clone(new RectangleF( rect.X, rect.Y, rect.Width, rect.Height ), pixFormat);
228         }
229                 
230                 public Bitmap Clone (RectangleF rect, PixelFormat pixFormat)
231                 {
232                         PlainImage plainImage = CurrentImage.Clone(false);\r
233                         BufferedImage clone = new BufferedImage( (int)rect.Width, (int)rect.Height, ToBufferedImageFormat( pixFormat ) );\r
234                         clone.getGraphics().drawImage( NativeObject, -(int)rect.X, -(int)rect.Y, null );\r
235 \r
236                         plainImage.NativeImage = clone;\r
237                         return new Bitmap(plainImage);\r
238                 }
239                 #endregion
240
241                 #region LockBits
242                 // TBD: implement this
243                 public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format) {
244                         throw new NotImplementedException();
245                 }
246                 #endregion
247
248                 #region MakeTransparent
249                 public void MakeTransparent ()
250                 {
251                         Color clr = GetPixel(0,0);                      
252                         MakeTransparent (clr);
253                 }
254
255                 public void MakeTransparent (Color transparentColor)
256                 {
257                         byte A = transparentColor.A;
258                         image.WritableRaster raster = NativeObject.getRaster();
259                         int numBands  = raster.getNumBands();
260                         int maxWidth  = raster.getWidth() + raster.getMinX();
261                         int maxHeight = raster.getHeight() + raster.getMinY();
262                         int[] srcPix  = new int[numBands];
263
264                         for (int y = raster.getMinY(); y < maxHeight; y++) {
265                                 for (int x = raster.getMinX(); x < maxWidth; x++) {
266                                         /*srcPix =*/ raster.getPixel(x, y, srcPix);
267                                         for (int z = 0; z < numBands; z++) {
268                                                 int argb = srcPix[z];
269                                                 if ((uint)argb >> 24 == A) {
270                                                         argb &= 0x00FFFFFF;
271                                                         srcPix[z] = argb;
272                                                 }
273                                         }
274                                 }
275                         }
276                 }
277                 #endregion
278
279                 #region SetResolution
280                 public void SetResolution (float xDpi, float yDpi)
281                 {
282                         CurrentImage.HorizontalResolution = xDpi;
283                         CurrentImage.VerticalResolution = yDpi;
284                 }
285                 #endregion 
286
287                 #region UnlockBits
288                 // TBD: implement this
289                 public void UnlockBits (BitmapData bitmap_data)
290                 {
291                         throw new NotImplementedException();
292                 }
293                 #endregion 
294
295                 #region NativeObject
296                 internal new BufferedImage NativeObject {
297                         get {
298                                 return (BufferedImage)base.NativeObject.CurrentImage.NativeImage;
299                         }
300                 }
301
302                 protected override java.awt.Image[] CloneNativeObjects(java.awt.Image[] src) {
303                         if (src == null)
304                                 return null;
305
306                         awt.Image[] dst = new awt.Image[src.Length];
307                         for (int i = 0; i < dst.Length; i++) {
308                                 BufferedImage image = src[i] as BufferedImage;
309                                 if (image == null)
310                                         throw new ArgumentException(String.Format("Unsupported image type '{0}'", src[i].ToString()), "src");
311
312                                 dst[i] = new BufferedImage(image.getColorModel(), image.copyData(null), image.isAlphaPremultiplied(), null);
313                         }
314
315                         return dst;
316                 }
317
318                 #endregion
319
320                 #region InternalPixelFormat
321                 protected override PixelFormat InternalPixelFormat {
322                         get {
323                                 int t = NativeObject.getType();
324                                 switch(t) {
325                                         case 11://JavaImage.TYPE_USHORT_GRAY:
326                                                 return PixelFormat.Format16bppGrayScale;
327                                         case 10://JavaImage.TYPE_BYTE_GRAY:
328                                                 return PixelFormat.Format1bppIndexed;                           
329                                         case 1: //JavaImage.TYPE_INT_RGB
330                                                 return PixelFormat.Format32bppRgb;
331                                         case 2: //JavaImage.TYPE_INT_ARGB:                      
332                                                 return PixelFormat.Format32bppArgb;
333                                         case 3://JavaImage.TYPE_INT_ARGB_PRE:
334                                                 return PixelFormat.Format32bppPArgb;
335                                         case 9://JavaImage.TYPE_USHORT_555_RGB:
336                                                 return PixelFormat.Format16bppRgb555;
337                                         case 8://JavaImage.TYPE_USHORT_565_RGB:
338                                                 return PixelFormat.Format16bppRgb565;
339                                         case 13://JavaImage.TYPE_BYTE_INDEXED:
340                                                 return PixelFormat.Indexed;
341                                                 //TBD: support this
342                                         case 12://JavaImage.TYPE_BYTE_BINARY:
343                                         case 0://JavaImage.TYPE_CUSTOM:
344                                         case 4://JavaImage.TYPE_INT_BGR:
345                                         case 5://JavaImage.TYPE_3BYTE_BGR:                                      
346                                         case 6://JavaImage.TYPE_4BYTE_ABGR:
347                                         case 7://JavaImage.TYPE_4BYTE_ABGR_PRE:
348                                         default:
349                                                 return PixelFormat.Undefined;
350                                 }                       
351                         }               
352                 }
353                 #endregion
354
355 #if INTPTR_SUPPORT
356                 public static Bitmap FromHicon (IntPtr hicon)
357                 {       
358                         throw new NotImplementedException();
359                 }
360
361                 public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TBD: Untested
362                 {
363                         throw new NotImplementedException();
364                 }
365
366                 public IntPtr GetHbitmap ()
367                 {
368                         throw new NotImplementedException();
369                 }
370
371                 public IntPtr GetHbitmap (Color background)
372                 {
373                         throw new NotImplementedException();
374                 }
375
376                 public IntPtr GetHicon ()
377                 {
378                         throw new NotImplementedException();
379                 }
380 #endif
381
382         }
383 }