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