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