, ben piksel veri Bitmap klonlanmış örneği arasında paylaşılan olacağını endişelendim. Bu yüzden Bitmap.Clone()
ve new Bitmap()
arasındaki farkları bulmak için bazı testler yapılır.
Bitmap.Clone()
kilitli orijinal dosyayı korur: original.Dispose()
sonra dosyayı kilidini açacak yerine new Bitmap(original)
kullanma
Bitmap original = new Bitmap("Test.jpg");
Bitmap clone = (Bitmap) original.Clone();
original.Dispose();
File.Delete("Test.jpg"); // Will throw System.IO.IOException
ve özel durum olmayacaktır. (.Clone()
ile oluşturulan) klonunun modifiye edilmesi Graphics
sınıfını kullanma orijinal değiştirmezler:
Bitmap original = new Bitmap("Test.jpg");
Bitmap clone = (Bitmap) original.Clone();
BitmapData odata = original.LockBits(new Rectangle(0, 0, original.Width, original.Height), ImageLockMode.ReadWrite, original.PixelFormat);
BitmapData cdata = clone.LockBits(new Rectangle(0, 0, clone.Width, clone.Height), ImageLockMode.ReadWrite, clone.PixelFormat);
Assert.AreNotEqual(odata.Scan0, cdata.Scan0);
The:
Bitmap original = new Bitmap("Test.jpg");
Bitmap clone = (Bitmap) original.Clone();
Graphics gfx = Graphics.FromImage(clone);
gfx.Clear(Brushes.Magenta);
Color c = original.GetPixel(0, 0); // Will not equal Magenta unless present in the original
Benzer şekilde, LockBits
yöntemi kullanılarak özgün ve klon için farklı bellek bloğu elde edilir sonuçlar object ICloneable.Clone()
ve Bitmap Bitmap.Clone(Rectangle, PixelFormat)
ikisi ile aynıdır.
Daha sonra, aşağıdaki kodu kullanarak bazı basit karşılaştırmaları denedim. listedeki 50 kopya saklama
6.2 saniye sürdü ve 1.7 GB bellek kullanımı (orijinal görüntü 24 bpp ve 3456 x 2400 piksel = 25 MB) ile sonuçlanmıştır:
Bitmap original = new Bitmap("Test.jpg");
long mem1 = Process.GetCurrentProcess().PrivateMemorySize64;
Stopwatch timer = Stopwatch.StartNew();
List<Bitmap> list = new List<Bitmap>();
Random rnd = new Random();
for(int i = 0; i < 50; i++)
{
list.Add(new Bitmap(original));
}
long mem2 = Process.GetCurrentProcess().PrivateMemorySize64;
Debug.WriteLine("ElapsedMilliseconds: " + timer.ElapsedMilliseconds);
Debug.WriteLine("PrivateMemorySize64: " + (mem2 - mem1));
bunun yerine saklamak Clone()
kullanılması Listede 0,7 saniyede 1 000 000 kopya ve 0,9 GB. Beklendiği gibi, Clone()
new Bitmap()
çok karşılaştırıldığında hafif geçerli: Clone()
yöntemi kullanılarak
for(int i = 0; i < 1000000; i++)
{
list.Add((Bitmap) original.Clone());
}
Klonlar kopya üzerinde yazma vardır. Burada bir rastgele pikseli klondaki rastgele bir renge değiştiriyorum.Sadece görüntüden bir Graphics
nesnesi oluşturarak
Random rnd = new Random();
for(int i = 0; i < 50; i++)
{
Bitmap clone = (Bitmap) original.Clone();
clone.SetPixel(rnd.Next(clone.Width), rnd.Next(clone.Height), Color.FromArgb(rnd.Next(0x1000000)));
list.Add(clone);
}
kopyasını tetiklemez: Şimdi geri 7.8 saniye ve 1.6 GB çünkü bu işlem, orijinal tüm piksel verilerin bir kopyasını tetikler gözükmektedir
for(int i = 0; i < 50; i++)
{
Bitmap clone = (Bitmap) original.Clone();
Graphics.FromImage(clone).Dispose();
list.Add(clone);
}
kopyayı tetiklemek için Graphics
nesnesini kullanarak bir şey çizmek gerekir. Son olarak, diğer taraftan LockBits
kullanarak ImageLockMode.ReadOnly
belirtilmiş olsa bile verileri kopyalar:
for(int i = 0; i < 50; i++)
{
Bitmap clone = (Bitmap) original.Clone();
BitmapData data = clone.LockBits(new Rectangle(0, 0, clone.Width, clone.Height), ImageLockMode.ReadOnly, clone.PixelFormat);
clone.UnlockBits(data);
list.Add(clone);
}
ben okuyordum dosyası 1 bitlik piksel başına TIFF dosya olan bir dava vardı. '(Bitmap) A.Clone()', piksel başına 1 bit iken, "yeni Bitmap (A)", piksel bitmap başına 32 bit döndürdü. Resmi daha sonra e-postayla göndermek için PDF'ye yerleştirdiğimden, görüntüyü 1 bitde tutmak önemliydi. @Aelios @HansPassant – gmlobdell