2 // Bitmap class testing unit
6 // Jordi Mas i Hernàndez (jmas@softcatala.org>
7 // Jonathan Gilbert <logic@deltaq.org>
9 // (C) 2004 Ximian, Inc. http://www.ximian.com
10 // Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Drawing.Imaging;
34 using NUnit.Framework;
36 using System.Security.Cryptography;
38 using System.Runtime.InteropServices;
39 using System.Security.Permissions;
41 namespace MonoTests.System.Drawing{
44 [SecurityPermission (SecurityAction.Deny, UnmanagedCode = true)]
45 public class TestBitmap {
48 public void TestPixels()
50 // Tests GetSetPixel/SetPixel
51 Bitmap bmp= new Bitmap(100,100, PixelFormat.Format32bppRgb);
52 bmp.SetPixel(0,0,Color.FromArgb(255,128,128,128));
53 Color color = bmp.GetPixel(0,0);
55 Assert.AreEqual (Color.FromArgb(255,128,128,128), color);
57 bmp.SetPixel(99,99,Color.FromArgb(255,255,0,155));
58 Color color2 = bmp.GetPixel(99,99);
59 Assert.AreEqual (Color.FromArgb(255,255,0,155), color2);
63 public void LockBits_NonIndexedWrite ()
65 Bitmap bmp= new Bitmap(100,100, PixelFormat.Format32bppRgb);
66 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
67 BitmapData mybitmapdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
68 bmp.UnlockBits (mybitmapdata);
72 [ExpectedException (typeof (ArgumentException))]
73 public void LockBits_IndexedWrite ()
75 Bitmap bmp= new Bitmap(100,100, PixelFormat.Format8bppIndexed);
76 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
77 BitmapData mybitmapdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
78 bmp.UnlockBits (mybitmapdata);
81 /* Get the output directory depending on the runtime and location*/
82 public static string getOutSubDir()
86 if (Environment.GetEnvironmentVariable("MSNet")==null)
91 sRslt = Path.GetFullPath (sSub);
93 if (Directory.Exists(sRslt) == false)
94 sRslt = "Test/System.Drawing/" + sSub;
97 if (sRslt[sRslt.Length-1] != '\\' && sRslt[sRslt.Length-1] != '/')
103 /* Get the input directory depending on the runtime*/
104 public static string getInFile(string file)
108 sRslt = Path.GetFullPath (file);
110 if (File.Exists(file)==false)
111 sRslt = "Test/System.Drawing/" + file;
117 public void MakeTransparent()
119 string sInFile = getInFile("bitmaps/maketransparent.bmp");
120 string sOutFile = getOutSubDir() + "transparent.bmp";
122 Bitmap bmp = new Bitmap(sInFile);
124 bmp.MakeTransparent();
127 Color color = bmp.GetPixel(1,1);
128 Assert.AreEqual (Color.Black.R, color.R);
129 Assert.AreEqual (Color.Black.G, color.G);
130 Assert.AreEqual (Color.Black.B, color.B);
136 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
137 Rectangle rect = new Rectangle(0,0,50,50);
138 Bitmap bmp = new Bitmap(sInFile);
140 Bitmap bmpNew = bmp.Clone (rect, PixelFormat.Format32bppArgb);
141 Color colororg0 = bmp.GetPixel(0,0);
142 Color colororg50 = bmp.GetPixel(49,49);
143 Color colornew0 = bmpNew.GetPixel(0,0);
144 Color colornew50 = bmpNew.GetPixel(49,49);
146 Assert.AreEqual (colororg0, colornew0);
147 Assert.AreEqual (colororg50, colornew50);
151 public void CloneImage()
153 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
154 Bitmap bmp = new Bitmap(sInFile);
156 Bitmap bmpNew = (Bitmap) bmp.Clone ();
158 Assert.AreEqual (bmp.Width, bmpNew.Width);
159 Assert.AreEqual (bmp.Height, bmpNew.Height);
160 Assert.AreEqual (bmp.PixelFormat, bmpNew.PixelFormat);
167 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
168 Bitmap bmp = new Bitmap(sInFile);
169 int cnt = bmp.GetFrameCount(FrameDimension.Page);
170 int active = bmp.SelectActiveFrame (FrameDimension.Page, 0);
172 Assert.AreEqual (1, cnt);
173 Assert.AreEqual (0, active);
177 [ExpectedException (typeof (ArgumentException))]
179 [Category ("NotWorking")]
181 public void FileDoesNotExists ()
183 Bitmap bmp = new Bitmap ("FileDoesNotExists.jpg");
186 static string ByteArrayToString(byte[] arrInput)
189 StringBuilder sOutput = new StringBuilder(arrInput.Length);
190 for (i=0;i < arrInput.Length -1; i++)
192 sOutput.Append(arrInput[i].ToString("X2"));
194 return sOutput.ToString();
198 public string RotateBmp (Bitmap src, RotateFlipType rotate)
200 int width = 150, height = 150, index = 0;
201 byte[] pixels = new byte [width * height * 3];
206 bmp_rotate = src.Clone (new RectangleF (0,0, width, height), PixelFormat.Format32bppArgb);
207 bmp_rotate.RotateFlip (rotate);
209 for (int y = 0; y < height; y++) {
210 for (int x = 0; x < width; x++) {
211 clr = bmp_rotate.GetPixel (x,y);
212 pixels[index++] = clr.R; pixels[index++] = clr.G; pixels[index++] = clr.B;
216 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
217 return ByteArrayToString (hash);
220 public string RotateIndexedBmp (Bitmap src, RotateFlipType type)
224 switch (src.PixelFormat)
226 case PixelFormat.Format1bppIndexed: pixels_per_byte = 8; break;
227 case PixelFormat.Format4bppIndexed: pixels_per_byte = 2; break;
228 case PixelFormat.Format8bppIndexed: pixels_per_byte = 1; break;
230 default: throw new Exception("Cannot pass a bitmap of format " + src.PixelFormat + " to RotateIndexedBmp");
233 Bitmap test = src.Clone () as Bitmap;
235 test.RotateFlip (type);
237 BitmapData data = null;
242 data = test.LockBits (new Rectangle (0, 0, test.Width, test.Height), ImageLockMode.ReadOnly, test.PixelFormat);
244 int scan_size = (data.Width + pixels_per_byte - 1) / pixels_per_byte;
245 pixel_data = new byte[data.Height * scan_size];
247 for (int y=0; y < data.Height; y++) {
248 IntPtr src_ptr = (IntPtr)(y * data.Stride + data.Scan0.ToInt64 ());
249 int dest_offset = y * scan_size;
250 for (int x=0; x < scan_size; x++)
251 pixel_data[dest_offset + x] = Marshal.ReadByte (src_ptr, x);
258 try { test.UnlockBits(data); } catch {}
260 try { test.Dispose(); } catch {}
264 if (pixel_data == null)
267 byte[] hash = new MD5CryptoServiceProvider().ComputeHash (pixel_data);
268 return ByteArrayToString (hash);
274 Rotate bitmap in diffent ways, and check the result
280 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
281 Bitmap bmp = new Bitmap(sInFile);
283 Assert.AreEqual ("312958A3C67402E1299413794988A3", RotateBmp (bmp, RotateFlipType.Rotate90FlipNone));
284 Assert.AreEqual ("BF70D8DA4F1545AEDD77D0296B47AE", RotateBmp (bmp, RotateFlipType.Rotate180FlipNone));
285 Assert.AreEqual ("15AD2ADBDC7090C0EC744D0F7ACE2F", RotateBmp (bmp, RotateFlipType.Rotate270FlipNone));
286 Assert.AreEqual ("2E10FEC1F4FD64ECC51D7CE68AEB18", RotateBmp (bmp, RotateFlipType.RotateNoneFlipX));
287 Assert.AreEqual ("E63204779B566ED01162B90B49BD9E", RotateBmp (bmp, RotateFlipType.Rotate90FlipX));
288 Assert.AreEqual ("B1ECB17B5093E13D04FF55CFCF7763", RotateBmp (bmp, RotateFlipType.Rotate180FlipX));
289 Assert.AreEqual ("71A173882C16755D86F4BC26532374", RotateBmp (bmp, RotateFlipType.Rotate270FlipX));
295 Rotate 1- and 4-bit bitmaps in different ways and check the
296 resulting pixels using MD5
299 [Category ("NotDotNet")] // that doesn't work under MS.NET and Windows (even without the StreamWriter)
300 public void Rotate1bit4bit()
303 getInFile ("bitmaps/1bit.png"),
304 getInFile ("bitmaps/4bit.png")
307 StringBuilder md5s = new StringBuilder();
309 foreach (string file in files)
310 using (Bitmap bmp = new Bitmap(file))
311 foreach (RotateFlipType type in Enum.GetValues (typeof(RotateFlipType)))
312 md5s.Append (RotateIndexedBmp (bmp, type));
314 using (StreamWriter writer = new StreamWriter("/tmp/md5s.txt"))
315 writer.WriteLine(md5s);
318 "A4DAF507C92BDE10626BC7B34FEFE5" + // 1-bit RotateNoneFlipNone
319 "A4DAF507C92BDE10626BC7B34FEFE5" + // 1-bit Rotate180FlipXY
320 "C0975EAFD2FC1CC9CC7AF20B92FC9F" + // 1-bit Rotate90FlipNone
321 "C0975EAFD2FC1CC9CC7AF20B92FC9F" + // 1-bit Rotate270FlipXY
322 "64AE60858A02228F7B1B18C7812FB6" + // 1-bit Rotate180FlipNone
323 "64AE60858A02228F7B1B18C7812FB6" + // 1-bit RotateNoneFlipXY
324 "E96D3390938350F9DE2608C4364424" + // 1-bit Rotate270FlipNone
325 "E96D3390938350F9DE2608C4364424" + // 1-bit Rotate90FlipXY
326 "23947CE822C1DDE6BEA69C01F8D0D9" + // 1-bit RotateNoneFlipX
327 "23947CE822C1DDE6BEA69C01F8D0D9" + // 1-bit Rotate180FlipY
328 "BE45F685BDEBD7079AA1B2CBA46723" + // 1-bit Rotate90FlipX
329 "BE45F685BDEBD7079AA1B2CBA46723" + // 1-bit Rotate270FlipY
330 "353E937CFF31B1BF6C3DD0A031ACB5" + // 1-bit Rotate180FlipX
331 "353E937CFF31B1BF6C3DD0A031ACB5" + // 1-bit RotateNoneFlipY
332 "AEA18A770A845E25B6A8CE28DD6DCB" + // 1-bit Rotate270FlipX
333 "AEA18A770A845E25B6A8CE28DD6DCB" + // 1-bit Rotate90FlipY
334 "3CC874B571902366AACED5D619E87D" + // 4-bit RotateNoneFlipNone
335 "3CC874B571902366AACED5D619E87D" + // 4-bit Rotate180FlipXY
336 "8DE25C7E1BE4A3B535DB5D83198D83" + // 4-bit Rotate90FlipNone
337 "8DE25C7E1BE4A3B535DB5D83198D83" + // 4-bit Rotate270FlipXY
338 "27CF5E9CE70BE9EBC47FB996721B95" + // 4-bit Rotate180FlipNone
339 "27CF5E9CE70BE9EBC47FB996721B95" + // 4-bit RotateNoneFlipXY
340 "A919CCB8F97CAD7DC1F01026D11A5D" + // 4-bit Rotate270FlipNone
341 "A919CCB8F97CAD7DC1F01026D11A5D" + // 4-bit Rotate90FlipXY
342 "545876C99ACF833E69FBFFBF436034" + // 4-bit RotateNoneFlipX
343 "545876C99ACF833E69FBFFBF436034" + // 4-bit Rotate180FlipY
344 "5DB56687757CDEFC52D89C77CA9223" + // 4-bit Rotate90FlipX
345 "5DB56687757CDEFC52D89C77CA9223" + // 4-bit Rotate270FlipY
346 "05A77EDDCDF20D5B0AC0169E95D7D7" + // 4-bit Rotate180FlipX
347 "05A77EDDCDF20D5B0AC0169E95D7D7" + // 4-bit RotateNoneFlipY
348 "B6B6245796C836923ABAABDF368B29" + // 4-bit Rotate270FlipX
349 "B6B6245796C836923ABAABDF368B29", // 4-bit Rotate90FlipY
353 public void LockBmp (PixelFormat fmt, PixelFormat fmtlock, string output,
354 int lwidth , int lheight, ref string hash1, ref string hash2)
356 int width = 100, height = 100, bbps, cur, pos;
357 Bitmap bmp = new Bitmap (width, height, fmt);
358 Graphics gr = Graphics.FromImage (bmp);
361 byte[] btv = new byte[1];
362 int y, x, len = width * height * 4, index = 0;
363 byte[] pixels = new byte [len];
366 bbps = Image.GetPixelFormatSize (fmt);
368 Pen p = new Pen (Color.FromArgb (255, 100, 200, 250), 2);
369 gr.DrawRectangle(p, 1.0F, 1.0F, 80.0F, 80.0F);
371 BitmapData bd = bmp.LockBits (new Rectangle (0, 0, lwidth, lheight), ImageLockMode.ReadOnly, fmtlock);
373 pos = bd.Scan0.ToInt32();
374 for (y = 0; y < bd.Height; y++) {
375 for (x = 0; x < bd.Width; x++) {
378 for (int bt =0; bt < bbps/8; bt++, index++) {
383 Marshal.Copy ((IntPtr)cur, btv, 0, 1);
384 pixels[index] = btv[0];
386 /* Make change of all the colours = 250 to 10*/
389 Marshal.Copy (btv, 0, (IntPtr)cur, 1);
395 for (int i = index; i < len; i++)
398 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
401 hash1 = ByteArrayToString (hash);
403 /* MD5 of the changed bitmap*/
404 for (y = 0, index = 0; y < height; y++) {
405 for (x = 0; x < width; x++) {
406 clr = bmp.GetPixel (x,y);
407 pixels[index++] = clr.R; pixels[index++] = clr.G; pixels[index++] = clr.B;
411 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
412 hash2 = ByteArrayToString (hash);
414 /*bmp.Save (output, ImageFormat.Bmp);*/
417 Tests the LockBitmap functions. Makes a hash of the block of pixels that it returns
418 firsts, changes them, and then using GetPixel does another check of the changes.
419 The results match the .Net framework
422 public void LockBitmap ()
427 /* Locks the whole bitmap*/
428 LockBmp (PixelFormat.Format32bppArgb, PixelFormat.Format32bppArgb, "output32bppArgb.bmp", 100, 100, ref hash, ref hashchg);
429 Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);
430 Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);
432 LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 100, 100, ref hash, ref hashchg);
433 Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);
434 Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);
436 LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 100, 100, ref hash, ref hashchg);
437 Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);
438 Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);
440 LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 100, 100, ref hash, ref hashchg);
441 Assert.AreEqual ("A8A071D0B3A3743905B4E193A62769", hash);
442 Assert.AreEqual ("EEE846FA8F892339C64082DFF775CF", hashchg);
444 /* Locks a portion of the bitmap*/
445 LockBmp (PixelFormat.Format32bppArgb, PixelFormat.Format32bppArgb, "output32bppArgb.bmp", 50, 50, ref hash, ref hashchg);
446 Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);
447 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
449 LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 50, 50, ref hash, ref hashchg);
450 Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);
451 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
453 LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 50, 50, ref hash, ref hashchg);
454 Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);
455 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
457 LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 50, 50, ref hash, ref hashchg);
458 Assert.AreEqual ("FFE86628478591D1A1EB30E894C34F", hash);
459 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
464 Tests the LockBitmap and UnlockBitmap functions, specifically the copying
465 of bitmap data in the directions indicated by the ImageLockMode.
468 public void LockUnlockBitmap()
474 Color red = Color.FromArgb (Color.Red.A, Color.Red.R, Color.Red.G, Color.Red.B);
475 Color blue = Color.FromArgb (Color.Blue.A, Color.Blue.R, Color.Blue.G, Color.Blue.B);
477 using (Bitmap bmp = new Bitmap (1, 1, PixelFormat.Format24bppRgb))
479 bmp.SetPixel (0, 0, red);
481 data = bmp.LockBits (new Rectangle (0, 0, 1, 1), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
482 pixel_value = Marshal.ReadInt32 (data.Scan0);
483 pixel_colour = Color.FromArgb (pixel_value);
485 // Disregard alpha information in the test
486 pixel_colour = Color.FromArgb(red.A, pixel_colour.R, pixel_colour.G, pixel_colour.B);
488 Assert.AreEqual (red, pixel_colour);
490 Marshal.WriteInt32 (data.Scan0, blue.ToArgb ());
492 bmp.UnlockBits (data);
494 pixel_colour = bmp.GetPixel (0, 0);
496 // Disregard alpha information in the test
497 pixel_colour = Color.FromArgb(red.A, pixel_colour.R, pixel_colour.G, pixel_colour.B);
499 Assert.AreEqual (red, pixel_colour);
501 data = bmp.LockBits (new Rectangle (0, 0, 1, 1), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
503 Marshal.WriteInt32 (data.Scan0, blue.ToArgb ());
505 bmp.UnlockBits (data);
507 pixel_colour = bmp.GetPixel (0, 0);
509 // Disregard alpha information in the test
510 pixel_colour = Color.FromArgb(blue.A, pixel_colour.R, pixel_colour.G, pixel_colour.B);
512 Assert.AreEqual (blue, pixel_colour);
515 using (Bitmap bmp = new Bitmap(1, 1, PixelFormat.Format32bppArgb))
517 bmp.SetPixel (0, 0, red);
519 data = bmp.LockBits (new Rectangle (0, 0, 1, 1), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
523 b = Marshal.ReadByte (data.Scan0, 0);
524 g = Marshal.ReadByte (data.Scan0, 1);
525 r = Marshal.ReadByte (data.Scan0, 2);
526 pixel_colour = Color.FromArgb (red.A, r, g, b);
528 Assert.AreEqual (red, pixel_colour);
530 Marshal.WriteByte (data.Scan0, 0, blue.B);
531 Marshal.WriteByte (data.Scan0, 1, blue.G);
532 Marshal.WriteByte (data.Scan0, 2, blue.R);
534 bmp.UnlockBits (data);
536 pixel_colour = bmp.GetPixel (0, 0);
538 // Disregard alpha information in the test
539 pixel_colour = Color.FromArgb(red.A, pixel_colour.R, pixel_colour.G, pixel_colour.B);
541 Assert.AreEqual (red, bmp.GetPixel (0, 0));
543 data = bmp.LockBits (new Rectangle (0, 0, 1, 1), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
545 Marshal.WriteByte (data.Scan0, 0, blue.B);
546 Marshal.WriteByte (data.Scan0, 1, blue.G);
547 Marshal.WriteByte (data.Scan0, 2, blue.R);
549 bmp.UnlockBits(data);
551 pixel_colour = bmp.GetPixel (0, 0);
553 // Disregard alpha information in the test
554 pixel_colour = Color.FromArgb(blue.A, pixel_colour.R, pixel_colour.G, pixel_colour.B);
556 Assert.AreEqual (blue, bmp.GetPixel (0, 0));
561 public void DefaultFormat1 ()
563 using (Bitmap bmp = new Bitmap (20, 20)) {
564 Assert.AreEqual (ImageFormat.MemoryBmp, bmp.RawFormat);
569 public void DefaultFormat2 ()
571 string filename = Path.GetTempFileName ();
572 using (Bitmap bmp = new Bitmap (20, 20)) {
576 using (Bitmap other = new Bitmap (filename)) {
577 Assert.AreEqual (ImageFormat.Png, other.RawFormat);
579 File.Delete (filename);