Make a copy of the old ZipLib
[mono.git] / mcs / class / System.Drawing / Test / System.Drawing / TestBitmap.cs
1 //
2 // Bitmap class testing unit
3 //
4 // Author:
5 //
6 //       Jordi Mas i Hernàndez (jmas@softcatala.org>
7 //       Jonathan Gilbert <logic@deltaq.org>
8 //
9 // (C) 2004 Ximian, Inc.  http://www.ximian.com
10 //
11
12 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34 using System;
35 using System.Drawing;
36 using System.Drawing.Imaging;
37 using NUnit.Framework;
38 using System.IO;
39 using System.Security.Cryptography;
40 using System.Text;
41 using System.Runtime.InteropServices;
42 using System.Security.Permissions;
43
44 namespace MonoTests.System.Drawing{
45
46         [TestFixture]
47         [SecurityPermission (SecurityAction.Deny, UnmanagedCode = true)]
48         public class TestBitmap {
49                 
50                 [TearDown]
51                 public void Clean() {}
52                 
53                 [SetUp]
54                 public void GetReady()          
55                 {
56                 
57                 }
58                         
59                 [Test]
60                 public void TestPixels() 
61                 {               
62                         // Tests GetSetPixel/SetPixel                   
63                         Bitmap bmp= new Bitmap(100,100, PixelFormat.Format32bppRgb);                                                                                    
64                         bmp.SetPixel(0,0,Color.FromArgb(255,128,128,128));                                      
65                         Color color = bmp.GetPixel(0,0);                                
66                                                 
67                         Assert.AreEqual (Color.FromArgb(255,128,128,128), color);
68                         
69                         bmp.SetPixel(99,99,Color.FromArgb(255,255,0,155));                                      
70                         Color color2 = bmp.GetPixel(99,99);                                                                             
71                         Assert.AreEqual (Color.FromArgb(255,255,0,155), color2);                        
72                 }
73                 
74                 /* Get the output directory depending on the runtime and location*/
75                 public static string getOutSubDir()
76                 {                               
77                         string sSub, sRslt;                     
78                         
79                         if (Environment.GetEnvironmentVariable("MSNet")==null)
80                                 sSub = "mono/";
81                         else
82                                 sSub = "MSNet/";                        
83                         
84                         sRslt = Path.GetFullPath (sSub);
85                                 
86                         if (Directory.Exists(sRslt) ==  false) 
87                                 sRslt = "Test/System.Drawing/" + sSub;                                                  
88                         
89                         if (sRslt.Length > 0)
90                                 if (sRslt[sRslt.Length-1] != '\\' && sRslt[sRslt.Length-1] != '/')
91                                         sRslt += "/";                                   
92                         
93                         return sRslt;
94                 }
95                 
96                 /* Get the input directory depending on the runtime*/
97                 public static string getInFile(string file)
98                 {                               
99                         string sRslt;                                           
100                         
101                         sRslt = Path.GetFullPath (file);
102                                 
103                         if (File.Exists(file)==false) 
104                                 sRslt = "Test/System.Drawing/" + file;                                                  
105                         
106                         return sRslt;
107                 }
108                 
109                 //[Test]
110                 public void MakeTransparent() 
111                 {
112                         string sInFile =   getInFile("bitmaps/maketransparent.bmp");
113                         string sOutFile =  getOutSubDir() + "transparent.bmp";
114                                                 
115                         Bitmap  bmp = new Bitmap(sInFile);
116                                         
117                         bmp.MakeTransparent();
118                         bmp.Save(sOutFile);                                                     
119                         
120                         Color color = bmp.GetPixel(1,1);                                                        
121                         Assert.AreEqual (Color.Black.R, color.R);                                                                                       
122                         Assert.AreEqual (Color.Black.G, color.G);                                                                                       
123                         Assert.AreEqual (Color.Black.B, color.B);                                                                               
124                 }
125                 
126                 [Test]
127                 public void Clone()
128                 {
129                         string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
130                         string sOutFile =  getOutSubDir() + "clone24.bmp";                      
131                         
132                         Rectangle rect = new Rectangle(0,0,50,50);                                              
133                         Bitmap  bmp = new Bitmap(sInFile);                      
134                         
135                         Bitmap bmpNew = bmp.Clone (rect, PixelFormat.Format32bppArgb);                                                                  
136                         
137                         Color colororg0 = bmp.GetPixel(0,0);            
138                         Color colororg50 = bmp.GetPixel(49,49);                                 
139                         Color colornew0 = bmpNew.GetPixel(0,0);         
140                         Color colornew50 = bmpNew.GetPixel(49,49);                              
141                         
142                         Assert.AreEqual (colororg0, colornew0);                                                                                 
143                         Assert.AreEqual (colororg50, colornew50);                               
144                 }       
145                 
146                 [Test]
147                 public void CloneImage()
148                 {
149                         string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");                     
150                         Bitmap  bmp = new Bitmap(sInFile);                      
151                         
152                         Bitmap bmpNew = (Bitmap) bmp.Clone ();                  
153                         
154                         Assert.AreEqual (bmp.Width, bmpNew.Width);
155                         Assert.AreEqual (bmp.Height, bmpNew.Height);            
156                         Assert.AreEqual (bmp.PixelFormat, bmpNew.PixelFormat);
157                         
158                 }       
159
160                 [Test]
161                 public void Frames()
162                 {
163                         string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");                     
164                         Bitmap  bmp = new Bitmap(sInFile);                                              
165                         int cnt = bmp.GetFrameCount(FrameDimension.Page);                       
166                         int active = bmp.SelectActiveFrame (FrameDimension.Page, 0);
167                         
168                         Assert.AreEqual (1, cnt);                                                               
169                         Assert.AreEqual (0, active);                                                                                    
170                 }
171                 
172                 [Test]
173                 [ExpectedException (typeof (ArgumentException))]
174                 public void FileDoesNotExists ()
175                 {                       
176                         Bitmap  bmp = new Bitmap ("FileDoesNotExists.jpg");                     
177                 }
178
179                 static string ByteArrayToString(byte[] arrInput)
180                 {
181                         int i;
182                         StringBuilder sOutput = new StringBuilder(arrInput.Length);
183                         for (i=0;i < arrInput.Length -1; i++) 
184                         {
185                                 sOutput.Append(arrInput[i].ToString("X2"));
186                         }
187                         return sOutput.ToString();
188                 }
189
190
191                 public string RotateBmp (Bitmap src, RotateFlipType rotate)
192                 {                       
193                         int witdh = 150, height = 150, index = 0;                       
194                         byte[] pixels = new byte [witdh * height * 3];
195                         Bitmap bmp_rotate;
196                         byte[] hash;
197                         Color clr;
198
199
200                         bmp_rotate = src.Clone (new RectangleF (0,0, witdh, height), PixelFormat.Format32bppArgb);      
201                         bmp_rotate.RotateFlip (rotate);                 
202
203                         for (int y = 0; y < height; y++) {
204                                 for (int x = 0; x < witdh; x++) {                               
205                                         clr = bmp_rotate.GetPixel (x,y);
206                                         pixels[index++] = clr.R; pixels[index++] = clr.G; pixels[index++]  = clr.B;     
207                                 }                               
208                         }
209                 
210                         hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
211                         return ByteArrayToString (hash);
212                 }
213
214                 public string RotateIndexedBmp (Bitmap src, RotateFlipType type)
215                 {
216                         int pixels_per_byte;
217
218                         switch (src.PixelFormat)
219                         {
220                                 case PixelFormat.Format1bppIndexed: pixels_per_byte = 8; break;
221                                 case PixelFormat.Format4bppIndexed: pixels_per_byte = 2; break;
222                                 case PixelFormat.Format8bppIndexed: pixels_per_byte = 1; break;
223
224                                 default: throw new Exception("Cannot pass a bitmap of format " + src.PixelFormat + " to RotateIndexedBmp");
225                         }
226
227                         Bitmap test = src.Clone () as Bitmap;
228
229                         test.RotateFlip (type);
230
231                         BitmapData data = null;
232                         byte[] pixel_data;
233
234                         try
235                         {
236                                 data = test.LockBits (new Rectangle (0, 0, test.Width, test.Height), ImageLockMode.ReadOnly, test.PixelFormat);
237
238                                 int scan_size = (data.Width + pixels_per_byte - 1) / pixels_per_byte;
239                                 pixel_data = new byte[data.Height * scan_size];
240
241                                 for (int y=0; y < data.Height; y++) {
242                                         IntPtr src_ptr = (IntPtr)(y * data.Stride + data.Scan0.ToInt64 ());
243                                         int dest_offset = y * scan_size;
244                                         for (int x=0; x < scan_size; x++)
245                                                 pixel_data[dest_offset + x] = Marshal.ReadByte (src_ptr, x);
246                                 }
247                         }
248                         finally
249                         {
250                                 if (test != null) {
251                                         if (data != null)
252                                                 try { test.UnlockBits(data); } catch {}
253
254                                         try { test.Dispose(); } catch {}
255                                 }
256                         }
257
258                         if (pixel_data == null)
259                                 return "--ERROR--";
260
261                         byte[] hash = new MD5CryptoServiceProvider().ComputeHash (pixel_data);
262                         return ByteArrayToString (hash);
263                 }
264                 
265                 
266                 /*
267                         Rotate bitmap in diffent ways, and check the result
268                         pixels using MD5
269                 */
270                 [Test]
271                 public void Rotate()
272                 {
273                         string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");     
274                         Bitmap  bmp = new Bitmap(sInFile);              
275                         
276                         Assert.AreEqual ("312958A3C67402E1299413794988A3", RotateBmp (bmp, RotateFlipType.Rotate90FlipNone));   
277                         Assert.AreEqual ("BF70D8DA4F1545AEDD77D0296B47AE", RotateBmp (bmp, RotateFlipType.Rotate180FlipNone));
278                         Assert.AreEqual ("15AD2ADBDC7090C0EC744D0F7ACE2F", RotateBmp (bmp, RotateFlipType.Rotate270FlipNone));
279                         Assert.AreEqual ("2E10FEC1F4FD64ECC51D7CE68AEB18", RotateBmp (bmp, RotateFlipType.RotateNoneFlipX));
280                         Assert.AreEqual ("E63204779B566ED01162B90B49BD9E", RotateBmp (bmp, RotateFlipType.Rotate90FlipX));
281                         Assert.AreEqual ("B1ECB17B5093E13D04FF55CFCF7763", RotateBmp (bmp, RotateFlipType.Rotate180FlipX));
282                         Assert.AreEqual ("71A173882C16755D86F4BC26532374", RotateBmp (bmp, RotateFlipType.Rotate270FlipX));
283
284                 }
285
286                 /*
287                         Rotate 1- and 4-bit bitmaps in different ways and check the
288                         resulting pixels using MD5
289                 */
290                 [Test]
291                 public void Rotate1bit4bit()
292                 {
293                         string[] files = {
294                                            getInFile ("bitmaps/1bit.png"),
295                                            getInFile ("bitmaps/4bit.png")
296                                          };
297
298                         StringBuilder md5s = new StringBuilder();
299
300                         foreach (string file in files)
301                                 using (Bitmap bmp = new Bitmap(file))
302                                         foreach (RotateFlipType type in Enum.GetValues (typeof(RotateFlipType)))
303                                                 md5s.Append (RotateIndexedBmp (bmp, type));
304
305                         using (StreamWriter writer = new StreamWriter("/tmp/md5s.txt"))
306                                 writer.WriteLine(md5s);
307
308                         Assert.AreEqual (
309                                 "A4DAF507C92BDE10626BC7B34FEFE5" + // 1-bit RotateNoneFlipNone
310                                 "A4DAF507C92BDE10626BC7B34FEFE5" + // 1-bit Rotate180FlipXY
311                                 "C0975EAFD2FC1CC9CC7AF20B92FC9F" + // 1-bit Rotate90FlipNone
312                                 "C0975EAFD2FC1CC9CC7AF20B92FC9F" + // 1-bit Rotate270FlipXY
313                                 "64AE60858A02228F7B1B18C7812FB6" + // 1-bit Rotate180FlipNone
314                                 "64AE60858A02228F7B1B18C7812FB6" + // 1-bit RotateNoneFlipXY
315                                 "E96D3390938350F9DE2608C4364424" + // 1-bit Rotate270FlipNone
316                                 "E96D3390938350F9DE2608C4364424" + // 1-bit Rotate90FlipXY
317                                 "23947CE822C1DDE6BEA69C01F8D0D9" + // 1-bit RotateNoneFlipX
318                                 "23947CE822C1DDE6BEA69C01F8D0D9" + // 1-bit Rotate180FlipY
319                                 "BE45F685BDEBD7079AA1B2CBA46723" + // 1-bit Rotate90FlipX
320                                 "BE45F685BDEBD7079AA1B2CBA46723" + // 1-bit Rotate270FlipY
321                                 "353E937CFF31B1BF6C3DD0A031ACB5" + // 1-bit Rotate180FlipX
322                                 "353E937CFF31B1BF6C3DD0A031ACB5" + // 1-bit RotateNoneFlipY
323                                 "AEA18A770A845E25B6A8CE28DD6DCB" + // 1-bit Rotate270FlipX
324                                 "AEA18A770A845E25B6A8CE28DD6DCB" + // 1-bit Rotate90FlipY
325                                 "3CC874B571902366AACED5D619E87D" + // 4-bit RotateNoneFlipNone
326                                 "3CC874B571902366AACED5D619E87D" + // 4-bit Rotate180FlipXY
327                                 "8DE25C7E1BE4A3B535DB5D83198D83" + // 4-bit Rotate90FlipNone
328                                 "8DE25C7E1BE4A3B535DB5D83198D83" + // 4-bit Rotate270FlipXY
329                                 "27CF5E9CE70BE9EBC47FB996721B95" + // 4-bit Rotate180FlipNone
330                                 "27CF5E9CE70BE9EBC47FB996721B95" + // 4-bit RotateNoneFlipXY
331                                 "A919CCB8F97CAD7DC1F01026D11A5D" + // 4-bit Rotate270FlipNone
332                                 "A919CCB8F97CAD7DC1F01026D11A5D" + // 4-bit Rotate90FlipXY
333                                 "545876C99ACF833E69FBFFBF436034" + // 4-bit RotateNoneFlipX
334                                 "545876C99ACF833E69FBFFBF436034" + // 4-bit Rotate180FlipY
335                                 "5DB56687757CDEFC52D89C77CA9223" + // 4-bit Rotate90FlipX
336                                 "5DB56687757CDEFC52D89C77CA9223" + // 4-bit Rotate270FlipY
337                                 "05A77EDDCDF20D5B0AC0169E95D7D7" + // 4-bit Rotate180FlipX
338                                 "05A77EDDCDF20D5B0AC0169E95D7D7" + // 4-bit RotateNoneFlipY
339                                 "B6B6245796C836923ABAABDF368B29" + // 4-bit Rotate270FlipX
340                                 "B6B6245796C836923ABAABDF368B29",  // 4-bit Rotate90FlipY
341                                 md5s.ToString ());
342                 }
343                 
344                 public void LockBmp (PixelFormat fmt, PixelFormat fmtlock, string output, 
345                         int lwidth , int lheight, ref string hash1, ref string hash2)
346                 {                       
347                         int width = 100, height = 100, bbps, cur, pos;
348                         Bitmap  bmp = new Bitmap (width, height, fmt);                                                                          
349                         Graphics gr = Graphics.FromImage (bmp);                 
350                         byte[] hash;
351                         Color clr;
352                         byte[] btv = new byte[1];                                               
353                         int y, x, len = width * height * 4, index = 0;                  
354                         byte[] pixels = new byte [len];
355                         hash1 = hash2 ="";
356                         
357                         bbps = Image.GetPixelFormatSize (fmt);                  
358                                  
359                         Pen p = new Pen (Color.FromArgb (255, 100, 200, 250), 2);                               
360                         gr.DrawRectangle(p, 1.0F, 1.0F, 80.0F, 80.0F);                          
361                         
362                         BitmapData bd = bmp.LockBits (new Rectangle (0, 0, lwidth, lheight), ImageLockMode.ReadOnly,  fmtlock);
363                         
364                         pos = bd.Scan0.ToInt32();                       
365                         for (y = 0; y < bd.Height; y++) {                       
366                                 for (x = 0; x < bd.Width; x++) {
367                                         
368                                         /* Read the pixels*/
369                                         for (int bt =0; bt < bbps/8; bt++, index++) {
370                                                 cur = pos;
371                                                 cur+= y * bd.Stride;
372                                                 cur+= x * bbps/8;                                       
373                                                 cur+= bt;                                       
374                                                 Marshal.Copy ((IntPtr)cur, btv, 0, 1);
375                                                 pixels[index] = btv[0];
376                                                 
377                                                 /* Make change of all the colours = 250 to 10*/                                         
378                                                 if (btv[0] == 250) {
379                                                         btv[0] = 10;
380                                                         Marshal.Copy (btv, 0, (IntPtr)cur, 1);
381                                                 }
382                                         }
383                                 }
384                         }                                       
385                         
386                         for (int i = index; i < len; i++)
387                                 pixels[index] = 0;
388                 
389                         hash = new MD5CryptoServiceProvider().ComputeHash (pixels);                     
390                         bmp.UnlockBits (bd);                                                    
391                                                 
392                         hash1 = ByteArrayToString (hash);
393                         
394                         /* MD5 of the changed bitmap*/
395                         for (y = 0, index = 0; y < height; y++) {
396                                 for (x = 0; x < width; x++) {                           
397                                         clr = bmp.GetPixel (x,y);
398                                         pixels[index++] = clr.R; pixels[index++] = clr.G; pixels[index++]  = clr.B;     
399                                 }                               
400                         }
401                         
402                         hash = new MD5CryptoServiceProvider().ComputeHash (pixels);                                             
403                         hash2 = ByteArrayToString (hash);
404                         
405                         /*bmp.Save (output, ImageFormat.Bmp);*/
406                 }
407                 /*
408                         Tests the LockBitmap functions. Makes a hash of the block of pixels that it returns
409                         firsts, changes them, and then using GetPixel does another check of the changes.
410                         The results match the .Net framework
411                 */
412                 //[Test]
413                 public void LockBitmap ()
414                 {       
415                         string hash = "";               
416                         string hashchg = "";                            
417                                                         
418                         /* Locks the whole bitmap*/                     
419                         LockBmp (PixelFormat.Format32bppArgb, PixelFormat.Format32bppArgb, "output32bppArgb.bmp", 100, 100, ref hash, ref hashchg);                             
420                         Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);                       
421                         Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);                    
422                         
423                         LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 100, 100, ref hash, ref hashchg);                  
424                         Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);                       
425                         Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);                    
426                         
427                         LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 100, 100, ref hash, ref hashchg);
428                         Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);                       
429                         Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);            
430                         
431                         LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 100, 100, ref hash, ref hashchg);
432                         Assert.AreEqual ("A8A071D0B3A3743905B4E193A62769", hash);                       
433                         Assert.AreEqual ("EEE846FA8F892339C64082DFF775CF", hashchg);                                    
434                         
435                         /* Locks a portion of the bitmap*/              
436                         LockBmp (PixelFormat.Format32bppArgb, PixelFormat.Format32bppArgb, "output32bppArgb.bmp", 50, 50, ref hash, ref hashchg);                               
437                         Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);                       
438                         Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);                    
439                         
440                         LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 50, 50, ref hash, ref hashchg);                    
441                         Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);                       
442                         Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);                    
443                 
444                         LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 50, 50, ref hash, ref hashchg);
445                         Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);                       
446                         Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);                    
447                         
448                         LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 50, 50, ref hash, ref hashchg);
449                         Assert.AreEqual ("FFE86628478591D1A1EB30E894C34F", hash);                       
450                         Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);                            
451                                                 
452                 }
453                 
454         }
455 }