पिछले उत्तरों को पढ़ते हुए, मुझे चिंता हो गई कि पिक्सेल डेटा बिटमैप के क्लोन उदाहरणों के बीच साझा किया जाएगा। इसलिए मैंने Bitmap.Clone()
और new Bitmap()
के बीच अंतर जानने के लिए कुछ परीक्षण किए।
Bitmap.Clone()
बंद कर दिया मूल फ़ाइल रखता है:
Bitmap original = new Bitmap("Test.jpg");
Bitmap clone = (Bitmap) original.Clone();
original.Dispose();
File.Delete("Test.jpg"); // Will throw System.IO.IOException
new Bitmap(original)
का उपयोग बजाय original.Dispose()
के बाद फ़ाइल अनलॉक हो जाएगा, और अपवाद उत्पन्न नहीं किया जाएगा। क्लोन (.Clone()
के साथ बनाया) को संशोधित करने के Graphics
वर्ग का उपयोग करते हुए मूल में बदलाव नहीं करेगी:
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);
:
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
इसी तरह, LockBits
पद्धति का उपयोग करके मूल और क्लोन के लिए अलग स्मृति ब्लॉक पैदावार परिणाम object ICloneable.Clone()
और Bitmap Bitmap.Clone(Rectangle, PixelFormat)
दोनों के साथ समान हैं।
अगला, मैंने निम्नलिखित कोड का उपयोग करके कुछ सरल मानकों का प्रयास किया।
सूची में 50 प्रतियां भंडारण 6.2 सेकंड लिया और परिणामस्वरूप 1.7 जीबी मेमोरी उपयोग में (मूल छवि 24 bpp और 3456 x 2400 पिक्सल = 25 MB):
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));
Clone()
का उपयोग करने के बजाय मैं संग्रहीत कर सकती है 0.7 सेकंड के दौरान सूची में 1 000 000 प्रतियां और 0.9 जीबी का उपयोग कर। जैसी उम्मीद थी, Clone()
बहुत new Bitmap()
की तुलना में हल्के वजन है:
for(int i = 0; i < 1000000; i++)
{
list.Add((Bitmap) original.Clone());
}
Clone()
पद्धति का उपयोग करके क्लोन कॉपी-ऑन-राइट कर रहे हैं। यहां मैं क्लोन पर एक यादृच्छिक रंग में एक यादृच्छिक पिक्सेल बदलता हूं।इस आपरेशन, मूल से सभी पिक्सेल डेटा की एक प्रतिलिपि को गति प्रदान करने लगता है क्योंकि अब हम 7.8 सेकंड और 1.6 जीबी में वापस आ गए हैं:
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);
}
बस छवि से एक Graphics
वस्तु बनाने की नकल ट्रिगर नहीं करेगा:
for(int i = 0; i < 50; i++)
{
Bitmap clone = (Bitmap) original.Clone();
Graphics.FromImage(clone).Dispose();
list.Add(clone);
}
आपको कॉपी को ट्रिगर करने के लिए Graphics
ऑब्जेक्ट का उपयोग करके कुछ आकर्षित करना होगा। अंत में, दूसरे हाथ पर LockBits
का उपयोग कर, डेटा की प्रतिलिपि जाएगा, भले ही ImageLockMode.ReadOnly
निर्दिष्ट किया जाता है:
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);
}
मैं एक मामले में जहां फ़ाइल मैं पढ़ रहा था एक प्रति पिक्सेल 1 बिट TIFF फ़ाइल था। 'नया बिटमैप (ए) '32 बिट प्रति पिक्सेल बिटमैप लौटा, जबकि' (बिटमैप) एक्लोन() 'अभी भी 1 बिट प्रति पिक्सेल था। चूंकि मैं बाद में ईमेलिंग के लिए पीडीएफ में छवि को एम्बेड कर रहा था, इसलिए छवि को 1 बिट पर रखना महत्वपूर्ण था। @ एलीओस @ हंसपैसेंट – gmlobdell