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
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
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.
36 using System.Drawing.Imaging;
37 using NUnit.Framework;
39 using System.Security.Cryptography;
41 using System.Runtime.InteropServices;
42 using System.Security.Permissions;
44 namespace MonoTests.System.Drawing{
47 [SecurityPermission (SecurityAction.Deny, UnmanagedCode = true)]
48 public class TestBitmap {
51 public void Clean() {}
54 public void GetReady()
60 public void TestPixels()
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);
67 Assert.AreEqual (Color.FromArgb(255,128,128,128), color);
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);
74 /* Get the output directory depending on the runtime and location*/
75 public static string getOutSubDir()
79 if (Environment.GetEnvironmentVariable("MSNet")==null)
84 sRslt = Path.GetFullPath (sSub);
86 if (Directory.Exists(sRslt) == false)
87 sRslt = "Test/System.Drawing/" + sSub;
90 if (sRslt[sRslt.Length-1] != '\\' && sRslt[sRslt.Length-1] != '/')
96 /* Get the input directory depending on the runtime*/
97 public static string getInFile(string file)
101 sRslt = Path.GetFullPath (file);
103 if (File.Exists(file)==false)
104 sRslt = "Test/System.Drawing/" + file;
110 public void MakeTransparent()
112 string sInFile = getInFile("bitmaps/maketransparent.bmp");
113 string sOutFile = getOutSubDir() + "transparent.bmp";
115 Bitmap bmp = new Bitmap(sInFile);
117 bmp.MakeTransparent();
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);
129 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
130 string sOutFile = getOutSubDir() + "clone24.bmp";
132 Rectangle rect = new Rectangle(0,0,50,50);
133 Bitmap bmp = new Bitmap(sInFile);
135 Bitmap bmpNew = bmp.Clone (rect, PixelFormat.Format32bppArgb);
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);
142 Assert.AreEqual (colororg0, colornew0);
143 Assert.AreEqual (colororg50, colornew50);
147 public void CloneImage()
149 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
150 Bitmap bmp = new Bitmap(sInFile);
152 Bitmap bmpNew = (Bitmap) bmp.Clone ();
154 Assert.AreEqual (bmp.Width, bmpNew.Width);
155 Assert.AreEqual (bmp.Height, bmpNew.Height);
156 Assert.AreEqual (bmp.PixelFormat, bmpNew.PixelFormat);
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);
168 Assert.AreEqual (1, cnt);
169 Assert.AreEqual (0, active);
173 [ExpectedException (typeof (ArgumentException))]
174 public void FileDoesNotExists ()
176 Bitmap bmp = new Bitmap ("FileDoesNotExists.jpg");
179 static string ByteArrayToString(byte[] arrInput)
182 StringBuilder sOutput = new StringBuilder(arrInput.Length);
183 for (i=0;i < arrInput.Length -1; i++)
185 sOutput.Append(arrInput[i].ToString("X2"));
187 return sOutput.ToString();
191 public string RotateBmp (Bitmap src, RotateFlipType rotate)
193 int witdh = 150, height = 150, index = 0;
194 byte[] pixels = new byte [witdh * height * 3];
200 bmp_rotate = src.Clone (new RectangleF (0,0, witdh, height), PixelFormat.Format32bppArgb);
201 bmp_rotate.RotateFlip (rotate);
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;
210 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
211 return ByteArrayToString (hash);
214 public string RotateIndexedBmp (Bitmap src, RotateFlipType type)
218 switch (src.PixelFormat)
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;
224 default: throw new Exception("Cannot pass a bitmap of format " + src.PixelFormat + " to RotateIndexedBmp");
227 Bitmap test = src.Clone () as Bitmap;
229 test.RotateFlip (type);
231 BitmapData data = null;
236 data = test.LockBits (new Rectangle (0, 0, test.Width, test.Height), ImageLockMode.ReadOnly, test.PixelFormat);
238 int scan_size = (data.Width + pixels_per_byte - 1) / pixels_per_byte;
239 pixel_data = new byte[data.Height * scan_size];
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);
252 try { test.UnlockBits(data); } catch {}
254 try { test.Dispose(); } catch {}
258 if (pixel_data == null)
261 byte[] hash = new MD5CryptoServiceProvider().ComputeHash (pixel_data);
262 return ByteArrayToString (hash);
267 Rotate bitmap in diffent ways, and check the result
273 string sInFile = getInFile ("bitmaps/almogaver24bits.bmp");
274 Bitmap bmp = new Bitmap(sInFile);
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));
287 Rotate 1- and 4-bit bitmaps in different ways and check the
288 resulting pixels using MD5
291 public void Rotate1bit4bit()
294 getInFile ("bitmaps/1bit.png"),
295 getInFile ("bitmaps/4bit.png")
298 StringBuilder md5s = new StringBuilder();
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));
305 using (StreamWriter writer = new StreamWriter("/tmp/md5s.txt"))
306 writer.WriteLine(md5s);
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
344 public void LockBmp (PixelFormat fmt, PixelFormat fmtlock, string output,
345 int lwidth , int lheight, ref string hash1, ref string hash2)
347 int width = 100, height = 100, bbps, cur, pos;
348 Bitmap bmp = new Bitmap (width, height, fmt);
349 Graphics gr = Graphics.FromImage (bmp);
352 byte[] btv = new byte[1];
353 int y, x, len = width * height * 4, index = 0;
354 byte[] pixels = new byte [len];
357 bbps = Image.GetPixelFormatSize (fmt);
359 Pen p = new Pen (Color.FromArgb (255, 100, 200, 250), 2);
360 gr.DrawRectangle(p, 1.0F, 1.0F, 80.0F, 80.0F);
362 BitmapData bd = bmp.LockBits (new Rectangle (0, 0, lwidth, lheight), ImageLockMode.ReadOnly, fmtlock);
364 pos = bd.Scan0.ToInt32();
365 for (y = 0; y < bd.Height; y++) {
366 for (x = 0; x < bd.Width; x++) {
369 for (int bt =0; bt < bbps/8; bt++, index++) {
374 Marshal.Copy ((IntPtr)cur, btv, 0, 1);
375 pixels[index] = btv[0];
377 /* Make change of all the colours = 250 to 10*/
380 Marshal.Copy (btv, 0, (IntPtr)cur, 1);
386 for (int i = index; i < len; i++)
389 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
392 hash1 = ByteArrayToString (hash);
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;
402 hash = new MD5CryptoServiceProvider().ComputeHash (pixels);
403 hash2 = ByteArrayToString (hash);
405 /*bmp.Save (output, ImageFormat.Bmp);*/
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
413 public void LockBitmap ()
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);
423 LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 100, 100, ref hash, ref hashchg);
424 Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);
425 Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);
427 LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 100, 100, ref hash, ref hashchg);
428 Assert.AreEqual ("AF5BFD4E98D6708FF4C9982CC9C68F", hash);
429 Assert.AreEqual ("BBEE27DC85563CB58EE11E8951230F", hashchg);
431 LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 100, 100, ref hash, ref hashchg);
432 Assert.AreEqual ("A8A071D0B3A3743905B4E193A62769", hash);
433 Assert.AreEqual ("EEE846FA8F892339C64082DFF775CF", hashchg);
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);
440 LockBmp (PixelFormat.Format32bppPArgb, PixelFormat.Format32bppPArgb, "output32bppPArgb.bmp", 50, 50, ref hash, ref hashchg);
441 Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);
442 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
444 LockBmp (PixelFormat.Format32bppRgb, PixelFormat.Format32bppRgb, "output32bppRgb.bmp", 50, 50, ref hash, ref hashchg);
445 Assert.AreEqual ("C361FBFD82A4F3C278605AE9EC5385", hash);
446 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);
448 LockBmp (PixelFormat.Format24bppRgb, PixelFormat.Format24bppRgb, "output24bppRgb.bmp", 50, 50, ref hash, ref hashchg);
449 Assert.AreEqual ("FFE86628478591D1A1EB30E894C34F", hash);
450 Assert.AreEqual ("8C2C04B361E1D5875EE8ACF5073F4E", hashchg);