[System.Net] Add support for .pac proxy config scripts on mac
[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 Static fields
21
22                 static readonly image.ColorModel _jpegColorModel = new image.DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x0);
23
24                 #endregion
25
26                 #region constructors
27
28                 Bitmap (PlainImage orig) {
29                         base.Initialize( orig, false );
30                 }
31
32                 [MonoTODO]
33                 private Bitmap (SerializationInfo info, StreamingContext context) {
34                         throw new NotImplementedException ();
35                 }
36
37                 public Bitmap (int width, int height, Graphics g) 
38                         :this (width, height, PixelFormat.Format32bppArgb) {
39                         CurrentImage.HorizontalResolution = g.DpiX;
40                         CurrentImage.VerticalResolution = g.DpiY;
41                 }
42
43                 public Bitmap (Image original) 
44                         :this (original, original.Size) {}
45
46                 public Bitmap (Image orig, Size newSize)
47                         :this (orig, newSize.Width, newSize.Height) {}
48
49                 public Bitmap (Image orig, int width, int height)
50                         :base (CreateScaledImage (orig, width, height), ImageFormat.MemoryBmp) {}
51
52                 internal Bitmap (java.awt.Image nativeObject, ImageFormat format)
53                         :base (nativeObject, format) {}
54
55                 [MonoTODO]
56                 private Bitmap (java.awt.Image nativeObject, ImageFormat format, PixelFormat pixFormat)
57                         :this (nativeObject, format) {
58                         if (pixFormat != this.PixelFormat)
59                                 throw new NotImplementedException ("Converting PixelFormat is not implemented yet.");
60                 }
61
62                 public Bitmap (int width, int height) 
63                         :this (width, height, PixelFormat.Format32bppArgb) {}
64
65                 public Bitmap (int width, int height, PixelFormat format)
66                         :base (
67                         new java.awt.image.BufferedImage (width, height,
68                         ToBufferedImageFormat (format)),
69                         ImageFormat.Bmp) {
70                 }
71
72                 public Bitmap (Stream stream)
73                         :this (stream, false) {}
74
75                 public Bitmap (string filename) 
76                         :this (filename, false) {}
77
78                 [MonoTODO]
79                 public Bitmap (Stream stream, bool useIcm)
80                         :this (stream, useIcm, null) {}
81
82                 [MonoTODO]
83                 public Bitmap (string filename, bool useIcm)
84                         :this (filename, useIcm, null) {}
85
86                 internal Bitmap (Stream stream, bool useIcm, ImageFormat format) {
87                         // TBD: useIcm param
88                         io.InputStream jis = vmw.common.IOUtils.ToInputStream (stream);
89             Initialize (new stream.MemoryCacheImageInputStream (jis), format);
90                 }
91
92                 internal Bitmap (string filename, bool useIcm, ImageFormat format) {
93                         using(FileStream stream = new FileStream(filename, FileMode.Open, FileAccess.Read)) {
94                                 // TBD: useIcm param
95                                 io.InputStream jis = vmw.common.IOUtils.ToInputStream (stream);
96                                 Initialize (new stream.MemoryCacheImageInputStream (jis), format);
97                         }
98                 }
99
100                 public Bitmap (Type type, string resource) {
101                         using (Stream s = type.Assembly.GetManifestResourceStream (resource)) {
102                                 if (s == null)
103                                         throw new ArgumentException("Resource '" + resource + "' could not be found in class '" + type.ToString() + "'");
104
105                                 io.InputStream jis = vmw.common.IOUtils.ToInputStream (s);
106                                 Initialize (new stream.MemoryCacheImageInputStream (jis), null);
107                         }
108                 }
109 #if INTPTR_SUPPORT
110                 [MonoTODO]
111                 public Bitmap (int width, int height, int stride, PixelFormat format, IntPtr scan0)
112                 {                                               
113                         throw new NotImplementedException();                    
114                 }
115 #endif
116                 #endregion
117
118                 #region Internal Initialization
119
120                 private void Initialize (stream.ImageInputStream input, ImageFormat format) {
121                         ImageCodec ic = null;
122
123                         if (format == null)
124                                 ic = ImageCodec.CreateReader(input);
125                         else
126                                 ic = ImageCodec.CreateReader(format);
127
128                         if (ic == null)
129                                 throw new ArgumentException ("Parameter is not valid.");
130
131                         try {
132                                 ic.NativeStream = input;
133                                 PlainImage pi = ic.ReadPlainImage();
134                                 base.Initialize( pi, false );
135
136                                 pi = ic.ReadNextPlainImage();
137                                 while ( pi != null) {
138                                         base.Initialize( pi, true );
139                                         pi = ic.ReadNextPlainImage();
140                                 }
141
142                                 _flags |= (int)(ImageFlags.ImageFlagsReadOnly | ImageFlags.ImageFlagsHasRealPixelSize);
143                         }
144                         catch (IOException ex) {
145                                 throw ex;
146                         }                       
147                         finally {
148                                 ic.Dispose();
149                         }
150                 }
151
152                 #endregion
153
154                 #region InternalSave
155                 protected override void InternalSave (stream.ImageOutputStream output, Guid clsid) {
156
157                         ImageCodec ic = ImageCodec.CreateWriter( clsid );
158                         using (ic) {
159
160                                 PlainImage plainImage = CurrentImage;
161                                 plainImage.NativeImage.flush();
162
163                                 if ( ImageCodec.ClsidToImageFormat( clsid ).Equals( ImageFormat.Jpeg ) ) {
164                                         image.ColorModel cm = ((image.BufferedImage)CurrentImage.NativeImage).getColorModel();
165                                         if (cm.hasAlpha()) {
166                                                 if (cm is image.DirectColorModel) {
167                                                         image.Raster raster = ((image.BufferedImage)CurrentImage.NativeImage).getRaster();
168                                                         image.DataBuffer db = raster.getDataBuffer();
169                                                         image.DirectColorModel dcm = (image.DirectColorModel)cm;
170                                                         image.SinglePixelPackedSampleModel jpegSampleModel = new image.SinglePixelPackedSampleModel( 
171                                                                 db.getDataType(), Width, Height, 
172                                                                 new int[] {dcm.getRedMask(), dcm.getGreenMask(), dcm.getBlueMask()}     );
173                 
174                                                         image.BufferedImage tb = new image.BufferedImage( 
175                                                                 _jpegColorModel, 
176                                                                 image.Raster.createWritableRaster( jpegSampleModel, db, null ),
177                                                                 false, null );
178
179                                                         plainImage = new PlainImage( tb, plainImage.Thumbnails, ImageFormat.Jpeg, plainImage.HorizontalResolution, plainImage.VerticalResolution, plainImage.Dimension );
180                                                         plainImage.NativeMetadata = plainImage.NativeMetadata;
181                                                 }
182                                         }
183                                 }
184
185                                 ic.NativeStream = output;
186                                 ic.WritePlainImage( plainImage );
187                         }
188                 }
189
190                 #endregion
191
192                 #region private statics: ToBufferedImageFormat, CreateScaledImage
193
194                 private static int ToBufferedImageFormat (PixelFormat format) {
195                         switch(format) {
196                                 case PixelFormat.Format16bppGrayScale:
197                                         return BufferedImage.TYPE_USHORT_GRAY;
198                                 case PixelFormat.Format1bppIndexed:
199                                         return BufferedImage.TYPE_BYTE_GRAY;
200                                 case PixelFormat.Format32bppArgb:
201                                         return BufferedImage.TYPE_INT_ARGB;
202                                 case PixelFormat.Format32bppRgb:
203                                         return BufferedImage.TYPE_INT_RGB;
204                                 case PixelFormat.Format32bppPArgb:
205                                         return BufferedImage.TYPE_INT_ARGB_PRE;
206                                 case PixelFormat.Format16bppRgb555:
207                                         return BufferedImage.TYPE_USHORT_555_RGB;
208                                 case PixelFormat.Format16bppRgb565:
209                                         return BufferedImage.TYPE_USHORT_565_RGB;
210                                 case PixelFormat.Indexed:
211                                         return BufferedImage.TYPE_BYTE_INDEXED;
212                                 default:
213                                         return BufferedImage.TYPE_INT_ARGB;
214                         }                       
215                 }
216
217                 private static java.awt.Image CreateScaledImage(Image original, int width, int height) {
218                         JavaImage oldscaled = original.CurrentImage.NativeImage.getScaledInstance(width, height,
219                                 JavaImage.SCALE_DEFAULT);
220                         BufferedImage newimage = new BufferedImage(oldscaled.getWidth(null), 
221                                 oldscaled.getHeight(null),
222                                 BufferedImage.TYPE_INT_ARGB);
223                         java.awt.Graphics2D graphics2d = newimage.createGraphics();
224                         graphics2d.drawImage(oldscaled, 0, 0, null);
225                         graphics2d.dispose();
226                         return newimage;                                
227                 }
228                 #endregion
229
230                 #region Get-SetPixel
231                 public Color GetPixel (int x, int y) 
232                 {
233
234                         int argb = NativeObject.getRGB(x,y);                            
235                         return Color.FromArgb(argb); 
236                 }
237
238                 public void SetPixel (int x, int y, Color color)
239                 {                               
240                         int rgb = color.ToArgb();
241                         NativeObject.setRGB(x,y,rgb);
242                 }
243                 #endregion
244
245                 #region Clone
246                 public override object Clone () {
247                         return new Bitmap ( (PlainImage)CurrentImage.Clone() );
248                 }
249
250                 public Bitmap Clone (Rectangle rect, PixelFormat pixFormat)
251                 {
252                         return Clone(new RectangleF( rect.X, rect.Y, rect.Width, rect.Height ), pixFormat);
253         }
254                 
255                 public Bitmap Clone (RectangleF rect, PixelFormat pixFormat)
256                 {
257                         PlainImage plainImage = CurrentImage.Clone(false);
258                         BufferedImage clone = new BufferedImage( (int)rect.Width, (int)rect.Height, ToBufferedImageFormat( pixFormat ) );
259                         awt.Graphics2D g = clone.createGraphics();
260                         try {
261                                 g.drawImage( NativeObject, -(int)rect.X, -(int)rect.Y, null );
262                         }
263                         finally {
264                                 g.dispose();
265                         }
266
267                         plainImage.NativeImage = clone;
268                         return new Bitmap(plainImage);
269                 }
270                 #endregion
271
272                 #region LockBits
273                 [MonoTODO]
274                 public BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format) {
275                         throw new NotImplementedException();
276                 }
277
278 #if NET_2_0
279                 public
280 #endif
281                 BitmapData LockBits (Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData) {
282                         throw new NotImplementedException();
283                 }
284                 #endregion
285
286                 #region MakeTransparent
287                 public void MakeTransparent ()
288                 {
289                         Color clr = Color.FromArgb(0,0,0);                      
290                         MakeTransparent (clr);
291                 }
292
293                 public void MakeTransparent (Color transparentColor)
294                 {
295                         image.WritableRaster raster = NativeObject.getRaster();
296                         int numBands  = raster.getNumBands();
297                         if (numBands != 4)
298                                 return;
299
300                         int maxWidth  = raster.getWidth() + raster.getMinX();
301                         int maxHeight = raster.getHeight() + raster.getMinY();
302                         int[] srcPix  = new int[numBands];
303
304                         for (int y = raster.getMinY(); y < maxHeight; y++) {
305                                 for (int x = raster.getMinX(); x < maxWidth; x++) {
306                                         /*srcPix =*/ raster.getPixel(x, y, srcPix);
307                                         if (srcPix[0] == transparentColor.R &&
308                                                 srcPix[1] == transparentColor.G &&
309                                                 srcPix[2] == transparentColor.B) {
310                                                 srcPix[3] = 0;
311                                                 raster.setPixel(x, y, srcPix);
312                                         }
313                                 }
314                         }
315                 }
316                 #endregion
317
318                 #region SetResolution
319                 public void SetResolution (float xDpi, float yDpi)
320                 {
321                         CurrentImage.HorizontalResolution = xDpi;
322                         CurrentImage.VerticalResolution = yDpi;
323                 }
324                 #endregion 
325
326                 #region UnlockBits
327                 [MonoTODO]
328                 public void UnlockBits (BitmapData bitmap_data)
329                 {
330                         throw new NotImplementedException();
331                 }
332                 #endregion 
333
334                 #region NativeObject
335                 internal new BufferedImage NativeObject {
336                         get {
337                                 return (BufferedImage)base.NativeObject.CurrentImage.NativeImage;
338                         }
339                 }
340
341                 protected override java.awt.Image[] CloneNativeObjects(java.awt.Image[] src) {
342                         if (src == null)
343                                 return null;
344
345                         awt.Image[] dst = new awt.Image[src.Length];
346                         for (int i = 0; i < dst.Length; i++) {
347                                 BufferedImage image = src[i] as BufferedImage;
348                                 if (image == null)
349                                         throw new ArgumentException(String.Format("Unsupported image type '{0}'", src[i].ToString()), "src");
350
351                                 dst[i] = new BufferedImage(image.getColorModel(), image.copyData(null), image.isAlphaPremultiplied(), null);
352                         }
353
354                         return dst;
355                 }
356
357                 #endregion
358
359                 #region InternalPixelFormat
360                 protected override PixelFormat InternalPixelFormat {
361                         get {
362                                 int t = NativeObject.getType();
363                                 switch(t) {
364                                         case 11://JavaImage.TYPE_USHORT_GRAY:
365                                                 return PixelFormat.Format16bppGrayScale;
366                                         case 10://JavaImage.TYPE_BYTE_GRAY:
367                                                 return PixelFormat.Format8bppIndexed;                           
368                                         case 1: //JavaImage.TYPE_INT_RGB
369                                                 return PixelFormat.Format32bppRgb;
370                                         case 2: //JavaImage.TYPE_INT_ARGB:                      
371                                                 return PixelFormat.Format32bppArgb;
372                                         case 3://JavaImage.TYPE_INT_ARGB_PRE:
373                                                 return PixelFormat.Format32bppPArgb;
374                                         case 9://JavaImage.TYPE_USHORT_555_RGB:
375                                                 return PixelFormat.Format16bppRgb555;
376                                         case 8://JavaImage.TYPE_USHORT_565_RGB:
377                                                 return PixelFormat.Format16bppRgb565;
378                                         case 13://JavaImage.TYPE_BYTE_INDEXED:
379                                                 return PixelFormat.Indexed;
380                                                 //TBD: support this
381                                         case 12://JavaImage.TYPE_BYTE_BINARY:
382                                         case 0://JavaImage.TYPE_CUSTOM:
383                                         case 4://JavaImage.TYPE_INT_BGR:
384                                         case 5://JavaImage.TYPE_3BYTE_BGR:                                      
385                                         case 6://JavaImage.TYPE_4BYTE_ABGR:
386                                         case 7://JavaImage.TYPE_4BYTE_ABGR_PRE:
387                                         default:
388                                                 return PixelFormat.Undefined;
389                                 }                       
390                         }               
391                 }
392                 #endregion
393
394 #if INTPTR_SUPPORT
395                 [MonoTODO]
396                 public static Bitmap FromHicon (IntPtr hicon)
397                 {       
398                         throw new NotImplementedException();
399                 }
400
401                 [MonoTODO]
402                 public static Bitmap FromResource (IntPtr hinstance, string bitmapName) //TBD: Untested
403                 {
404                         throw new NotImplementedException();
405                 }
406
407                 [MonoTODO]
408                 public IntPtr GetHbitmap ()
409                 {
410                         throw new NotImplementedException();
411                 }
412
413                 [MonoTODO]
414                 public IntPtr GetHbitmap (Color background)
415                 {
416                         throw new NotImplementedException();
417                 }
418
419                 [MonoTODO]
420                 public IntPtr GetHicon ()
421                 {
422                         throw new NotImplementedException();
423                 }
424 #endif
425
426         }
427 }